* Arnold Daniels <info@stripped> [2007-09-05 20:44-0400]
> Hi Eric,
>
> First of all let me say that at least one person is enthusiastic (me). I do
> have a few question remarks:
>
> You mentioned about the possibility to add an XQuery parser. But then how
> would you map the data in the storage engines, which is relational data, to
> XQuery? Or are you thinking about a special XML engine? Personally I like
> the way DB2 solves this. You do an pass a value to the XQuery
> SELECT XMLCAST(XMLQUERY(for $i in $t/product/description/category return
> $i' PASSING BY REF T.DESCRIPTION AS "t" RETURNING SEQUENCE) AS
> VARCHAR(128)) FROM xmlproduct AS t
The XQuery portion of your query was
for $i in $t/product/description/category return $i
which leads me to guess a schema where the XPaths represent joins
through tables ala:
SELECT XMLrepresentationOf(something.primaryKey)
FROM something
JOIN Products ON something.product=Products.primaryKey
JOIN Descriptions ON Product.description=Descriptions.primaryKey
JOIN Categories ON Description.Category=Categories.primaryKey
Lots of folks have done XQuery/relational mappings, and I have the
impression they have this sort of mapping. This problem can be viewed
as:
1 How would you represent your relational data in XQuery?
2 How would you query that representation?
Given that approach, you need knowledge of the schema rather than a lot
SQL-like code mapping the XML names and type to SQL terms. That, however,
is if you wish to do everything in XQuery. If you want the outer language
to be SQL, then yes, something like the DB2 name/type mapping is needed.
> This functionality cannot be mimicked by a function, like ExtractValue(),
> because a function can't make the query return more rows than selected.
> Lets say that table had 7 rows with 3 products in the XML per row, the
> query should return 21 record.
Agreed. Violating these restriction semantics would mean you weren't
acutally using XQuery, just something that looked like it.
Aside {
When we started work on SPARQL, we had to prove to ourselves that we
shouldn't use an existing W3C spec, namely XQuery. Some approaches
were suggested and the ones that violated the predicate-as-restriction
rule were dismissed. The remaining ones mostly focused around a
canonical representation in XML. We didnt't find those close enough to
our data model (and consequently they were too verbose) for our liking.
That said, I'm always keen to enable interoperability between query
systems. }
> Here you see however that the XQuery parser isn't choosen to be `the`
> parser because this would be quite useless. Instead the XMLQuery if the
> directive.
Useless to folks who want to use SQL as their main language, but
that's not how the XQuery (or SPARQL) folks see the world. If you
offer someone a standard language, it's most useful to them if they
don't have to do any transformations into another language. Otherwise,
the "standard" query is different on MySQL and on Oracle, or DB2 ...
> I don't know much about SPARQL, but from what I've read the query does map
> well to relational data. However simply choosing the parser based on the
> syntax seems rather confusing. For instance the '?' is also used to insert
> data from a prepared statement. Now when you forget to type a comma, the
> query is suddenly interpreted as SPASQL. Making a change to the
> client/server protocol doesn't seem like the best solution to me as well,
> because that well have a huge impact across the software development world,
> and not in a good way. A simple solution seems to be to just specify it in
> the query:
>
> SPASQL SELECT ?s WHERE { ?s <foo.bar> "hibbyhop";
That's what I originally implemented, but Brian Miezejewski's proposal
was to differentiate parsers based on the protocol. I was fearful of the
work it involved, but looking now, the patch actually isn't so large.
> Both cases require that the parser actually integrates with the current
> (SQL) parser, this is probably a bit harder to implement. Also, this seems
> like a perfect candidate for the INSTALL PLUGIN syntax.
I can imagine a few ways to do this:
== Parser Integration (extend sql_yacc.yy and sql_lex.cc):
Integrating with the SQL parser has a pretty high implementation and
deployment cost. There are currently 285 shift/reduce conflicts in the
grammar and adding a language like XQuery, which has 5 special cases
in the lexer, would make quiet a soup. I'm doing some work with
mechanical grammar recombination in the yacker, but that's kinda
researchy. Another drawback is the likelyhood of collisions on popular
idioms like set foo="bar".
== Parser Encapsulation (add parser state to dispatch other language):
The lexer could have a special state where it expected another
language span and had some lexer rules controlling when that span
would end. For example:
posn | start | end |example
start|!(SELECT|SET|SHOW|...)|rest of query|XQuery for $i ...
any |CALLOUT(%language, ...|balanced ')' |... IN CALLOUT('XQuery', for $i ...
These require query-time transformation of an otherwise standard
language; nice if you see the world through SQL eyes, less so if
you see the world through XQuery or SPARQL eyes and want
platform-independent queries.
Also, this requires that all the THD manipulation done so far when
parsing be compatible with whatever the next parser will do to it. A
relational API that composed query plan would be a pretty cool way to
handle this sort of integration, but that seems a good ways out. (I'd
have a lot of fun working on that, though.)
== Callout function (encapsulate query as a string):
This looks like the
... IN CALLOUT('XQuery', for $i ...
above, except you need quotes around, and quote escaping of, the
foreign query. This is compatible with the User Defined Function
interface. It is simple to implement, but hard to use; same
challenges as above.
== Prefix matching (look for string before calling SQL parser):
This is how I implemented the first SPARQL parser:
if (!strncmp(inBuf, "SPARQL:", 7)) {
lex->ptr = (uchar*)inBuf+7;
sparqlFrob frob(thd, (char**)&lex->ptr);
parse_res = frob.parse();
} else {
parse_res = MYSQLparse((void *)thd);
}
It worked well enough, but required a priori knowledge of all the
possible extension languages and the requirement that they not
conflict with any possible first token in the MySQL SQL grammar.
As described above, this was not a verbatim SPARQL query.
Ulimately, I like the protocol-switched approach as it gives the user
explicit control and means that SPARQL queries on MySQL will be like
SPARQL queries in Jena or any other implementation.
==
> Best regards,
> Arnold
>
>
> Eric Prud'hommeaux wrote:
>> Attached is a dynParser patch to add alternate parsers into mysqld
>> (and a parser that uses this interface). I developed this for the
>> SPASQL project [SPA], but expect folks might want to use it to add
>> parsers for other variants of SQL as well as totally different
>> languages like XQuery and SPARQL.
>> [SPA] http://esw.w3.org/topic/SPASQL
>>
>> The extension works by adding three new request types to the
>> client/server protocol: PARSER1, PARSER2, PARSER3. The API function
>> mysql_send_query takes a fourth parameter in order to send this to the
>> server. On the server side, sql_parse.cc responds to requests for
>> PARSER{1,2,3} by invoking dynamic_parsers[N].initialize->parse().
>> See [SRC] and [DYN] (below) for compilation and execution instructions.
>> [SRC] http://www.w3.org/2005/05/22-SPARQL-MySQL/#srcbuild
>> [DYN] http://www.w3.org/2005/05/22-SPARQL-MySQL/#dynParser
>>
>>
>> A couple notes about protocol compatibility: a stock 5.x client does
>> everything we need except invoke PARSERn requests. This is 'cause I
>> left COM_QUERY where it was, and stuck the user-selected parsers at
>> the end of the enum.
>> /* add-on parsers */
>> COM_PARSER0, /* !!! change to COM_QUERY on next protocol change */
>> COM_PARSER1, COM_PARSER2, COM_PARSER3,
>> The cost is a slight discontinuity in the code for COM_QUERY vs. the
>> other parsers. On the other hand, I haven't made MYSQLparse conform to
>> the user parser API so it requires special code anyways. (I never
>> figured out how to set defaults in set_var so I couldn't gracefully
>> make MYSQLparse the default parser, plus it's dangerous to have the
>> core parser be a shared library, and finally, if you did change
>> parser0 from MYSQLparse to some other parser, you could find yourself
>> with no tested way to talk to mysqld.)
>>
>> COM_PARSER0 is only used as a base for counting parser offsetsd; it is
>> never passed so we could save an enum by assigning it to the previous
>> value:
>>
>> /* add-on parsers */
>> COM_PARSER0 = COM_STMT_FETCH, COM_PARSER1, COM_PARSER2, COM_PARSER3,
>> but it may make sense to move COM_QUERY there instead.
>>
>> Brian and I discussed implementing a stacked parser approach:
>> mysql> add_parser("libsparql", ParserPos_FRONT);
>> mysql> SELECT ?s WHERE { ?s <foo.bar> "hibbyhop";
>> The cost of this is that you can't force any particular parser to
>> handle a particular request (unless you remove_parser and add_parser
>> to get the one you like up front for that query). It would, however,
>> provide a neat extensibility mechanism where 3rd party providers could
>> supply parsers for add-on functionality. I prototyped this a bit in a
>> Dynamic_parser and believe that a Dynamic_parser could provide a
>> parser that stacked other Dynamic_parsers and even target queries at a
>> particular parser if one chose. However, I have not really implemented
>> this.
>>
>> Any feedback will be enthusiastically welcomed. I'm motivated to type
>> madly on this on the off-chance I can get it into the 5.2 release as
>> I have several pharmaceuticals interested in the SPASQL project and
>> am anxious to get them working with the MySQL implementation.
>> ------------------------------------------------------------------------
>>
>> diff -au sql/set_var.cc.orig sql/set_var.cc
>> --- sql/set_var.cc.orig 2007-09-03 19:17:28.000000000 -0400
>> +++ sql/set_var.cc 2007-09-04 17:48:12.000000000 -0400
>> @@ -69,6 +69,10 @@
>> extern ulong ndb_report_thresh_binlog_mem_usage;
>> #endif
>> +/* dynamically-loaded parsers */
>> +#include "dyn_parser.h"
>> +#include <dlfcn.h>
>> +
>> extern CHARSET_INFO *character_set_filesystem;
>> @@ -88,6 +92,8 @@
>> delay_key_write_type_names, NULL
>> };
>> +struct dynamic_parser_info dynamic_parsers[3];
>> +
>> static int sys_check_ftb_syntax(THD *thd, set_var *var);
>> static bool sys_update_ftb_syntax(THD *thd, set_var * var);
>> static void sys_default_ftb_syntax(THD *thd, enum_var_type type);
>> @@ -117,6 +123,11 @@
>> static void fix_max_relay_log_size(THD *thd, enum_var_type type);
>> static void fix_max_connections(THD *thd, enum_var_type type);
>> static int check_max_delayed_threads(THD *thd, set_var *var);
>> +static int sys_check_parser(THD *thd, set_var *var);
>> +static bool sys_update_parserN(THD *thd, set_var * var, uchar parser);
>> +static bool sys_update_parser0(THD *thd, set_var * var);
>> +static bool sys_update_parser1(THD *thd, set_var * var);
>> +static bool sys_update_parser2(THD *thd, set_var * var);
>> static void fix_thd_mem_root(THD *thd, enum_var_type type);
>> static void fix_trans_mem_root(THD *thd, enum_var_type type);
>> static void fix_server_id(THD *thd, enum_var_type type);
>> @@ -348,6 +359,21 @@
>>
>> &SV::optimizer_prune_level);
>> static sys_var_thd_ulong sys_optimizer_search_depth(&vars,
>> "optimizer_search_depth",
>>
>> &SV::optimizer_search_depth);
>> +static sys_var_str sys_dynamic_parser0(&vars,
>> "dynamic_parser1",
>> + sys_check_parser,
>> + sys_update_parser0,
>> + 0,
>> + dynamic_parsers[0].name);
>> +static sys_var_str sys_dynamic_parser1(&vars,
>> "dynamic_parser2",
>> + sys_check_parser,
>> + sys_update_parser1,
>> + 0,
>> + dynamic_parsers[1].name);
>> +static sys_var_str sys_dynamic_parser2(&vars,
>> "dynamic_parser3",
>> + sys_check_parser,
>> + sys_update_parser2,
>> + 0,
>> + dynamic_parsers[2].name);
>> const char *optimizer_use_mrr_names[] = {"auto", "force", "disable",
>> NullS};
>> TYPELIB optimizer_use_mrr_typelib= {
>> @@ -828,6 +854,44 @@
>> sizeof(ft_boolean_syntax)-1);
>> }
>> +static int sys_check_parser(THD *thd, set_var *var)
>> +{
>> + if (thd->security_ctx->master_access & SUPER_ACL) {
>> + void* lib = dlopen(var->value->str_value.ptr(), RTLD_NOW);
>> + if (lib) {
>> + dlclose(lib);
>> + return 0;
>> + }
>> + else
>> + {
>> + char* errstr = dlerror();
>> + my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), errstr); // !!! need new
>> error
>> + return 1;
>> + }
>> + }
>> + else
>> + {
>> + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
>> + return 1;
>> + }
>> +}
>> +
>> +static bool sys_update_parserN(THD *thd, set_var * var, uchar parser)
>> +{
>> + strmake(dynamic_parsers[parser].name, var->value->str_value.c_ptr(),
>> + sizeof(dynamic_parsers[parser].name)-1);
>> + if (dynamic_parsers[parser].handle)
>> + dlclose(dynamic_parsers[parser].handle);
>> + dynamic_parsers[parser].handle = dlopen(dynamic_parsers[parser].name,
>> RTLD_NOW);
>> + dynamic_parsers[parser].initialize =
>> (t_initialize*)dlsym(dynamic_parsers[parser].handle,
>> "_Z10initializeP3THDPPc");
>> + return 0;
>> +}
>> +static bool sys_update_parser0(THD *thd, set_var * var)
>> +{ return sys_update_parserN(thd, var, 0); }
>> +static bool sys_update_parser1(THD *thd, set_var * var)
>> +{ return sys_update_parserN(thd, var, 1); }
>> +static bool sys_update_parser2(THD *thd, set_var * var)
>> +{ return sys_update_parserN(thd, var, 2); }
>> /*
>> If one sets the LOW_PRIORIY UPDATES flag, we also must change the
>> diff -au client/mysqltest.c.orig client/mysqltest.c
>> --- client/mysqltest.c.orig 2007-09-03 19:07:45.000000000 -0400
>> +++ client/mysqltest.c 2007-09-03 14:51:56.000000000 -0400
>> @@ -500,7 +500,7 @@
>> struct st_connection *cn= (struct st_connection*)arg;
>> mysql_thread_init();
>> - VOID(mysql_send_query(&cn->mysql, cn->cur_query,
> cn->cur_query_len));
>> + VOID(mysql_send_query(&cn->mysql, cn->cur_query,
> cn->cur_query_len,
>> 0));
>> mysql_thread_end();
>> pthread_mutex_lock(&cn->mutex);
>> @@ -517,7 +517,7 @@
>> pthread_t tid;
>> if (flags & QUERY_REAP_FLAG)
>> - return mysql_send_query(&cn->mysql, q, q_len);
>> + return mysql_send_query(&cn->mysql, q, q_len, 0);
>> if (pthread_mutex_init(&cn->mutex, NULL) ||
>> pthread_cond_init(&cn->cond, NULL))
>> @@ -534,7 +534,7 @@
>> #else /*EMBEDDED_LIBRARY*/
>> -#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q,
>
>> q_len)
>> +#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q,
>> q_len, 0)
>> #endif /*EMBEDDED_LIBRARY*/
>> diff -au client/mysql.cc.orig client/mysql.cc
>> --- client/mysql.cc.orig 2007-09-03 19:07:45.000000000 -0400
>> +++ client/mysql.cc 2007-09-03 14:52:29.000000000 -0400
>> @@ -1828,7 +1828,17 @@
>> for (uint retry=0;; retry++)
>> {
>> int error;
>> - if (!mysql_real_query(&mysql,buf,length))
>> + uchar parser = 0;
>> + if (!strncmp(buf, "parser", 6) && buf[6] != 0 && buf[7] ==
> ':') {
>> + parser = buf[6]-'0';
>> + if (parser > 0 || parser < PARSERS) {
>> + buf += 8;
>> + length -= 8;
>> + } else {
>> + // !!! error: invalid parser
>> + }
>> + }
>> + if (!mysql_parser_query(&mysql,buf,length,parser))
>> return 0;
>> error= put_error(&mysql);
>> if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
>> diff -au sql/sql_parse.cc.orig sql/sql_parse.cc
>> --- sql/sql_parse.cc.orig 2007-08-26 04:36:04.000000000 -0400
>> +++ sql/sql_parse.cc 2007-09-05 09:54:19.000000000 -0400
>> @@ -28,6 +28,10 @@
>> #include "events.h"
>> #include "sql_trigger.h"
>> +/* dynamically-loaded parsers */
>> +#include "dyn_parser.h"
>> +#include <dlfcn.h>
>> +
>> /**
>> @defgroup Runtime_Environment Runtime Environment
>> @{
>> @@ -80,6 +84,10 @@
>> { C_STRING_WITH_LEN("Set option") },
>> { C_STRING_WITH_LEN("Fetch") },
>> { C_STRING_WITH_LEN("Daemon") },
>> + { C_STRING_WITH_LEN("Parser 0") },
>> + { C_STRING_WITH_LEN("Parser 1") },
>> + { C_STRING_WITH_LEN("Parser 2") },
>> + { C_STRING_WITH_LEN("Parser 3") },
>> { C_STRING_WITH_LEN("Error") } // Last command number
>> };
>> @@ -431,7 +439,7 @@
>> */
>> thd->query_id=next_query_id();
>> thd->set_time();
>> - mysql_parse(thd, thd->query, length, & found_semicolon);
>> + mysql_parse(thd, thd->query, length, & found_semicolon, 0);
>> close_thread_tables(thd); // Free tables
>> if (thd->is_fatal_error)
>> @@ -842,6 +850,9 @@
>> break;
>> }
>> case COM_QUERY:
>> + case COM_PARSER1:
>> + case COM_PARSER2:
>> + case COM_PARSER3:
>> {
>> if (alloc_query(thd, packet, packet_length))
>> break; // fatal error is set
>> @@ -856,7 +867,8 @@
>> if (!(specialflag & SPECIAL_NO_PRIOR))
>> my_pthread_setprio(pthread_self(),QUERY_PRIOR);
>> - mysql_parse(thd, thd->query, thd->query_length, &
> found_semicolon);
>> + int parser = command == COM_QUERY ? 0 : command - COM_PARSER0;
>> + mysql_parse(thd, thd->query, thd->query_length, & found_semicolon,
>
>> parser);
>> while (!thd->killed && found_semicolon &&
> !thd->net.report_error)
>> {
>> @@ -885,7 +897,7 @@
>> thd->set_time(); /* Reset the query start time. */
>> /* TODO: set thd->lex->sql_command to SQLCOM_END here */
>> VOID(pthread_mutex_unlock(&LOCK_thread_count));
>> - mysql_parse(thd, next_packet, length, & found_semicolon);
>> + mysql_parse(thd, next_packet, length, & found_semicolon, parser);
>> }
>> if (!(specialflag & SPECIAL_NO_PRIOR))
>> @@ -5302,7 +5314,7 @@
>> */
>> void mysql_parse(THD *thd, const char *inBuf, uint length,
>> - const char ** found_semicolon)
>> + const char ** found_semicolon, uchar parser)
>> {
>> DBUG_ENTER("mysql_parse");
>> @@ -5336,7 +5348,24 @@
>> Lex_input_stream lip(thd, inBuf, length);
>> - bool err= parse_sql(thd, &lip, NULL);
>> + bool err;
>> + if (parser == 0) {
>> + err= parse_sql(thd, &lip, NULL);
>> + } else {
>> + struct dynamic_parser_info* p = &dynamic_parsers[parser-1];
>> + if (p->initialize) {
>> + char* space = (char*)malloc(strlen(lip.get_ptr())+1);
>> + strcpy(space, lip.get_ptr());
>> +
>> + Dynamic_parser* parser = p->initialize(thd, &space);
>> + err= parser->parse();
>> + delete parser;
>> + } else {
>> + my_error(ER_WRONG_DB_NAME ,MYF(0), "parser not loaded");//!!!need error
>> + err= 1;
>> + }
>> + }
>> +
>> *found_semicolon= lip.found_semicolon;
>> if (!err)
>> @@ -7160,6 +7189,14 @@
>> return err_status;
>> }
>> +
>> +/* fill Dynamic_parser's vtable with dummy functions */
>> +int Dynamic_parser::parse() {
>> +}
>> +
>> +Dynamic_parser::~Dynamic_parser() {
>> +}
>> +
>> /**
>> @} (end of group Runtime_Environment)
>> */
>> diff -au sql-common/client.c.orig sql-common/client.c
>> --- sql-common/client.c.orig 2007-09-03 19:07:45.000000000 -0400
>> +++ sql-common/client.c 2007-09-05 07:54:48.000000000 -0400
>> @@ -2757,7 +2757,8 @@
>> */
>> int STDCALL
>> -mysql_send_query(MYSQL* mysql, const char* query, ulong length)
>> +mysql_send_query(MYSQL* mysql, const char* query, + ulong length,
>> unsigned char parser)
>> {
>> DBUG_ENTER("mysql_send_query");
>> DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d",
>> @@ -2777,7 +2778,8 @@
>> mysql->last_used_con = mysql;
>> #endif
>> - DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length,
>> 1));
>> + enum enum_server_command command = parser ? COM_PARSER0 + parser :
>> COM_QUERY;
>> + DBUG_RETURN(simple_command(mysql, command, (uchar*) query, length, 1));
>> }
>> @@ -2788,7 +2790,20 @@
>> DBUG_PRINT("enter",("handle: 0x%lx", (long) mysql));
>> DBUG_PRINT("query",("Query = '%-.4096s'",query));
>> - if (mysql_send_query(mysql,query,length))
>> + if (mysql_send_query(mysql,query,length,0))
>> + DBUG_RETURN(1);
>> + DBUG_RETURN((int) (*mysql->methods->read_query_result)(mysql));
>> +}
>> +
>> +
>> +int STDCALL
>> +mysql_parser_query(MYSQL *mysql, const char *query, ulong length, uchar
>> parser)
>> +{
>> + DBUG_ENTER("mysql_real_query");
>> + DBUG_PRINT("enter",("handle: 0x%lx", (long) mysql));
>> + DBUG_PRINT("query",("Query = '%-.4096s'",query));
>> +
>> + if (mysql_send_query(mysql,query,length,parser))
>> DBUG_RETURN(1);
>> DBUG_RETURN((int) (*mysql->methods->read_query_result)(mysql));
>> }
>> diff -au sql/slave.cc.orig sql/slave.cc
>> diff -au sql/log_event.cc.orig sql/log_event.cc
>> --- sql/log_event.cc.orig 2007-09-03 19:07:45.000000000 -0400
>> +++ sql/log_event.cc 2007-09-03 14:53:12.000000000 -0400
>> @@ -2083,7 +2083,7 @@
>> /* Execute the query (note that we bypass
>> dispatch_command()) */
>> const char* found_semicolon= NULL;
>> - mysql_parse(thd, thd->query, thd->query_length,
> &found_semicolon);
>> + mysql_parse(thd, thd->query, thd->query_length,
> &found_semicolon,
>> 0);
>> log_slow_statement(thd);
>> }
>> else
>> diff -au sql/mysql_priv.h.orig sql/mysql_priv.h
>> --- sql/mysql_priv.h.orig 2007-08-26 18:38:30.000000000 -0400
>> +++ sql/mysql_priv.h 2007-09-03 14:53:51.000000000 -0400
>> @@ -970,7 +970,7 @@
>> bool force_switch);
>> void mysql_parse(THD *thd, const char *inBuf, uint length,
>> - const char ** semicolon);
>> + const char ** semicolon, uchar parser);
>> bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
>> bool is_update_query(enum enum_sql_command command);
>> diff -au include/mysql_com.h.orig include/mysql_com.h
>> --- include/mysql_com.h.orig 2007-08-25 15:13:27.000000000 -0400
>> +++ include/mysql_com.h 2007-09-03 14:54:03.000000000 -0400
>> @@ -60,6 +60,7 @@
>> servers won't be able to handle them as 'unsupported'.
>> */
>> +#define PARSERS 3 // c.f. COM_PARSER1, COM_PARSER2, COM_PARSER3 below
>> enum enum_server_command
>> {
>> COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
>> @@ -69,6 +70,11 @@
>> COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
>> COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA,
>> COM_STMT_CLOSE,
>> COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON,
>> +
>> + /* add-on parsers */
>> + COM_PARSER0, /* !!! change to COM_QUERY on next protocol change */
>> + COM_PARSER1, COM_PARSER2, COM_PARSER3, +
>> /* don't forget to update const char *command_name[] in sql_parse.cc */
>> /* Must be last */
>> diff -au include/mysql.h.orig include/mysql.h
>> --- include/mysql.h.orig 2007-09-03 19:07:45.000000000 -0400
>> +++ include/mysql.h 2007-09-03 14:54:03.000000000 -0400
>> @@ -446,9 +446,13 @@
>> int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
>> int STDCALL mysql_query(MYSQL *mysql, const char *q);
>> int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
>> - unsigned long length);
>> + unsigned long length, + unsigned char parser);
>> int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
>> - unsigned long length);
>> + unsigned long length);
>> +int STDCALL mysql_parser_query(MYSQL *mysql, const char *q,
>> + unsigned long length,
>> + unsigned char parser);
>> MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
>> MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql);
>> diff -au include/dyn_parser.h.orig include/dyn_parser.h
>> --- include/dyn_parser.h.orig 2007-09-03 19:10:02.000000000 -0400
>> +++ include/dyn_parser.h 2007-09-03 19:09:52.000000000 -0400
>> @@ -0,0 +1,33 @@
>> +#ifndef _dyn_parser_h
>> +#define _dyn_parser_h
>> +/*-- use only from C++
>> + #ifdef __cplusplus
>> + extern "C" {
>> + #endif
>> +*/
>> +
>> +class Dynamic_parser {
>> +
>> +public:
>> + Dynamic_parser(THD *thd, char** ptr) {
>> + this->thd= thd;
>> + }
>> + virtual ~Dynamic_parser();
>> + virtual int parse();
>> +
>> + THD *thd;
>> +};
>> +extern "C" {
>> + typedef Dynamic_parser* t_initialize(THD *, char **);
>> +}
>> +
>> +struct dynamic_parser_info {
>> + char name[FN_REFLEN];
>> + void* handle;
>> + t_initialize* initialize;
>> + // Dynamic_parser* (*initialize)(THD *, char **);
>> +};
>> +extern struct dynamic_parser_info dynamic_parsers[];
>> +
>> +#endif /* _dyn_parser_h */
>> +
>> diff -au sql/backup/meta_backup.cc.orig sql/backup/meta_backup.cc
>> --- sql/backup/meta_backup.cc.orig 2007-09-03 21:55:06.000000000 -0400
>> +++ sql/backup/meta_backup.cc 2007-09-03 21:55:43.000000000 -0400
>> @@ -361,7 +361,7 @@
>> pthread_mutex_unlock(&::LOCK_thread_count);
>> const char *ptr;
>> - ::mysql_parse(thd,thd->query,thd->query_length,&ptr);
>> + ::mysql_parse(thd,thd->query,thd->query_length,&ptr,0);
>> thd->net.vio= save_vio;
>> diff -au sql/ha_ndbcluster_binlog.cc.orig sql/ha_ndbcluster_binlog.cc
>> --- sql/ha_ndbcluster_binlog.cc.orig 2007-09-03 21:56:23.000000000 -0400
>> +++ sql/ha_ndbcluster_binlog.cc 2007-09-03 21:56:28.000000000 -0400
>> @@ -277,7 +277,7 @@
>> thd->options&= ~OPTION_BIN_LOG;
>> DBUG_PRINT("query", ("%s", thd->query));
>> - mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
>> + mysql_parse(thd, thd->query, thd->query_length, &found_semicolon,
> 0);
>> if (no_print_error && thd->query_error)
>> {
>> ------------------------------------------------------------------------
>>
>> %{
>> #define YY_sparqlParser_STYPE yy_sparqlParser_stype
>> /* $Id: sparqlParser.yy,v 1.9 2007/09/05 18:40:30 eric Exp $
>>
>> TODO:
>> research pre-existing var.jt in conjunction with trump
>>
>> OUTLINE:
>>
>> Some SPARQL graph pattern opperations correspond to SQL subselects. These
>> create
>> a new BindingContext, which keeps track of looks for table alias re-use
>> opportunities. These occur in a given binding context where more than one
>> subject/predicate pair is in the same table. For instance, both (?s,
>> T1.p1) and
>> (?s, T1.p2) both map to the alias T1_0. (Ohterwise, you get needless joins
>> like
>> FROM T1 AS T1_0 JOIN T1 AS T1_1 ON T1_0.id=T1_1.id
>> WHERE T1_0.p1=o1 AND T1_1.p1=o2
>>
>> sparqlFrob::object(subject, predicate, object)
>>
>> */
>> %}
>> %name sparqlParser
>> %define LSP_NEEDED
>> %define ERROR_BODY =0
>> %define LEX_BODY =0
>> %header{
>> #include <iostream>
>> #include <string>
>> using namespace std;
>> #undef yyFlexLexer
>> #define yyFlexLexer sparqlFlexLexer
>>
>> #ifndef FLEXFIX
>> #define FLEXFIX YY_sparqlParser_STYPE *val
>> #define FLEXFIX2 val
>> #endif
>>
>> #define MYSQL_YACC
>> #define YYINITDEPTH 100
>> #define YYMAXDEPTH 3200 /* Because of 64K stack */
>> #include "mysql_priv.h"
>> #include "slave.h"
>> #include "lex_symbol.h"
>> #include "item_create.h"
>> #include "sp_head.h"
>> #include "sp_pcontext.h"
>> #include "sp_rcontext.h"
>> #include "sp.h"
>> #include <myisam.h>
>> #include <myisammrg.h>
>>
>> #include "sparqlFrob.h"
>> #define YY_sparqlParser_PARSE_PARAM sparqlFrob *yySparqlFrob
>>
>> #define PLS_REPORT "Please report this bug, along with the query that
>> triggered it."
>>
>> static char * Iso8601formatStr = "%Y-%m-%dT%H:%i:%sZ";
>> //DATE_TIME_FORMAT Iso8601_format = {Iso8601formatStr,
>> strlen(Iso8601formatStr)};
>>
>> extern String Global_string; // call test->print(&Global_string); p
>> Global_string.c_ptr(); call Global_string.free()
>>
>> /* DEBUGGING/DEVELOPMENT
>> * aggregates a string representing the parsed input.
>> */
>> class Buf {
>> protected:
>> char* data;
>> int len;
>> public:
>> Buf() {
>> len = 0;
>> data = 0;
>> }
>> Buf(char *str);
>> Buf(int count, ...);
>> ~Buf() {
>> if (data) delete[] data;
>> }
>> char *str() {return data;}
>> };
>>
>>
>> /* forward class declarations */
>> class BindingContext;
>>
>>
>> /* static function declarations */
>> static const char* scan_string(THD *thd, LEX_STRING *lex_string,
>> const char *start, const char *end, const char look_for);
>>
>>
>> /* Item_POS: overload the mysql Item object for all the SPARQL parts
>> * of speach (URIs, bNodes, variables, and various forms of literal).
>> *
>> * Item overloads: bind_field
>> */
>> class Item_POS
>> {
>> protected:
>> Item *item;
>> public:
>> Item_POS (Item* item_arg) {item = item_arg;}
>> virtual ~Item_POS () {}
>> virtual void bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt) =
>> 0;
>> virtual bool is_URI () {return false;}
>> virtual bool is_variable () {return false;}
>> virtual bool is_blank_node () {return false;}
>> virtual bool is_string () {return false;}
>> Item* get_item () {return item;} // OK 'cause ALL Item_POS's are Items.
>> virtual void print(String *str)= 0;
>> };
>>
>>
>> class Item_URI : public Item_field, public Item_POS
>> {
>> protected:
>> LEX_STRING table;
>> LEX_STRING field;
>> LEX_STRING value;
>>
>> public:
>> Item_URI(Name_resolution_context *context_arg, LEX_STRING uri, THD
>> *thd);
>> virtual void bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt);
>> virtual bool is_URI () {return true;}
>> LEX_STRING get_table () {return table;}
>> LEX_STRING get_field () {return field;}
>> LEX_STRING get_value () {return value;}
>> void print(String *str);
>> };
>> extern Item_URI *XSD_integer;
>> extern Item_URI *XSD_float;
>> extern Item_URI *XSD_decimal;
>>
>>
>> /* Item_variable: represent SPARQL variable.
>> *
>> * includes the status of a variable's use in the current JOIN. A variable
>> in
>> * a nested JOIN is different from a variable in an outer context (the
>> * UnionGraphContext::close handles the correlation
>> (U0.foo=oldTable.oldField).
>> *
>> * Item_variable has the same virtual functions as an Item, but is never
>> * added to the SQL compile tree (for instance, in the form of a table
>> * constraint or a select item).
>> */
>> class Item_variable : public Item_field, public Item_POS
>> {
>> private:
>> Name_resolution_context *nr_context;
>> GraphContext *gc;
>> bool bound;
>> bool primary_key;
>> TABLE_LIST *jt;
>> Item_variable *outer;
>> sparqlFrob *frob;
>> const char *real_table_name;
>> int ref_count;
>> const char* get_primary_key () {return
>> frob->get_primary_key(real_table_name);}
>> Item* make_Item_field(Name_resolution_context *context_arg,
>> const char *db_arg, const char *table_name_arg,
>> const char *field_name_arg, const char* real_table_name);
>>
>> public:
>> Item_variable(Name_resolution_context *context_arg, const char
>> *variable_name, Item_variable *outer_arg, sparqlFrob *frob_arg, int
>> ref_count_arg);
>>
>> /* Item_field Virtual Overloads:
>> * Item_variable behaves as as an Item_result_field when the variable
>> * identifies a primary key and as an Item_field the rest of the time.
>> * These methods produce a URI when the constructed from the primary
>> * key field name and value.
>> */
>> void make_field(Send_field *tmp_field);
>> virtual bool fix_fields(THD *, Item **);
>> virtual bool send(Protocol *protocol, String *buffer);
>>
>> /* Item_POS Virtual Overloads:
>> *
>> */
>> virtual void bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt);
>> virtual bool is_variable () {return true;}
>>
>> /* SparqlFrob interface */
>> bool same_variable (const char* variable_name) {
>> return !strcmp(orig_field_name, variable_name);
>> }
>> bool outer_has_no_refs () {return outer ? outer->ref_count == 0 : true;}
>> static Item_variable* match_var_in_list (List<Item_variable>
>> *p_item_variables, const char *var);
>>
>> /* BindingContext interface */
>> void add_ref_count (int ref_count_arg) {ref_count+= ref_count_arg;}
>> Item* get_null_item();
>>
>> /* debugging */
>> void print(String *str);
>> };
>>
>>
>> /* Item_blank_node: represent SPARQL bNode.
>> */
>> class Item_blank_node : public Item_variable
>> {
>> public:
>> Item_blank_node (Name_resolution_context *context_arg, const char
>> *node_name, sparqlFrob *frob_arg) : Item_variable(context_arg,
>> node_name, NULL, frob_arg, 0) {}
>> virtual bool is_blank_node () {return true;}
>> void print(String *str);
>> };
>>
>>
>> /* Item_literal_string: represent SPARQL xsd:string typed literal.
>> */
>> class Item_literal_string : public Item_string, public Item_POS
>> {
>> private:
>> Item_POS *lang_or_datatype;
>> public:
>> Item_literal_string (LEX_STRING string, Item_POS
>> *lang_or_datatype, CHARSET_INFO *charset) : Item_string(string.str,
>> string.length, charset), Item_POS(this) {
>> this->lang_or_datatype = lang_or_datatype;
>> }
>> virtual void bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt);
>> virtual bool is_string () {return true;}
>> Item_POS* get_language_or_datatype () {
>> return lang_or_datatype;
>> }
>> Item_URI* get_datatype () {
>> return lang_or_datatype && lang_or_datatype->is_URI() ?
>> (Item_URI*)lang_or_datatype : NULL;
>> }
>> Item_literal_string* get_language () {
>> return lang_or_datatype && lang_or_datatype->is_string() ?
>> (Item_literal_string*)lang_or_datatype : NULL;
>> }
>> void print(String *str);
>> };
>>
>>
>> /* Item_literal_int: represent SPARQL xsd:integer typed literal.
>> */
>> class Item_literal_int : public Item_int, public Item_POS
>> {
>> public:
>> Item_literal_int (LEX_STRING string, Item_POS *lang_or_datatype,
>> CHARSET_INFO *charset) : Item_int(string.str), Item_POS(this) {}
>> virtual void bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt);
>> virtual bool is_string () {return false;}
>> Item_URI* get_datatype () {return XSD_integer;}
>> Item_literal_string* get_language () {return NULL;}
>> void print(String *str);
>> };
>>
>>
>> /* Item_literal_decimal: represent SPARQL xsd:decimal typed literal.
>> */
>> class Item_literal_decimal : public Item_decimal, public Item_POS
>> {
>> public:
>> Item_literal_decimal (LEX_STRING string, Item_POS *lang_or_datatype,
>> CHARSET_INFO *charset) : Item_decimal(string.str, string.length,
>> charset), Item_POS(this) {}
>> virtual void bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt);
>> virtual bool is_string () {return false;}
>> Item_URI* get_datatype () {return XSD_decimal;}
>> Item_literal_string* get_language () {return NULL;}
>> void print(String *str);
>> };
>>
>>
>> /* Item_literal_float: represent SPARQL xsd:float typed literal.
>> */
>> class Item_literal_float : public Item_float, public Item_POS
>> {
>> public:
>> Item_literal_float (LEX_STRING string, Item_POS *lang_or_datatype,
>> CHARSET_INFO *charset) : Item_float(string.str, string.length),
>> Item_POS(this) {}
>> virtual void bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt);
>> virtual bool is_string () {return false;}
>> Item_URI* get_datatype () {return XSD_float;}
>> Item_literal_string* get_language() {return NULL;}
>> void print(String *str);
>> };
>>
>>
>> /* Item_primary_key_field: reference to an Item_field that is a primary
>> key.
>> * Used to create foreign key/primary key constraints on joins.
>> */
>> class Item_primary_key_field : public Item_field
>> {
>> protected:
>> sparqlFrob *frob;
>> const char* real_table_name;
>> public:
>> Item_primary_key_field(Name_resolution_context *context_arg,
>> const char *db_arg, const char *table_name_arg, sparqlFrob
>> *frob_arg, const char* real_table_name_arg);
>> virtual bool fix_fields(THD *, Item **);
>> };
>>
>>
>> #if 0
>> /* Item_func_call: not implemented
>> */
>> class Item_func_call : public Item_POS
>> {
>> protected:
>> Item_POS* name;
>> List<Item>* args;
>> public:
>> Item_func_call (Name_resolution_context *context_arg, Item_POS*
>> name, List<Item>* args) :
>> Item_POS(context_arg, "<Item_func_call>") {
>> this->name = name;
>> this->args = args;
>> }
>> ~Item_func_call() {}
>> void bind_field (const char *table_name, const char *alias, const
>> char *field_name_arg, bool trump, T HD *thd, TABLE_LIST *jt) {}
>> bool fix_fields(THD *, Item **);
>> };
>> #endif
>>
>>
>> /* Alias_info: aliases for a table, indexed by subject.
>> * If it's not in subjects, you need a new alias.
>> */
>> class Alias_info {
>> friend class GraphContext;
>> private:
>> LEX_STRING table;
>> List<Item_POS> subjects;
>> public:
>> Alias_info(LEX_STRING table) {
>> this->table = table;
>> }
>> bool same_table(LEX_STRING table) {
>> return !strcmp(this->table.str, table.str);
>> }
>> };
>>
>>
>> /* BindingContext: SQL table aliases and constraints for a given
>> * SPARQL group graph pattern.
>> */
>> class BindingContext {
>> protected:
>> List<Item_variable> item_variables;
>> // All known table aliases for in the context.
>> List<Alias_info> aliases;
>> Name_resolution_context *name_res_context;
>> BindingContext *parent;
>> LEX *lex;
>> List<Item> *constraints;
>>
>> public:
>> BindingContext(GraphContext *gc_param, BindingContext *parent_param,
>> LEX *lex_param) {
>> parent= parent_param;
>> lex= lex_param;
>> //name_res_context= lex->current_context();
>> }
>> Item_variable* ensure_bound_item_variable(const char *name,
>> sparqlFrob *sparql_frob, int ref_count);
>> void select_star(THD *thd);
>> List<Item_variable>* get_item_variables () { return &item_variables;
> }
>> Alias_info* get_table_alias(THD *thd, Item_POS *s, Item_URI *p, Item_POS
>> *o);
>> Item* get_bound_variable_constraints(Item *conjunction_constraints,
>> GraphContext *gc);
>> void start_constraints();
>> void end_and_check_constraints() {
>> assert(constraints == lex->select_lex.expr_list.pop());
>> }
>> Item* make_item_constraints() {
>> return constraints->elements ? new Item_cond_and(*constraints) : NULL;
>> }
>> };
>>
>>
>> /* GraphContext: corresponds to a SPARQL graph context.
>> */
>> class GraphContext {
>> protected:
>> GraphContext *parent;
>> THD *thd;
>> Buf *buf; // temporary
>>
>> public:
>> sparqlFrob *sparql_frob; // !!! should be protected
>> GraphContext (GraphContext *parent_param, sparqlFrob *sparql_frob_param)
>> {
>> sparql_frob= sparql_frob_param;
>> parent= parent_param;
>> thd= sparql_frob->thd;
>> buf= NULL;
>> }
>> virtual ~GraphContext () {}
>> virtual void close () {
>> cout << "SPARQL: close {" << endl << buf->str() <<
> "}" << endl;
>> }
>> virtual void no_right_union () {
>> cout << "SPARQL: non-UNION {" << endl << buf->str()
> << "}" << endl;
>> }
>> void set_Buf (Buf *buf_param) { buf= buf_param; }
>> Buf* get_Buf () { return buf; }
>> virtual bool is_optional () { return false; }
>> virtual BindingContext* get_binding_context () {
>> return parent->get_binding_context();
>> }
>> const char* get_alias_string(Alias_info *ai, Item_POS *s, THD *thd);
>> };
>>
>>
>> /* BindingGraphContext: the graph contexts that require a new
>> BindingContext.
>> * Raison d'etre: factored common code from Union and Graph contexts.
>> */
>> class BindingGraphContext : public GraphContext {
>> friend class Union2GraphContext; // why doesn't BindingGraphContext work
>> here?
>> protected:
>> BindingContext *bindings;
>> SELECT_LEX *current_select;
>> BindingGraphContext(GraphContext *parent_param, sparqlFrob
>> *sparql_frob_param);
>> public:
>> void select_var(Item_variable *var, bool exists);
>> virtual BindingContext* get_binding_context() { return bindings; }
>> };
>>
>>
>> /* RootGraphContext: the graph context just inside the WHERE.
>> */
>> class RootGraphContext : public BindingGraphContext {
>> public:
>> RootGraphContext(GraphContext *parent, sparqlFrob *sparql_frob);
>> virtual void close () {
>> bindings->end_and_check_constraints();
>> }
>> };
>>
>>
>> /* OptionalGraphContext: OPTIONAL { }.
>> * ^^^
>> */
>> class OptionalGraphContext : public GraphContext {
>> public:
>> OptionalGraphContext (GraphContext *parent, sparqlFrob *sparql_frob) :
>> GraphContext(parent, sparql_frob) {
>> /* if (!(on_context= make_join_on_context(thd, $1, $3)))
>> assert(0);
>> thd->lex->push_context(on_context);
>> */
>> }
>> virtual void close () {
>> /* thd->lex->pop_context();
>> */
>> }
>> virtual bool is_optional () { return true; }
>> };
>>
>>
>> /* Union1GraphContext: { } UNION { }.
>> * ^^^
>> */
>> class Union1GraphContext : public BindingGraphContext {
>> public:
>> Union1GraphContext(GraphContext *parent, sparqlFrob *sparql_frob);
>> virtual void no_right_union () {
>> /* Just a spurious {} so copy the context up to the parent.
>> @@@ TODO
>> */
>> my_printf_error(1, "SPARQL: implementation limitation: not ready to
>> deal with non-UNION %s. "PLS_REPORT, MYF(0), buf->str());
>> }
>> virtual void close();
>> Item* map_variables_to_outer_context () { // !!! does nothing
>> return NULL;
>> }
>> };
>>
>>
>> /* Union1GraphContext: { } UNION { }.
>> * ^^^
>> */
>> class Union2GraphContext : public BindingGraphContext {
>> private:
>> BindingGraphContext *left; // left side of the UNION
>>
>> public:
>> Union2GraphContext(GraphContext *parent, sparqlFrob *sparql_frob);
>> virtual void close();
>> };
>>
>>
>> /* GraphGraphContext: GRAPH { }.
>> * ^^^
>> */
>> class GraphGraphContext : public BindingGraphContext {
>> public:
>> GraphGraphContext (GraphContext *parent, sparqlFrob *sparql_frob) :
>> BindingGraphContext(parent, sparql_frob) {}
>> };
>>
>>
>> %}
>>
>> %union {
>> int num;
>> LEX_STRING lex_str;
>> Item *item;
>> List<Item> *item_list;
>> List<BindingGraphContext> *BindingGraphContext_list;
>> Item_POS *item_pos;
>> GraphContext *graph_context;
>> BindingGraphContext *binding_graph_context;
>> Buf *buf;
>> }
>>
>> %token <buf> IT_BASE
>> %token <buf> IT_PREFIX
>> %token <buf> IT_SELECT
>> %token <buf> IT_DISTINCT
>> %token <buf> GT_TIMES
>> %token <buf> IT_CONSTRUCT
>> %token <buf> IT_DESCRIBE
>> %token <buf> IT_ASK
>> %token <buf> IT_FROM
>> %token <buf> IT_NAMED
>> %token <buf> IT_WHERE
>> %token <buf> IT_ORDER
>> %token <buf> IT_BY
>> %token <buf> IT_ASC
>> %token <buf> IT_DESC
>> %token <buf> IT_LIMIT
>> %token <buf> IT_OFFSET
>> %token <buf> GT_LCURLEY
>> %token <buf> GT_RCURLEY
>> %token <buf> GT_DOT
>> %token <buf> IT_OPTIONAL
>> %token <buf> IT_GRAPH
>> %token <buf> IT_UNION
>> %token <buf> IT_FILTER
>> %token <buf> GT_COMMA
>> %token <buf> GT_LPAREN
>> %token <buf> GT_RPAREN
>> %token <buf> GT_SEMI
>> %token <item_pos> IT_a
>> %token <buf> GT_LBRACKET
>> %token <buf> GT_RBRACKET
>> %token <buf> GT_MINUS
>> %token <buf> GT_PLUS
>> %token <buf> GT_OR
>> %token <buf> GT_AND
>> %token <buf> GT_EQUAL
>> %token <buf> GT_NEQUAL
>> %token <buf> GT_LT
>> %token <buf> GT_GT
>> %token <buf> GT_LE
>> %token <buf> GT_GE
>> %token <buf> GT_DIVIDE
>> %token <buf> GT_NOT
>> %token <buf> IT_STR
>> %token <buf> IT_LANG
>> %token <buf> IT_LANGMATCHES
>> %token <buf> IT_DATATYPE
>> %token <buf> IT_BOUND
>> %token <buf> IT_isIRI
>> %token <buf> IT_isURI
>> %token <buf> IT_isBLANK
>> %token <buf> IT_isLITERAL
>> %token <buf> IT_REGEX
>> %token <buf> GT_DTYPE
>> %token <item_pos> IT_true
>> %token <item_pos> IT_false
>> %token <lex_str> Q_IRI_REF
>> %token <lex_str> QNAME_NS
>> %token <lex_str> QNAME
>> %token <lex_str> BLANK_NODE_LABEL
>> %token <lex_str> VAR1
>> %token <lex_str> VAR2
>> %token <item_pos> LANGTAG
>> %token <lex_str> INTEGER
>> %token <lex_str> DECIMAL
>> %token <lex_str> DOUBLE
>> %token <lex_str> STRING_LITERAL1
>> %token <lex_str> STRING_LITERAL2
>> %token <lex_str> STRING_LITERAL_LONG1
>> %token <lex_str> STRING_LITERAL_LONG2
>> %token <item_pos> NIL
>> %token <lex_str> ANON
>> %type <buf> Query
>> %type <buf>
>>
> _O_QSelectQuery_E__Or__QConstructQuery_E__Or__QDescribeQuery_E__Or__QAskQuery_E__C
>> %type <buf> Prolog
>> %type <buf> _QBaseDecl_E_Opt
>> %type <buf> _QPrefixDecl_E_Star
>> %type <buf> BaseDecl
>> %type <buf> PrefixDecl
>> %type <buf> SelectQuery
>> %type <buf> _QDISTINCT_E_Opt
>> %type <buf> _QVar_E_Plus
>> %type <buf> _O_QVar_E_Plus_Or__QTIMES_E__C
>> %type <buf> _QDatasetClause_E_Star
>> %type <buf> ConstructQuery
>> %type <buf> DescribeQuery
>> %type <buf> _QVarOrIRIref_E_Plus
>> %type <buf> _O_QVarOrIRIref_E_Plus_Or__QTIMES_E__C
>> %type <buf> _QWhereClause_E_Opt
>> %type <buf> AskQuery
>> %type <buf> DatasetClause
>> %type <buf> _O_QDefaultGraphClause_E__Or__QNamedGraphClause_E__C
>> %type <buf> DefaultGraphClause
>> %type <buf> NamedGraphClause
>> %type <buf> SourceSelector
>> %type <buf> WhereClause
>> %type <buf> _QWHERE_E_Opt
>> %type <buf> SolutionModifier
>> %type <buf> _QOrderClause_E_Opt
>> %type <buf> _QLimitClause_E_Opt
>> %type <buf> _QOffsetClause_E_Opt
>> %type <buf> OrderClause
>> %type <buf> _QOrderCondition_E_Plus
>> %type <buf> OrderCondition
>> %type <num> _O_QASC_E__Or__QDESC_E__C
>> %type <buf> _O_QASC_E__Or__QDESC_E____QBrackettedExpression_E__C
>> %type <item>
>> _O_QFunctionCall_E__Or__QVar_E__Or__QBrackettedExpression_E__C
>> %type <buf> LimitClause
>> %type <buf> OffsetClause
>> %type <graph_context> GroupGraphPattern
>> %type <buf> GraphPattern
>> %type <buf> _QDOT_E_Opt
>> %type <buf>
>> _O_QGraphPatternNotTriples_E____QDOT_E_Opt___QGraphPattern_E__C
>> %type <buf>
>> _Q_O_QGraphPatternNotTriples_E____QDOT_E_Opt___QGraphPattern_E__C_E_Opt
>> %type <buf> FilteredBasicGraphPattern
>> %type <buf> _QBlockOfTriples_E_Opt
>> %type <buf>
>> _O_QConstraint_E____QDOT_E_Opt___QFilteredBasicGraphPattern_E__C
>> %type <buf>
>> _Q_O_QConstraint_E____QDOT_E_Opt___QFilteredBasicGraphPattern_E__C_E_Opt
>> %type <buf> BlockOfTriples
>> %type <buf> _QTriplesSameSubject_E_Opt
>> %type <buf> _O_QDOT_E____QTriplesSameSubject_E_Opt_C
>> %type <buf> _Q_O_QDOT_E____QTriplesSameSubject_E_Opt_C_E_Star
>> %type <buf> GraphPatternNotTriples
>> %type <buf> OptionalGraphPattern
>> %type <buf> GraphGraphPattern
>> %type <buf> GroupOrUnionGraphPattern
>> %type <binding_graph_context> _O_QUNION_E____QGroupGraphPattern_E__C
>> %type <BindingGraphContext_list>
>> _Q_O_QUNION_E____QGroupGraphPattern_E__C_E_Star
>> %type <buf> Constraint
>> %type <item>
>> _O_QBrackettedExpression_E__Or__QBuiltInCall_E__Or__QFunctionCall_E__C
>> %type <item> FunctionCall
>> %type <item_list> ArgList
>> %type <item> _O_QCOMMA_E____QExpression_E__C
>> %type <NONE> _Q_O_QCOMMA_E____QExpression_E__C_E_Star
>> %type <item_list>
>>
> _O_QNIL_E__Or__QLPAREN_E____QExpression_E____QCOMMA_E____QExpression_E_Star___QRPAREN_E__C
>> %type <buf> ConstructTemplate
>> %type <buf> ConstructTriples
>> %type <buf> _O_QDOT_E____QConstructTriples_E__C
>> %type <buf> _Q_O_QDOT_E____QConstructTriples_E__C_E_Opt
>> %type <buf>
>> _O_QTriplesSameSubject_E____QDOT_E____QConstructTriples_E_Opt_C
>> %type <buf>
>> _Q_O_QTriplesSameSubject_E____QDOT_E____QConstructTriples_E_Opt_C_E_Opt
>> %type <buf> TriplesSameSubject
>> %type <buf> PropertyList
>> %type <buf> _QPropertyListNotEmpty_E_Opt
>> %type <buf> PropertyListNotEmpty
>> %type <buf> _O_QSEMI_E____QPropertyList_E__C
>> %type <buf> _Q_O_QSEMI_E____QPropertyList_E__C_E_Opt
>> %type <buf> ObjectList
>> %type <buf> _O_QCOMMA_E____QObjectList_E__C
>> %type <buf> _Q_O_QCOMMA_E____QObjectList_E__C_E_Opt
>> %type <item_pos> Verb
>> %type <item_pos> TriplesNode
>> %type <item_pos> BlankNodePropertyList
>> %type <item_pos> Collection
>> %type <buf> _QGraphNode_E_Plus
>> %type <item_pos> GraphNode
>> %type <item_pos> VarOrTerm
>> %type <item_pos> VarOrIRIref
>> %type <buf> VarOrBlankNodeOrIRIref
>> %type <item_pos> Var
>> %type <item_pos> GraphTerm
>> %type <buf> _O_QMINUS_E__Or__QPLUS_E__C
>> %type <buf> _Q_O_QMINUS_E__Or__QPLUS_E__C_E_Opt
>> %type <item> Expression
>> %type <item> ConditionalOrExpression
>> %type <NONE> _O_QOR_E____QConditionalAndExpression_E__C
>> %type <NONE> _Q_O_QOR_E____QConditionalAndExpression_E__C_E_Star
>> %type <item> ConditionalAndExpression
>> %type <NONE> _O_QAND_E____QValueLogical_E__C
>> %type <NONE> _Q_O_QAND_E____QValueLogical_E__C_E_Star
>> %type <item> ValueLogical
>> %type <item> RelationalExpression
>> %type <NONE>
>>
> _O_QEQUAL_E____QNumericExpression_E__Or__QNEQUAL_E____QNumericExpression_E__Or__QLT_E____QNumericExpression_E__Or__QGT_E____QNumericExpression_E__Or__QLE_E____QNumericExpression_E__Or__QGE_E____QNumericExpression_E__C
>> %type <NONE>
>>
> _Q_O_QEQUAL_E____QNumericExpression_E__Or__QNEQUAL_E____QNumericExpression_E__Or__QLT_E____QNumericExpression_E__Or__QGT_E____QNumericExpression_E__Or__QLE_E____QNumericExpression_E__Or__QGE_E____QNumericExpression_E__C_E_Opt
>> %type <item> NumericExpression
>> %type <item> AdditiveExpression
>> %type <NONE>
>>
> _O_QPLUS_E____QMultiplicativeExpression_E__Or__QMINUS_E____QMultiplicativeExpression_E__C
>> %type <NONE>
>>
> _Q_O_QPLUS_E____QMultiplicativeExpression_E__Or__QMINUS_E____QMultiplicativeExpression_E__C_E_Star
>> %type <item> MultiplicativeExpression
>> %type <NONE>
>> _O_QTIMES_E____QUnaryExpression_E__Or__QDIVIDE_E____QUnaryExpression_E__C
>> %type <NONE>
>>
> _Q_O_QTIMES_E____QUnaryExpression_E__Or__QDIVIDE_E____QUnaryExpression_E__C_E_Star
>> %type <item> UnaryExpression
>> %type <item> PrimaryExpression
>> %type <item> BrackettedExpression
>> %type <item> BuiltInCall
>> %type <item> RegexExpression
>> %type <item> _Q_O_QCOMMA_E____QExpression_E__C_E_Opt
>> %type <item> IRIrefOrFunction
>> %type <item_list> _QArgList_E_Opt
>> %type <item_pos> RDFLiteral
>> %type <item_pos> _O_QDTYPE_E____QIRIref_E__C
>> %type <item_pos> _O_QLANGTAG_E__Or__QDTYPE_E____QIRIref_E__C
>> %type <item_pos> _Q_O_QLANGTAG_E__Or__QDTYPE_E____QIRIref_E__C_E_Opt
>> %type <item_pos> NumericLiteral
>> %type <item_pos> BooleanLiteral
>> %type <lex_str> String
>> %type <item_pos> IRIref
>> %type <item_pos> QName
>> %type <item_pos> BlankNode
>> %%
>>
>> Query:
>> {
>> LEX *lex= yySparqlFrob->thd->lex;
>> SELECT_LEX *sel= lex->current_select;
>> lex->current_select->parsing_place = NO_MATTER;
>> sel->offset_limit= NULL;
>> sel->select_limit= NULL;
>> // create root context right away so SELECTs have a context
>> yySparqlFrob->push_context(
>> new RootGraphContext(yySparqlFrob->head_context(), yySparqlFrob));
>> }
>> Prolog
>>
> _O_QSelectQuery_E__Or__QConstructQuery_E__Or__QDescribeQuery_E__Or__QAskQuery_E__C
>> {
>> Buf *b = new Buf(2, $2, $3);
>> cout << "Query end -- " << b->str() << endl;
>> delete b;
>> };
>>
>>
> _O_QSelectQuery_E__Or__QConstructQuery_E__Or__QDescribeQuery_E__Or__QAskQuery_E__C:
>> SelectQuery {$$ = $1}
>> | ConstructQuery {$$ = $1; YYABORT;}
>> | DescribeQuery {$$ = $1; YYABORT;}
>> | AskQuery {$$ = $1; YYABORT;};
>>
>> Prolog:
>> _QBaseDecl_E_Opt _QPrefixDecl_E_Star {$$ = new Buf(2, $1, $2)};
>>
>> _QBaseDecl_E_Opt:
>> {$$ = new Buf()}
>> | BaseDecl {$$ = $1};
>>
>> _QPrefixDecl_E_Star:
>> {$$ = new Buf()}
>> | _QPrefixDecl_E_Star PrefixDecl {$$ = new Buf(2, $1, $2)};
>>
>> BaseDecl:
>> IT_BASE Q_IRI_REF {$$ = new Buf(2, new Buf("BASE"), new Buf($2.str))};
>>
>> PrefixDecl:
>> IT_PREFIX QNAME_NS Q_IRI_REF {$$ = new Buf(3, $1, new Buf($2.str), new
>> Buf($3.str))};
>>
>> SelectQuery:
>> IT_SELECT
>> {
>> LEX *lex= yySparqlFrob->lex;
>> SELECT_LEX *sel= lex->current_select;
>>
>> sel->parsing_place = SELECT_LIST;
>> lex->sql_command= SQLCOM_SELECT; // SQLCOM_EMPTY_QUERY;
>> }
>> _QDISTINCT_E_Opt _O_QVar_E_Plus_Or__QTIMES_E__C
>> {
>> //SELECT_LEX *sel= yySparqlFrob->lex->current_select;
>>
>> // commented out 'cause the didn't seem to be needed - EGP 20060326
>> // lex->create_view_select_start = $1->get_item()->name;
>> //sel->parsing_place = NO_MATTER;
>> //sel->set_braces(0);
>> }
>> _QDatasetClause_E_Star WhereClause SolutionModifier
>> {
>> LEX *lex= yySparqlFrob->lex;
>> SELECT_LEX *sel= lex->current_select;
>>
>> // Now that we have all the variables, fix up the SELECTs.
>> yySparqlFrob->select_variables();
>>
>> sel->parsing_place = NO_MATTER;
>> $$ = new Buf(6, new Buf("SELECT"), $3, $4, $6, $7, $8);
>> }
>> ;
>>
>> _QDISTINCT_E_Opt:
>> {$$ = new Buf()}
>> | IT_DISTINCT
>> {
>> yySparqlFrob->set_distinct(true);
>> $$ = $1;
>> };
>>
>> _QVar_E_Plus:
>> Var
>> {
>> THD *thd= yySparqlFrob->thd;
>> LEX *lex= thd->lex;
>> SELECT_LEX *sel= lex->current_select;
>> //sel->use_index_ptr=sel->ignore_index_ptr=0;
>> sel->table_join_options= 0;
>> if (add_item_to_list(thd, $1->get_item())) {
>> YYABORT;
>> }
>>
>> $$ = new Buf($1->get_item()->name);
>> }
>> | _QVar_E_Plus Var
>> {
>> THD *thd= yySparqlFrob->thd;
>> if (add_item_to_list(thd, $2->get_item())) {
>> YYABORT;
>> }
>> $$ = new Buf(2, $1, new Buf($2->get_item()->name));
>> };
>>
>> _O_QVar_E_Plus_Or__QTIMES_E__C:
>> _QVar_E_Plus {$$ = $1}
>> | GT_TIMES
>> { $$ = $1; }
>> ;
>>
>> _QDatasetClause_E_Star:
>> {$$ = new Buf()}
>> | _QDatasetClause_E_Star DatasetClause {$$ = new Buf(2, $1, $2)};
>>
>> ConstructQuery:
>> IT_CONSTRUCT ConstructTemplate _QDatasetClause_E_Star WhereClause
>> SolutionModifier {$$ = new Buf(5, $1, $2, $3, $4, $5)};
>>
>> DescribeQuery:
>> IT_DESCRIBE _O_QVarOrIRIref_E_Plus_Or__QTIMES_E__C
>> _QDatasetClause_E_Star _QWhereClause_E_Opt SolutionModifier {$$ = new
>> Buf(5, $1, $2, $3, $4, $5)};
>>
>> _QVarOrIRIref_E_Plus:
>> VarOrIRIref {$$ = new Buf($1->get_item()->name)}
>> | _QVarOrIRIref_E_Plus VarOrIRIref {$$ = new Buf(2, $1, new
>> Buf($2->get_item()->name))};
>>
>> _O_QVarOrIRIref_E_Plus_Or__QTIMES_E__C:
>> _QVarOrIRIref_E_Plus {$$ = $1}
>> | GT_TIMES {$$ = $1};
>>
>> _QWhereClause_E_Opt:
>> {$$ = new Buf()}
>> | WhereClause {$$ = $1};
>>
>> AskQuery:
>> IT_ASK _QDatasetClause_E_Star WhereClause {$$ = new Buf(3, $1, $2,
>> $3)};
>>
>> DatasetClause:
>> IT_FROM _O_QDefaultGraphClause_E__Or__QNamedGraphClause_E__C {$$ = new
>> Buf(2, $1, $2)};
>>
>> _O_QDefaultGraphClause_E__Or__QNamedGraphClause_E__C:
>> DefaultGraphClause {$$ = $1}
>> | NamedGraphClause {$$ = $1};
>>
>> DefaultGraphClause:
>> SourceSelector {$$ = $1};
>>
>> NamedGraphClause:
>> IT_NAMED SourceSelector {$$ = new Buf(2, $1, $2)};
>>
>> SourceSelector:
>> IRIref {$$ = new Buf($1->get_item()->name)};
>>
>> WhereClause:
>> _QWHERE_E_Opt
>> {
>> SELECT_LEX* sel = &yySparqlFrob->lex->select_lex;
>> sel->parsing_place = IN_WHERE;
>>
>> /* we've been using a context (for SELECTs) but need
>> to pop it so it can be pushed back on at the LCURLEY */
>> yySparqlFrob->set_next_GC(yySparqlFrob->pop_context());
>> }
>> GroupGraphPattern
>> {
>> GraphContext *gc= $3;
>> SELECT_LEX* sel = &yySparqlFrob->lex->select_lex;
>> BindingContext *bc= gc->get_binding_context();
>> Item *constraints= bc->make_item_constraints();
>> yySparqlFrob->add_root_constraints(bc->
>> get_bound_variable_constraints(constraints, gc));
>> Item *where = yySparqlFrob->get_root_constraints();
>> if (where) {
>> where->top_level_item();
>> sel->where = where;
>> String string;
>> where->print(&string);
>> $$ = new Buf(4, $1, $3->get_Buf(), new Buf("WHERE"), new
>> Buf(string.c_ptr()));
>> } else {
>> $$ = new Buf(2, $1, $3->get_Buf());
>> }
>> sel->parsing_place= NO_MATTER;
>> };
>>
>> _QWHERE_E_Opt:
>> {$$ = new Buf()}
>> | IT_WHERE {$$ = $1};
>>
>> SolutionModifier:
>> _QOrderClause_E_Opt _QLimitClause_E_Opt _QOffsetClause_E_Opt {$$ = new
>> Buf(3, $1, $2, $3)};
>>
>> _QOrderClause_E_Opt:
>> {$$ = new Buf()}
>> | OrderClause {$$ = $1};
>>
>> _QLimitClause_E_Opt:
>> {$$ = new Buf();}
>> | LimitClause {$$ = $1};
>>
>> _QOffsetClause_E_Opt:
>> {$$ = new Buf()}
>> | OffsetClause {$$ = $1};
>>
>> OrderClause:
>> IT_ORDER IT_BY _QOrderCondition_E_Plus {$$ = new Buf(3, $1, $2, $3)};
>>
>> _QOrderCondition_E_Plus:
>> OrderCondition {$$ = $1}
>> | _QOrderCondition_E_Plus OrderCondition {$$ = new Buf(2, $1, $2)};
>>
>> OrderCondition:
>> _O_QASC_E__Or__QDESC_E____QBrackettedExpression_E__C {$$ = $1}
>> | _O_QFunctionCall_E__Or__QVar_E__Or__QBrackettedExpression_E__C {$$ =
>> new Buf("!!!")};
>>
>> _O_QASC_E__Or__QDESC_E__C:
>> IT_ASC {$$ =1}
>> | IT_DESC {$$ =0};
>>
>> _O_QASC_E__Or__QDESC_E____QBrackettedExpression_E__C:
>> _O_QASC_E__Or__QDESC_E__C BrackettedExpression
>> {
>> if (add_order_to_list(yySparqlFrob->thd, $2, (bool) $1))
>> YYABORT; String string;
>> $2->print(&string);
>> $$ = new Buf(2, new Buf((char*)($1 ? "ASK" : "DESC")), new
>> Buf(string.c_ptr()));
>> };
>>
>> _O_QFunctionCall_E__Or__QVar_E__Or__QBrackettedExpression_E__C:
>> FunctionCall {$$ = $1}
>> | Var {$$ = $1->get_item()}
>> | BrackettedExpression {$$ = $1};
>>
>> LimitClause:
>> IT_LIMIT INTEGER
>> {
>> SELECT_LEX *sel = &yySparqlFrob->lex->select_lex;
>> sel->select_limit = new Item_uint($2.str, $2.length);
>> sel->explicit_limit= 1;
>> $$ = new Buf(2, $1, new Buf($2.str));
>> };
>>
>> OffsetClause:
>> IT_OFFSET INTEGER
>> {
>> SELECT_LEX *sel = &yySparqlFrob->lex->select_lex;
>> sel->offset_limit = new Item_uint($2.str, $2.length);
>> sel->explicit_limit= 1;
>> $$ = new Buf(2, $1, new Buf($2.str));
>> };
>>
>> GroupGraphPattern:
>> GT_LCURLEY
>> {
>> GraphContext *gc = yySparqlFrob->was_next_GC();
>> yySparqlFrob->push_context(gc ? gc : new
>> Union1GraphContext(yySparqlFrob->head_context(), yySparqlFrob));
>> }
>> GraphPattern GT_RCURLEY
>> {
>> if (yySparqlFrob->get_distinct())
>> yySparqlFrob->lex->current_select->options|= SELECT_DISTINCT;
>> $$= yySparqlFrob->pop_context();
>> $$->set_Buf(new Buf(3, $1, $3, $4));
>> $$->close();
>> };
>>
>> GraphPattern:
>> FilteredBasicGraphPattern
>> _Q_O_QGraphPatternNotTriples_E____QDOT_E_Opt___QGraphPattern_E__C_E_Opt {$$
>> = new Buf(2, $1, $2)};
>>
>> _QDOT_E_Opt:
>> {$$ = new Buf()}
>> | GT_DOT {$$ = $1};
>>
>> _O_QGraphPatternNotTriples_E____QDOT_E_Opt___QGraphPattern_E__C:
>> GraphPatternNotTriples _QDOT_E_Opt GraphPattern {$$ = new Buf(3, $1,
>> $2, $3)};
>>
>> _Q_O_QGraphPatternNotTriples_E____QDOT_E_Opt___QGraphPattern_E__C_E_Opt:
>> {$$ = new Buf()}
>> | _O_QGraphPatternNotTriples_E____QDOT_E_Opt___QGraphPattern_E__C {$$
>> = $1};
>>
>> FilteredBasicGraphPattern:
>> _QBlockOfTriples_E_Opt
>> _Q_O_QConstraint_E____QDOT_E_Opt___QFilteredBasicGraphPattern_E__C_E_Opt {$$
>> = new Buf(2, $1, $2)};
>>
>> _QBlockOfTriples_E_Opt:
>> {$$ = new Buf()}
>> | BlockOfTriples {$$ = $1};
>>
>> _O_QConstraint_E____QDOT_E_Opt___QFilteredBasicGraphPattern_E__C:
>> Constraint _QDOT_E_Opt FilteredBasicGraphPattern {$$ = new Buf(3, $1,
>> $2, $3)};
>>
>> _Q_O_QConstraint_E____QDOT_E_Opt___QFilteredBasicGraphPattern_E__C_E_Opt:
>> {$$ = new Buf()}
>> | _O_QConstraint_E____QDOT_E_Opt___QFilteredBasicGraphPattern_E__C {$$
>> = $1};
>>
>> BlockOfTriples:
>> TriplesSameSubject
>> _Q_O_QDOT_E____QTriplesSameSubject_E_Opt_C_E_Star {$$ = new Buf(2, $1,
>> $2)};
>>
>> _QTriplesSameSubject_E_Opt:
>> {$$ = new Buf()}
>> | TriplesSameSubject {$$ = $1};
>>
>> _O_QDOT_E____QTriplesSameSubject_E_Opt_C:
>> GT_DOT _QTriplesSameSubject_E_Opt {$$ = new Buf(2, $1, $2)};
>>
>> _Q_O_QDOT_E____QTriplesSameSubject_E_Opt_C_E_Star:
>> {$$ = new Buf()}
>> | _Q_O_QDOT_E____QTriplesSameSubject_E_Opt_C_E_Star
>> _O_QDOT_E____QTriplesSameSubject_E_Opt_C {$$ = new Buf(2, $1, $2)};
>>
>> GraphPatternNotTriples:
>> OptionalGraphPattern {$$ = $1}
>> | GroupOrUnionGraphPattern {$$ = $1}
>> | GraphGraphPattern {$$ = $1};
>>
>> OptionalGraphPattern:
>> IT_OPTIONAL
>> {
>> yySparqlFrob->lex->select_lex.init_nested_join(yySparqlFrob->thd);
>> yySparqlFrob->set_next_GC(
>> new OptionalGraphContext(yySparqlFrob->head_context(),
>> yySparqlFrob));
>> }
>> GroupGraphPattern
>> {
>> GraphContext *gc= $3;
>> SELECT_LEX* sel= &yySparqlFrob->lex->select_lex;
>> BindingContext *bc= gc->get_binding_context();
>> Item *constraints= bc->make_item_constraints();
>> Item *constraint= bc->get_bound_variable_constraints(constraints, gc);
>> yySparqlFrob->add_root_constraints(constraint);
>>
>> String string;
>> if (constraint)
>> constraint->print(&string);
>>
>> yySparqlFrob->lex->select_lex.end_nested_join(yySparqlFrob->thd);
>>
>> $$ = new Buf(3, $1, $3->get_Buf(), new Buf(string.c_ptr()));
>> };
>>
>> GraphGraphPattern:
>> IT_GRAPH VarOrBlankNodeOrIRIref
>> {
>> yySparqlFrob->set_next_GC(
>> new GraphGraphContext(yySparqlFrob->head_context(),
>> yySparqlFrob));
>> }
>> GroupGraphPattern
>> {
>> $$ = new Buf(3, $1, $2, $4->get_Buf());
>> };
>>
>> GroupOrUnionGraphPattern:
>> GroupGraphPattern
>> {
>> cout << "look for UNIONs in \"" <<
>> yySparqlFrob->thd->m_lip->get_ptr() << "\"?" << endl; //
>> yySparqlFrob->lex->ptr
>> }
>> _Q_O_QUNION_E____QGroupGraphPattern_E__C_E_Star
>> {
>> $$= $1->get_Buf();
>> if ($3) {
>> $3->push_front((BindingGraphContext*)$1);
>> cout << "there were " << $3->elements << " UNION
> elements" << endl;
>>
>> yySparqlFrob->needs_select($3);
>>
>> // Maintain the Buf for debugging.
>> cout << "0: " << (void*)$1 << ": " << $$->str()
> << endl;
>> unsigned i= 1;
>> List_iterator<BindingGraphContext> item_list_it(*$3);
>> GraphContext* gc= item_list_it++;
>> while ((gc= item_list_it++)) {
>> cout << i++ << ": " << (void*)gc << ": " <<
> gc->get_Buf()->str() <<
>> endl;
>> $$= new Buf(3, $$, new Buf("UNION"), gc->get_Buf());
>> }
>> } else {
>> $1->no_right_union();
>> }
>> }; // !! check return
>>
>> _O_QUNION_E____QGroupGraphPattern_E__C:
>> IT_UNION
>> {
>> yySparqlFrob->set_next_GC(
>> new Union2GraphContext(yySparqlFrob->head_context(),
>> yySparqlFrob));
>> //cout << " found UNION start \"" <<
> yySparqlFrob->lex->ptr << "\"?"
>> << endl;
>> }
>> GroupGraphPattern
>> {
>> $$ = (BindingGraphContext*)$3;
>> //cout << " UNION end at \"" <<
> yySparqlFrob->lex->ptr << "\"?"
>> << endl;
>> };
>>
>> _Q_O_QUNION_E____QGroupGraphPattern_E__C_E_Star:
>> {
>> $$= NULL;
>> }
>> | _Q_O_QUNION_E____QGroupGraphPattern_E__C_E_Star
>> _O_QUNION_E____QGroupGraphPattern_E__C
>> {
>> //cout << " UNION found before \"" <<
> yySparqlFrob->lex->ptr << "\"?"
>> << endl;
>> $$= $1 ? $1 : new List<BindingGraphContext>;
>> $$->push_back($2);
>> };
>>
>> Constraint:
>> IT_FILTER
>> _O_QBrackettedExpression_E__Or__QBuiltInCall_E__Or__QFunctionCall_E__C
>> {
>> LEX *lex = yySparqlFrob->lex;
>> SELECT_LEX* sel = &lex->select_lex;
>> sel->expr_list.head()->push_back($2);
>> String string;
>> $2->print(&string);
>> $$ = new Buf(string.c_ptr());
>> };
>>
>> _O_QBrackettedExpression_E__Or__QBuiltInCall_E__Or__QFunctionCall_E__C:
>> BrackettedExpression {$$ = $1}
>> | BuiltInCall {$$ = $1}
>> | FunctionCall {$$ = $1};
>>
>> FunctionCall:
>> IRIref ArgList {$$ = NULL; // new
>> Item_func_call(yySparqlFrob->lex->current_context(), $1, $2); YYABORT /*
>> !!! NI */};
>>
>> ArgList:
>>
>>
> _O_QNIL_E__Or__QLPAREN_E____QExpression_E____QCOMMA_E____QExpression_E_Star___QRPAREN_E__C {$$
>
>> = $1};
>>
>> _O_QCOMMA_E____QExpression_E__C:
>> GT_COMMA Expression {$$ = $2};
>>
>> _Q_O_QCOMMA_E____QExpression_E__C_E_Star:
>> {}
>> | _Q_O_QCOMMA_E____QExpression_E__C_E_Star
>> _O_QCOMMA_E____QExpression_E__C
>> {
>> yySparqlFrob->lex->select_lex.expr_list.push_front(new
> List<Item>);
>> };
>>
>>
> _O_QNIL_E__Or__QLPAREN_E____QExpression_E____QCOMMA_E____QExpression_E_Star___QRPAREN_E__C:
>> NIL {$$ = NULL}
>> | GT_LPAREN {
>> yySparqlFrob->lex->select_lex.expr_list.push_front(new
> List<Item>);
>> }
>> Expression _Q_O_QCOMMA_E____QExpression_E__C_E_Star GT_RPAREN
>> {
>> $$ = yySparqlFrob->lex->select_lex.expr_list.pop();
>> $$->push_front($3);
>> };
>>
>> ConstructTemplate:
>> GT_LCURLEY ConstructTriples GT_RCURLEY {$$ = new Buf(3, $1, $2, $3)};
>>
>> ConstructTriples:
>>
>> _Q_O_QTriplesSameSubject_E____QDOT_E____QConstructTriples_E_Opt_C_E_Opt {$$
>> = $1};
>>
>> _O_QDOT_E____QConstructTriples_E__C:
>> GT_DOT ConstructTriples {$$ = new Buf(2, $1, $2)};
>>
>> _Q_O_QDOT_E____QConstructTriples_E__C_E_Opt:
>> {$$ = new Buf()}
>> | _O_QDOT_E____QConstructTriples_E__C {$$ = $1};
>>
>> _O_QTriplesSameSubject_E____QDOT_E____QConstructTriples_E_Opt_C:
>> TriplesSameSubject _Q_O_QDOT_E____QConstructTriples_E__C_E_Opt {$$ =
>> new Buf(2, $1, $2)};
>>
>> _Q_O_QTriplesSameSubject_E____QDOT_E____QConstructTriples_E_Opt_C_E_Opt:
>> {$$ = new Buf()}
>> | _O_QTriplesSameSubject_E____QDOT_E____QConstructTriples_E_Opt_C {$$
>> = $1};
>>
>> TriplesSameSubject:
>> VarOrTerm
>> {
>> yySparqlFrob->push_subject($1);
>> }
>> PropertyListNotEmpty
>> {
>> yySparqlFrob->pop_subject();
>> $$ = new Buf(2, new Buf($1->get_item()->name), $3);
>> }
>> | TriplesNode
>> {
>> yySparqlFrob->push_subject($1);
>> }
>> PropertyList
>> {
>> yySparqlFrob->pop_subject();
>> $$ = new Buf(2, new Buf($1->get_item()->name), $3);
>> };
>>
>> PropertyList:
>> _QPropertyListNotEmpty_E_Opt {$$ = $1};
>>
>> _QPropertyListNotEmpty_E_Opt:
>> {$$ = new Buf()}
>> | PropertyListNotEmpty {$$ = $1};
>>
>> PropertyListNotEmpty:
>> Verb
>> {
>> yySparqlFrob->push_predicate($1);
>> }
>> ObjectList _Q_O_QSEMI_E____QPropertyList_E__C_E_Opt
>> {
>> yySparqlFrob->pop_predicate();
>> $$ = new Buf(3, new Buf($1->get_item()->name), $3, $4);
>> };
>>
>> _O_QSEMI_E____QPropertyList_E__C:
>> GT_SEMI PropertyList {$$ = new Buf(2, $1, $2)};
>>
>> _Q_O_QSEMI_E____QPropertyList_E__C_E_Opt:
>> {$$ = new Buf()}
>> | _O_QSEMI_E____QPropertyList_E__C {$$ = $1};
>>
>> ObjectList:
>> GraphNode
>> {
>> if (yySparqlFrob->object($1))
>> YYABORT;
>> }
>> _Q_O_QCOMMA_E____QObjectList_E__C_E_Opt {$$ = new Buf(2, new
>> Buf($1->get_item()->name), $3)};
>>
>> _O_QCOMMA_E____QObjectList_E__C:
>> GT_COMMA ObjectList {$$ = new Buf(2, $1, $2)};
>>
>> _Q_O_QCOMMA_E____QObjectList_E__C_E_Opt:
>> {$$ = new Buf()}
>> | _O_QCOMMA_E____QObjectList_E__C {$$ = $1};
>>
>> Verb:
>> VarOrIRIref {$$ = $1}
>> | IT_a {$$ = $1};
>>
>> TriplesNode:
>> Collection {$$ = $1}
>> | BlankNodePropertyList {$$ = $1};
>>
>> BlankNodePropertyList:
>> GT_LBRACKET
>> {
>> yySparqlFrob->push_subject(yySparqlFrob->make_blank_node());
>> }
>> PropertyListNotEmpty GT_RBRACKET
>> {
>> //Buf* t = new Buf(3, $1, $3, $4);
>> $$ = yySparqlFrob->pop_subject();
>> };
>>
>> Collection:
>> GT_LPAREN
>> {
>> yySparqlFrob->push_subject(yySparqlFrob->make_blank_node());
>> if (yySparqlFrob->type_list())
>> YYABORT
>> }
>> _QGraphNode_E_Plus GT_RPAREN
>> {
>> //Buf *t = new Buf(3, $1, $3, $4);
>> $$ = yySparqlFrob->pop_subject();
>> };
>>
>> _QGraphNode_E_Plus:
>> GraphNode
>> {
>> if (yySparqlFrob->add_listElement($1))
>> YYABORT;
>> }
>> | _QGraphNode_E_Plus GraphNode
>> {
>> if (yySparqlFrob->add_listElement($2))
>> YYABORT;
>> $$ = new Buf(2, $1, new Buf($2->get_item()->name));
>> };
>>
>> GraphNode:
>> VarOrTerm {$$ = $1}
>> | TriplesNode {$$ = $1};
>>
>> VarOrTerm:
>> Var {$$ = $1}
>> | GraphTerm {$$ = $1};
>>
>> VarOrIRIref:
>> Var {$$ = $1}
>> | IRIref {$$ = $1};
>>
>> VarOrBlankNodeOrIRIref:
>> Var {$$ = new Buf($1->get_item()->name)}
>> | BlankNode {$$ = new Buf($1->get_item()->name)}
>> | IRIref {$$ = new Buf($1->get_item()->name)};
>>
>> Var:
>> VAR1
>> {
>> $$ = yySparqlFrob->ensure_variable($1.str);
>> }
>> | VAR2
>> {
>> $$ = yySparqlFrob->ensure_variable($1.str);
>> };
>>
>> GraphTerm:
>> IRIref {$$ = $1}
>> | RDFLiteral {$$ = $1}
>> | _Q_O_QMINUS_E__Or__QPLUS_E__C_E_Opt NumericLiteral {$$ = $2 /* !!!
>> */}
>> | BooleanLiteral {$$ = $1}
>> | BlankNode {$$ = $1}
>> | NIL {$$ = $1};
>>
>> _O_QMINUS_E__Or__QPLUS_E__C:
>> GT_MINUS {$$ = $1}
>> | GT_PLUS {$$ = $1};
>>
>> _Q_O_QMINUS_E__Or__QPLUS_E__C_E_Opt:
>> {$$ = new Buf()}
>> | _O_QMINUS_E__Or__QPLUS_E__C {$$ = $1};
>>
>> Expression:
>> ConditionalOrExpression {$$ = $1}
>>
>> ConditionalOrExpression:
>> ConditionalAndExpression
>> {
>> yySparqlFrob->lex->select_lex.expr_list.push_front(new
> List<Item>);
>> }
>> _Q_O_QOR_E____QConditionalAndExpression_E__C_E_Star
>> {
>> List<Item> *list= yySparqlFrob->lex->select_lex.expr_list.pop();
>> if (list->elements)
>> {
>> list->push_front($1);
>> $$= new Item_cond_or(*list);
>> }
>> else
>> $$= $1;
>> delete list;
>> };
>>
>> _O_QOR_E____QConditionalAndExpression_E__C:
>> GT_OR ConditionalAndExpression
>> {
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> };
>>
>> _Q_O_QOR_E____QConditionalAndExpression_E__C_E_Star:
>> {}
>> | _Q_O_QOR_E____QConditionalAndExpression_E__C_E_Star
>> _O_QOR_E____QConditionalAndExpression_E__C {};
>>
>> ConditionalAndExpression:
>> ValueLogical
>> {
>> yySparqlFrob->lex->select_lex.expr_list.push_front(new
> List<Item>);
>> }
>> _Q_O_QAND_E____QValueLogical_E__C_E_Star
>> {
>> List<Item> *list= yySparqlFrob->lex->select_lex.expr_list.pop();
>> if (list->elements)
>> {
>> list->push_front($1);
>> $$= new Item_cond_and(*list);
>> }
>> else
>> $$= $1;
>> delete list;
>> };
>>
>> _O_QAND_E____QValueLogical_E__C:
>> GT_AND ValueLogical
>> {
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> };
>>
>> _Q_O_QAND_E____QValueLogical_E__C_E_Star:
>> {}
>> | _Q_O_QAND_E____QValueLogical_E__C_E_Star
>> _O_QAND_E____QValueLogical_E__C {};
>>
>> ValueLogical:
>> RelationalExpression {$$ = $1};
>>
>> RelationalExpression:
>> NumericExpression
>> {
>> // Stick " = 3 " into two list elements in the expr_list.
>> yySparqlFrob->lex->select_lex.expr_list.push_front(new
> List<Item>);
>> }
>>
> _Q_O_QEQUAL_E____QNumericExpression_E__Or__QNEQUAL_E____QNumericExpression_E__Or__QLT_E____QNumericExpression_E__Or__QGT_E____QNumericExpression_E__Or__QLE_E____QNumericExpression_E__Or__QGE_E____QNumericExpression_E__C_E_Opt
>> {
>> List<Item> *list= yySparqlFrob->lex->select_lex.expr_list.pop();
>> if (list->elements)
>> {
>> chooser_compare_func_creator op =
>> (chooser_compare_func_creator)list->pop();
>> Item* value = list->pop();
>> // chooser_compare_func_creator eq = &comp_eq_creator;
>> // Item* test = eq(0)->create($1, value);
>> $$= op(0)->create($1, value);
>> }
>> else
>> $$= $1;
>> delete list;
>> };
>>
>>
> _O_QEQUAL_E____QNumericExpression_E__Or__QNEQUAL_E____QNumericExpression_E__Or__QLT_E____QNumericExpression_E__Or__QGT_E____QNumericExpression_E__Or__QLE_E____QNumericExpression_E__Or__QGE_E____QNumericExpression_E__C:
>> GT_EQUAL NumericExpression
>> {
>>
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)comp_eq_creator);
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> }
>> | GT_NEQUAL NumericExpression
>> {
>>
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)comp_ne_creator);
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> }
>> | GT_LT NumericExpression
>> {
>>
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)comp_lt_creator);
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> }
>> | GT_GT NumericExpression
>> {
>>
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)comp_gt_creator);
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> }
>> | GT_LE NumericExpression
>> {
>>
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)comp_le_creator);
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> }
>> | GT_GE NumericExpression
>> {
>>
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)comp_ge_creator);
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> };
>>
>>
> _Q_O_QEQUAL_E____QNumericExpression_E__Or__QNEQUAL_E____QNumericExpression_E__Or__QLT_E____QNumericExpression_E__Or__QGT_E____QNumericExpression_E__Or__QLE_E____QNumericExpression_E__Or__QGE_E____QNumericExpression_E__C_E_Opt:
>> {}
>> |
>>
> _O_QEQUAL_E____QNumericExpression_E__Or__QNEQUAL_E____QNumericExpression_E__Or__QLT_E____QNumericExpression_E__Or__QGT_E____QNumericExpression_E__Or__QLE_E____QNumericExpression_E__Or__QGE_E____QNumericExpression_E__C {};
>>
>> NumericExpression:
>> AdditiveExpression {$$ = $1};
>>
>> AdditiveExpression:
>> MultiplicativeExpression
>> {
>> // Stick " + 3 " into two list elements in the expr_list.
>> yySparqlFrob->lex->select_lex.expr_list.push_front(new
> List<Item>);
>> }
>>
> _Q_O_QPLUS_E____QMultiplicativeExpression_E__Or__QMINUS_E____QMultiplicativeExpression_E__C_E_Star
>> {
>> List<Item> *list= yySparqlFrob->lex->select_lex.expr_list.pop();
>> if (list->elements)
>> {
>> // chooser_compare_func_creator *op =
>> (chooser_compare_func_creator*)list->pop();
>> char *op = (char*)list->pop();
>> Item* value = list->pop();
>> if (op[0] == '+') {
>> $$= new Item_func_plus($1, value);
>> } else {
>> $$= new Item_func_minus($1, value);
>> }
>> // $$= (*op)(0)->create($1, value);
>> }
>> else
>> $$= $1;
>> delete list;
>> };
>>
>>
> _O_QPLUS_E____QMultiplicativeExpression_E__Or__QMINUS_E____QMultiplicativeExpression_E__C:
>> GT_PLUS MultiplicativeExpression
>> {
>> //
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)&comp_plus_creator);
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)"+");
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> }
>> | GT_MINUS MultiplicativeExpression
>> {
>> //
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)&comp_minus_creator);
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)"-");
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> };
>>
>>
> _Q_O_QPLUS_E____QMultiplicativeExpression_E__Or__QMINUS_E____QMultiplicativeExpression_E__C_E_Star:
>> {}
>> |
>>
> _Q_O_QPLUS_E____QMultiplicativeExpression_E__Or__QMINUS_E____QMultiplicativeExpression_E__C_E_Star
>
>>
> _O_QPLUS_E____QMultiplicativeExpression_E__Or__QMINUS_E____QMultiplicativeExpression_E__C {};
>>
>> MultiplicativeExpression:
>> UnaryExpression
>> {
>> // Stick " * 3 " into two list elements in the expr_list.
>> yySparqlFrob->lex->select_lex.expr_list.push_front(new
> List<Item>);
>> }
>>
> _Q_O_QTIMES_E____QUnaryExpression_E__Or__QDIVIDE_E____QUnaryExpression_E__C_E_Star
>> {
>> List<Item> *list= yySparqlFrob->lex->select_lex.expr_list.pop();
>> if (list->elements)
>> {
>> // chooser_compare_func_creator *op =
>> (chooser_compare_func_creator*)list->pop();
>> char *op = (char*)list->pop();
>> Item* value = list->pop();
>> if (op[0] == '*') {
>> $$= new Item_func_mul($1, value);
>> } else {
>> $$= new Item_func_div($1, value);
>> }
>> // $$= (*op)(0)->create($1, value);
>> }
>> else
>> $$= $1;
>> delete list;
>> };
>>
>> _O_QTIMES_E____QUnaryExpression_E__Or__QDIVIDE_E____QUnaryExpression_E__C:
>> GT_TIMES UnaryExpression
>> {
>> //
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)&comp_times_creator);
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)"*");
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> }
>> | GT_DIVIDE UnaryExpression
>> {
>> //
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)&comp_divide_creator);
>>
> yySparqlFrob->lex->select_lex.expr_list.head()->push_back((Item*)"/");
>> yySparqlFrob->lex->select_lex.expr_list.head()->push_back($2);
>> };
>>
>>
> _Q_O_QTIMES_E____QUnaryExpression_E__Or__QDIVIDE_E____QUnaryExpression_E__C_E_Star:
>> {}
>> |
>>
> _Q_O_QTIMES_E____QUnaryExpression_E__Or__QDIVIDE_E____QUnaryExpression_E__C_E_Star
>> _O_QTIMES_E____QUnaryExpression_E__Or__QDIVIDE_E____QUnaryExpression_E__C {};
>>
>> UnaryExpression:
>> GT_NOT PrimaryExpression
>> {
>> new Item_func_not($2);
>> }
>> | GT_PLUS PrimaryExpression {$$ = $2}
>> | GT_MINUS PrimaryExpression
>> {
>> new Item_func_neg($2);
>> }
>> | PrimaryExpression {$$ = $1};
>>
>> PrimaryExpression:
>> BrackettedExpression {$$ = $1}
>> | BuiltInCall {$$ = $1}
>> | IRIrefOrFunction {$$ = $1}
>> | RDFLiteral {$$ = $1->get_item()}
>> | NumericLiteral {$$ = $1->get_item()}
>> | BooleanLiteral {$$ = $1->get_item()}
>> | BlankNode {$$ = $1->get_item()}
>> | Var {$$ = $1->get_item()};
>>
>> BrackettedExpression:
>> GT_LPAREN Expression GT_RPAREN {$$ = $2};
>>
>> BuiltInCall:
>> IT_STR GT_LPAREN Expression GT_RPAREN {$$ = $3; YYABORT /* !!! NI */}
>> | IT_LANG GT_LPAREN Expression GT_RPAREN {$$ = $3; YYABORT /* !!! NI
>> */}
>> | IT_LANGMATCHES GT_LPAREN Expression GT_COMMA Expression
>> GT_RPAREN {$$ = $3; YYABORT /* !!! NI */}
>> | IT_DATATYPE GT_LPAREN Expression GT_RPAREN {$$ = $3; YYABORT /* !!!
>> NI */}
>> | IT_BOUND GT_LPAREN Var GT_RPAREN {$$ = new
>> Item_func_isnotnull($3->get_item());}
>> | IT_isIRI GT_LPAREN Expression GT_RPAREN {$$ = $3; YYABORT /* !!! NI
>> */}
>> | IT_isURI GT_LPAREN Expression GT_RPAREN {$$ = $3; YYABORT /* !!! NI
>> */}
>> | IT_isBLANK GT_LPAREN Expression GT_RPAREN {$$ = $3; YYABORT /* !!!
>> NI */}
>> | IT_isLITERAL GT_LPAREN Expression GT_RPAREN {$$ = $3; YYABORT /* !!!
>> NI */}
>> | RegexExpression {$$ = $1};
>>
>> RegexExpression:
>> IT_REGEX GT_LPAREN Expression GT_COMMA Expression
>> _Q_O_QCOMMA_E____QExpression_E__C_E_Opt GT_RPAREN {$$ = $3; YYABORT /* !!!
>> NI */};
>>
>> _Q_O_QCOMMA_E____QExpression_E__C_E_Opt:
>> {$$ = NULL}
>> | _O_QCOMMA_E____QExpression_E__C {$$ = $1};
>>
>> IRIrefOrFunction:
>> IRIref _QArgList_E_Opt {$$ = NULL; // new
>> Item_func_call(yySparqlFrob->lex->current_context(), $1, $2); YYABORT /*
>> !!! NI */};
>>
>> _QArgList_E_Opt:
>> {$$ = NULL}
>> | ArgList {$$ = $1};
>>
>> RDFLiteral:
>> String _Q_O_QLANGTAG_E__Or__QDTYPE_E____QIRIref_E__C_E_Opt {$$ =
>> yySparqlFrob->ensure_string($1, $2) /* !!! */};
>>
>> _O_QDTYPE_E____QIRIref_E__C:
>> GT_DTYPE IRIref {$$ = $2};
>>
>> _O_QLANGTAG_E__Or__QDTYPE_E____QIRIref_E__C:
>> LANGTAG {$$ = $1}
>> | _O_QDTYPE_E____QIRIref_E__C {$$ = $1};
>>
>> _Q_O_QLANGTAG_E__Or__QDTYPE_E____QIRIref_E__C_E_Opt:
>> {$$ = NULL}
>> | _O_QLANGTAG_E__Or__QDTYPE_E____QIRIref_E__C {$$ = $1};
>>
>> NumericLiteral:
>> INTEGER {$$ = yySparqlFrob->ensure_int($1, NULL) /* !!! */}
>> | DECIMAL {$$ = yySparqlFrob->ensure_decimal($1, NULL) /* !!! */}
>> | DOUBLE {$$ = yySparqlFrob->ensure_float($1, NULL) /* !!! */};
>>
>> BooleanLiteral:
>> IT_true {$$ = $1}
>> | IT_false {$$ = $1};
>>
>> String:
>> STRING_LITERAL1 {$$ = $1}
>> | STRING_LITERAL2 {$$ = $1}
>> | STRING_LITERAL_LONG1 {$$ = $1}
>> | STRING_LITERAL_LONG2 {$$ = $1};
>>
>> IRIref:
>> Q_IRI_REF {$$ = yySparqlFrob->ensure_URI($1)}
>> | QName {$$ = $1};
>>
>> QName:
>> QNAME {$$ = yySparqlFrob->ensure_URI($1)}
>> | QNAME_NS {$$ = yySparqlFrob->ensure_URI($1)};
>>
>> BlankNode:
>> BLANK_NODE_LABEL {$$ = yySparqlFrob->ensure_blank_node($1.str)}
>> | ANON {$$ = yySparqlFrob->make_blank_node()};
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> %%
>>
>> #define YY_DECL int yyFlexLexer::yylex(YY_sparqlParser_STYPE *val, void
>> *yythd)
>> //int yylex(void *yylval, void *yythd);
>> const LEX_STRING null_lex_str={0,0};
>>
>>
>> int Simple_error (const char *format) {
>> my_printf_error(1, format, MYF(0));
>> return 1;
>> }
>>
>> int Item_error (const char *format, Item *item) {
>> String pString;
>> item->print(&pString);
>> my_printf_error(1, format, MYF(0), pString.c_ptr());
>> return 1;
>> }
>>
>> const char* scan_string (THD *thd, LEX_STRING *lex_string, const char
>> *start, const char *end, const char look_for) {
>> const char *ptr = end;
>> lex_string->length = 0;
>> for (; ; ) {
>> if (ptr == start) {
>> if (look_for) {
>> // we didn't find it
>> ptr = NULL;
>> lex_string->length = 0;
>> return NULL;
>> } else {
>> lex_string->str = thd->strmake(ptr, lex_string->length);
>> return ptr;
>> }
>> }
>> if (*ptr == look_for) {
>> --lex_string->length;
>> lex_string->str = thd->strmake(ptr+1, lex_string->length);
>> return ptr;
>> }
>> --ptr;
>> ++lex_string->length;
>> }
>> }
>>
>>
>> // -------------------------------------- START
>> #include "FlexLexer.h"
>> // -------------------------------------- END
>>
>> class sparqlParserPackage : public sparqlParser
>> {
>> private:
>> yyFlexLexer theScanner;
>> THD *thd;
>> public:
>> virtual int yylex();
>> virtual void yyerror(char *m);
>> sparqlParserPackage(THD *thd, char** ptr) : theScanner(thd, ptr) {
>> this->thd = thd;
>> };
>> };
>>
>> int sparqlParserPackage::sparqllex()
>> {
>> return theScanner.yylex(&yylval);
>> }
>>
>> void sparqlParserPackage::yyerror(char *s)
>> {
>> const char *yytext= theScanner.YYText(); // theScanner.get_last_word();
>> my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
>> (yytext ? (char*) yytext : ""),
>> theScanner.lineno());
>> }
>>
>> // Move this class definition into sparqlFrob.h and uncomment the #include
>> // below. See http://www.w3.org/1999/02/26-modules/User/Yacker#encap for
>> more
>> // details.
>> /* <sparqlFrob> */
>> sparqlFrob::sparqlFrob(THD *thd, char** ptr) : Dynamic_parser(thd, ptr)
>> {
>> // stringstream* ss = new stringstream(buf, stringstream::in);
>> // this->thd= thd;
>> lex= thd ? thd->lex : NULL;
>> distinct= false;
>> sparqlParserPackage* aCompiler= new sparqlParserPackage(thd, ptr);
>> parser= aCompiler;
>> next_union_alias_index= 0;
>> }
>> sparqlFrob::~sparqlFrob()
>> {
>> }
>>
>> int sparqlFrob::parse()
>> {
>> sparqlParserPackage* aCompiler = (sparqlParserPackage*) parser;
>> return aCompiler->yyparse(this);
>> }
>>
>> const char* sparqlFrob::get_primary_key(const char *table_name) {
>> TABLE_LIST *entry = lex->select_lex.context.table_list;
>> while (entry) {
>> if (!strcmp(table_name, entry->table_name)) {
>> KEY *key= entry->table->key_info;
>>
>> /* Search table structure for PRIMARY KEY.
>> Taken from sql_show.cc::2905 get_schema_stat_record */
>> for (unsigned i= 0; i < entry->table->s->keys; i++) {
>> if (!strcmp(key[i].name, "PRIMARY")) {
>> const char *ret = key[i].key_part->field->field_name;
>> if (key[i].key_parts != 1)
>> cout << "SPARQL: table \"" << table_name << "\" primary
> key has " <<
>> key[i].key_parts << " parts -- using only 1st field, \"" <<
> ret <<
>> "\"" << endl;
>> return ret;
>> }
>> }
>>
>> // Couldn't find PRIMARY KEY
>> const char *ret = entry->table->s->fieldnames.type_names[0];
>> cout << "SPARQL: could not find " << table_name <<
> ".<pk> -- trying
>> " << ret << endl;
>> return ret;
>> }
>> entry= entry->next_global;
>> }
>> my_printf_error(1, "SPARQL: could not find table entry for %s.
>> "PLS_REPORT, MYF(0), table_name);
>> return NULL;
>> }
>> LEX_STRING* sparqlFrob::next_union_alias () {
>> char space[3];
>> space[0]= 'U';
>> space[1]= '0'+next_union_alias_index++;
>> space[2]= 0;
>>
>> LEX_STRING *alias = new LEX_STRING;
>> alias->str= thd->strmake(space, 3);
>> alias->length = 2;
>> return alias;
>> }
>>
>>
>> Item_variable* sparqlFrob::ensure_variable (const char *var) {
>> return head_context()->get_binding_context()->
>> ensure_bound_item_variable(var, this, 1);
>> }
>>
>> Item_URI* sparqlFrob::ensure_URI (LEX_STRING uristr) {
>> Item_URI* ret;
>> List_iterator<Item_URI> item_list_it(uris);
>> while ((ret = item_list_it++))
>> {
>> if (!strcmp(ret->name, uristr.str)) { /* !!! */
>> return ret;
>> }
>> // if (curr_item->eq(this, 1))
>> // DBUG_RETURN(FALSE); /* Already in the set. */
>> }
>>
>> ret = new Item_URI(lex->current_context(), uristr, thd);
>> uris.push_back(ret);
>> return ret;
>> }
>>
>> Item_blank_node* sparqlFrob::make_blank_node () {
>> return new Item_blank_node(lex->current_context(), "", this);
>> }
>>
>> Item_blank_node* sparqlFrob::ensure_blank_node (const char *label) {
>> Item_blank_node* ret;
>> List_iterator<Item_blank_node> item_list_it(blank_nodes);
>> while ((ret = item_list_it++))
>> {
>> if (!strcmp(ret->name, label)) {
>> return ret;
>> }
>> // if (curr_item->eq(this, 1))
>> // DBUG_RETURN(FALSE); /* Already in the set. */
>> }
>>
>> ret = new Item_blank_node(lex->current_context(), label, this);
>> blank_nodes.push_back(ret);
>> return ret;
>> }
>> Item_literal_string* sparqlFrob::ensure_string (LEX_STRING str, Item_POS
>> *lang_or_datatype) {
>> Item_literal_string* ret;
>> List_iterator<Item_literal_string> item_list_it(strings);
>> while ((ret = item_list_it++))
>> if (!strncmp(ret->name, str.str, str.length) &&
>> ret->get_language_or_datatype() == lang_or_datatype) // !!! check len or
>> "foo1"="foo"
>> return ret;
>>
>> Item_string* d = new Item_string(str.str, str.length,
>> thd->variables.collation_connection);
>> Item_string* Iso = new Item_string(Iso8601formatStr,
>> strlen(Iso8601formatStr), &my_charset_bin);
>> Item_func_str_to_date* t = new Item_func_str_to_date(d, Iso); //
>> t->str_value
>> t->quick_fix_field();
>> t->fix_length_and_dec();
>> String* ptr = t->val_str(&Global_string);
>> if (ptr) {
>> LEX_STRING tmp;
>> tmp.length = ptr->length();
>> tmp.str = (char*) thd->strmake((char*) ptr->ptr(), tmp.length);;
>> ret = new Item_literal_string(tmp, lang_or_datatype, thd->charset());
>> } else {
>> ret = new Item_literal_string(str, lang_or_datatype, thd->charset());
>> }
>> strings.push_back(ret);
>> return ret;
>> }
>> Item_literal_int* sparqlFrob::ensure_int (LEX_STRING str, Item_POS
>> *lang_or_datatype) {
>> Item_literal_int* ret;
>> List_iterator<Item_literal_int> item_list_it(ints);
>> while ((ret = item_list_it++))
>> if (!strncmp(ret->name, str.str, str.length)) // !!! check len or
>> "foo1"="foo"
>> return ret;
>> ret = new Item_literal_int(str, lang_or_datatype, thd->charset());
>> ints.push_back(ret);
>> return ret;
>> }
>> Item_literal_decimal* sparqlFrob::ensure_decimal (LEX_STRING str, Item_POS
>> *lang_or_datatype) {
>> Item_literal_decimal* ret;
>> List_iterator<Item_literal_decimal> item_list_it(decimals);
>> while ((ret = item_list_it++))
>> if (!strncmp(ret->name, str.str, str.length)) // !!! check len or
>> "foo1"="foo"
>> return ret;
>> ret = new Item_literal_decimal(str, lang_or_datatype, thd->charset());
>> decimals.push_back(ret);
>> return ret;
>> }
>> Item_literal_float* sparqlFrob::ensure_float (LEX_STRING str, Item_POS
>> *lang_or_datatype) {
>> Item_literal_float* ret;
>> List_iterator<Item_literal_float> item_list_it(floats);
>> while ((ret = item_list_it++))
>> if (!strncmp(ret->name, str.str, str.length)) // !!! check len or
>> "foo1"="foo"
>> return ret;
>> ret = new Item_literal_float(str, lang_or_datatype, thd->charset());
>> floats.push_back(ret);
>> return ret;
>> }
>>
>> void sparqlFrob::select_variables () {
>> SELECT_LEX *sel= lex->current_select; sel->parsing_place=
>> SELECT_LIST;
>> print(&Global_string);
>> cout << Global_string.c_ptr();
>> Global_string.free();
>> BindingContext *bc = last_context()->get_binding_context();
>>
>> // If nothing was selected, we know there was a "SELECT *".
>> bool select_star= !lex->current_select->item_list.elements;
>>
>> /**************************
>> * Handle the subselects. *
>> **************************/
>>
>> // Walk the list of GraphContext sets
>> List_iterator<List<BindingGraphContext> > list_it(need_selects);
>> List<BindingGraphContext> *list;
>> while ((list= list_it++)) {
>>
>> // Assemble a list of selected variables.
>> List<Item_variable> selected_vars;
>>
>> // List of BindingGraphContexts that need newly added vars (starts
>> with ()).
>> List<BindingGraphContext> passed_gcs;
>>
>> // For each BindingGraphContext...
>> List_iterator<BindingGraphContext> gc_it(*list);
>> BindingGraphContext *gc;
>> while ((gc= gc_it++)) {
>>
>> // Walk variables bound in this context.
>> List<Item_variable> *known_vars=
>> gc->get_binding_context()->get_item_variables();
>> List_iterator<Item_variable> known_vars_it(*known_vars);
>> Item_variable *known_var;
>> while ((known_var= known_vars_it++)) {
>>
>> // If the variable has no in parents refs, skip it.
>> if (!select_star && known_var->outer_has_no_refs())
>> continue;
>>
>> // If the variable was already selected, skip it.
>> bool stupid_continue_flag= false; // C doesn't have a labeled continue.
>> List_iterator<Item_variable> selected_vars_it(selected_vars);
>> Item_variable *selected_var;
>> while ((selected_var= selected_vars_it++))
>> if (selected_var->same_variable(known_var->name)) {
>> stupid_continue_flag= true;
>> break;
>> }
>> if (stupid_continue_flag)
>> continue;
>>
>> // known_var is referenced in a parent context and not yet selected in
>> // this UNION.
>>
>> // Select in this gc...
>> gc->select_var(known_var, true);
>> // ...and all passed...
>> List_iterator<BindingGraphContext> passed_gcs_it(passed_gcs);
>> BindingGraphContext *passed_gc;
>> while ((passed_gc= passed_gcs_it++))
>> passed_gc->select_var(known_var, false);// also sets binding in parent.
>> // ...and future gcs.
>> List_iterator<BindingGraphContext> future_gcs_it= gc_it; // @@@ ca
>> marche?
>> BindingGraphContext *future_gc;
>> while ((future_gc= future_gcs_it++)) {
>> bool exists=
>>
> Item_variable::match_var_in_list(future_gc->get_binding_context()->get_item_variables(),
>
>> known_var->name) != NULL;
>> future_gc->select_var(known_var, exists);
>> }
>>
>> selected_vars.push_front(known_var); // It's selected now.
>> }
>> passed_gcs.push_front(gc);
>> }
>> }
>> if (select_star)
>> // Select known vars and update reference counts.
>> bc->select_star(thd);
>>
>> sel->parsing_place= NO_MATTER;
>> }
>>
>> void sparqlFrob::push_subject (Item_POS *subject) {
>> subjects.push_front(subject);
>> }
>>
>> Item_POS* sparqlFrob::pop_subject () {
>> return subjects.pop();
>> }
>>
>> void sparqlFrob::push_predicate (Item_POS *predicate) {
>> predicates.push_front(predicate);
>> }
>>
>> void sparqlFrob::pop_predicate () {
>> predicates.pop();
>> }
>>
>> bool sparqlFrob::object (Item_POS *object) {
>> Item_POS* subject = subjects.head();
>> if (!predicates.head()->is_URI())
>> return Item_error("predicate must be a URI, not \"%s\"",
>> predicates.head()->get_item());
>> Item_URI* predicate = (Item_URI*)predicates.head();
>> BindingContext *bc= head_context()->get_binding_context();
>> Alias_info *ai= bc->get_table_alias(thd, subject, predicate, object);
>> const char *ptr = head_context()->get_alias_string(ai, subject, thd);
>> if (!ptr)
>> return true;
>>
>> object->bind_field(predicate->get_table().str, ptr,
>> predicate->get_field().str, false, thd, NULL);
>> return false;
>> }
>>
>> bool sparqlFrob::type_list () {
>> return Simple_error("Lists not supported");
>> }
>>
>> bool sparqlFrob::add_listElement (Item_POS *item) {
>> return Item_error("Lists not supported -- can't add \"%s\"",
>> item->get_item());
>> }
>>
>> void sparqlFrob::print (String *str) {
>> str->append("sparqlFrob: ");
>> char ptrSpace[2 + sizeof(void*)*2 + 1];
>> sprintf(ptrSpace, "%p", this);
>> str->append(ptrSpace);
>> str->append(distinct ? " distinct\n" : "\n");
>> str->append("uris:\n");
>> List_iterator<Item_URI> uri_it(uris);
>> Item_URI *uri;
>> while ((uri= uri_it++)) {
>> str->append(" ");
>> uri->print(str);
>> str->append("\n");
>> }
>> str->append("subjects:\n");
>> List_iterator<Item_POS> subjects_it(subjects);
>> Item_POS *subject;
>> while ((subject= subjects_it++)) {
>> str->append(" ");
>> subject->print(str);
>> str->append("\n");
>> }
>> str->append("root_constraints:\n");
>> List_iterator<Item> root_constraints_it(root_constraints);
>> Item *root_constraint;
>> while ((root_constraint= root_constraints_it++)) {
>> str->append(" ");
>> root_constraint->print(str);
>> str->append("\n");
>> }
>> str->append("need_selects:\n");
>> List_iterator<List<BindingGraphContext> > list_it(need_selects);
>> List<BindingGraphContext> *list;
>> while ((list= list_it++)) {
>> str->append(" (\n");
>> List_iterator<BindingGraphContext> gc_it(*list);
>> BindingGraphContext *gc;
>> while ((gc= gc_it++)) {
>> str->append(" ");
>> sprintf(ptrSpace, "%p", gc);
>> str->append(ptrSpace);
>> str->append("\n");
>> }
>> str->append(" )\n");
>> }
>> }
>> /* </sparqlFrob> */
>>
>>
>> /* <Item_URI> */
>> Item_URI::Item_URI(Name_resolution_context *context_arg, LEX_STRING uri,
>> THD *thd) : Item_field(context_arg, NullS, NullS, uri.str),
>> Item_POS(this) {
>> const char* ptr = scan_string(thd, &value, name, name + uri.length,
>> '=');
>> if ((ptr = scan_string(thd, &field, name, ptr ? ptr : name + uri.length,
>> '.'))) {
>> scan_string(thd, &table, name, ptr ? ptr : name + uri.length, 0);
>> }
>> }
>> void Item_URI::bind_field(const char *table_name, const char *alias,
>> const char *field_name_arg, bool trump, THD *thd, TABLE_LIST *jt) {
>> LEX *lex= thd->lex;
>> SELECT_LEX *sel= lex->current_select;
>> chooser_compare_func_creator eq = &comp_eq_creator;
>> LEX_STRING value = get_value();
>> cout << "WHERE " << alias << "." << get_field().str
> << "=" << value.str
>> << endl;
>> Item* idI = new Item_field(lex->current_context(), NullS, alias,
>> get_field().str);
>> int error;
>> Item* val = new Item_int(value.str, (longlong) my_strtoll10(value.str,
>> NULL, &error), value.length);
>> Item* test = eq(0)->create(idI, val);
>> sel->expr_list.head()->push_back(test);
>> test->top_level_item();
>> if (jt) {
>> SELECT_LEX *sel= lex->current_select;
>> sel->add_joined_table(jt);
>> }
>> }
>> void Item_URI::print(String *str)
>> {
>> str->append('<');
>> str->append(name);
>> str->append('>');
>> }
>> /* </Item_URI> */
>>
>>
>> /* <Item_variable> */
>> Item_variable::Item_variable(Name_resolution_context *context_arg,
>> const char *variable_name, Item_variable *outer_arg, sparqlFrob
>> *frob_arg, int ref_count_arg) : Item_field(context_arg, NullS, NullS,
>> variable_name), Item_POS(this) {
>> set_name(variable_name, strlen(variable_name), system_charset_info);
>> is_autogenerated_name= FALSE;
>> nr_context= context_arg;
>> bound= false;
>> outer= outer_arg;
>> frob= frob_arg;
>> primary_key= false;
>> gc= frob->head_context();
>> jt= NULL;
>> ref_count= ref_count_arg;
>> }
>> Item* Item_variable::make_Item_field(Name_resolution_context *context_arg,
>> const char *db_arg,
>> const char *table_name_arg,
>> const char *field_name_arg, const char* real_table_name)
>> {
>> return field_name_arg ? new Item_field(context_arg, db_arg,
>> table_name_arg, field_name_arg) :
>> new Item_primary_key_field(context_arg, db_arg,
>> table_name_arg, frob, real_table_name);
>> }
>>
>> /* Item_field Virtual Overloads */
>> void Item_variable::make_field(Send_field *tmp_field) //
>> Protocol::send_fields
>> {
>> if (primary_key) {
>> init_make_field(tmp_field, FIELD_TYPE_STRING);
>> } else {
>> Item_field::make_field(tmp_field);
>> }
>> }
>> bool Item_variable::fix_fields(THD *thd, Item **reference)
>> {
>> if (primary_key)
>> if (!(field_name = get_primary_key()))
>> return true; // signal an error
>> return Item_field::fix_fields(thd, reference);
>> }
>> /* virtual overload of Item::send, which is called when serializing the
>> results.
>> */
>> bool Item_variable::send(Protocol *protocol, String *buffer)
>> {
>> if (primary_key) {
>> String *res;
>> if ((res=val_str(buffer))) {
>> // Return something in the form of "<Orders.id=2186>".
>> size_t len =
>> 1+strlen(real_table_name)+1+strlen(field_name)+1+res->length()+1;
>> // Assume res->charset() is compatible with ASCII.
>> // Otherwise, we'd need to convert names et all to res->charset().
>> char space[len+1];
>> space[0] = '<';
>> strcpy(space+1, real_table_name);
>> strcat(space, ".");
>> strcat(space, field_name);
>> strcat(space, "=");
>> strncat(space, res->ptr(), res->length());
>> space[len-1] = '>';
>> space[len] = 0;
>> return protocol->store(space,len,res->charset());
>> } else
>> return protocol->store_null();
>> } else {
>> switch (field_type()) {
>> case MYSQL_TYPE_TIMESTAMP:
>> case MYSQL_TYPE_DATETIME:
>> Item_string* Iso = new Item_string(Iso8601formatStr,
>> strlen(Iso8601formatStr), &my_charset_bin);
>> Item * t = new Item_func_date_format(this, Iso, 0); // result_field
>> t->quick_fix_field();
>> String* ptr = t->val_str(&Global_string);
>> Field_datetime* f = new Field_datetime((bool)0, ptr->ptr(),
>> &my_charset_bin);
>>
>> // return protocol->store(f);
>> }
>> return protocol->store(result_field);
>> }
>> }
>>
>> /* Item_POS Virtual Overloads */
>> void Item_variable::bind_field(const char *table_name_arg, const char
>> *alias, const char *field_name_arg, bool trump, THD
>> *thd, TABLE_LIST *jt_param) {
>> LEX *lex= thd->lex;
>> if (jt_param && (!jt || trump)) {
>> // assert(!jt);
>> jt = jt_param;
>> SELECT_LEX *sel= lex->current_select;
>> sel->add_joined_table(jt);
>> }
>> if (jt && bound) {
>> cout << " ON " << table_name << "." << (primary_key ?
> "<pk>" :
>> field_name) << " = " << alias << "." << (field_name_arg ?
> field_name_arg :
>> "<pk>") << endl; // !!!
>> Item* l = make_Item_field(lex->current_context(), NullS, table_name,
>> primary_key ? NULL : field_name, real_table_name);
>> Item* r = make_Item_field(lex->current_context(), NullS, alias,
>> field_name_arg, table_name_arg);
>> chooser_compare_func_creator eq = &comp_eq_creator;
>> Item* on = eq(0)->create(l, r);
>> add_join_on(jt, on);
>> }
>> if (!bound || trump) {
>> cout << " " << alias << "." << (field_name_arg ?
> field_name_arg :
>> "<pk>") << " AS \"" << name << "\"" << endl;
>> table_name = (char*) alias;
>> if (field_name_arg) {
>> field_name = (char*) field_name_arg;
>> primary_key = false;
>> } else {
>> primary_key = true;
>> real_table_name = table_name_arg;
>> }
>> bound = true;
>> // name = (char*) field_name;
>> }
>> }
>>
>> /* SparqlFrob interface */
>> Item_variable* Item_variable::match_var_in_list (List<Item_variable>
>> *p_item_variables, const char *var) {
>> List_iterator<Item_variable> item_list_it(*p_item_variables);
>> Item_variable* ret;
>> while ((ret= item_list_it++))
>> if (ret->same_variable(var)) {
>> return ret;
>> }
>> return NULL;
>> }
>>
>> /* BindingContext interface */
>> Item* Item_variable::get_null_item() {
>> Item *ret= new Item_null();
>> ret->set_name(name, strlen(name), system_charset_info);
>> ret->is_autogenerated_name= FALSE;
>> return ret;
>> }
>>
>> /* debugging */
>> void Item_variable::print(String *str)
>> {
>> Item::print(str);
>> str->append("{?");
>> str->append(name);
>> str->append('}');
>> }
>> /* </Item_variable> */
>>
>>
>> /* <Item_blank_node> */
>> void Item_blank_node::print(String *str)
>> {
>> Item::print(str);
>> str->append("[_:");
>> str->append(name);
>> str->append(']');
>> }
>> /* </Item_blank_node> */
>>
>>
>> /* <Item_literal_string> */
>> void Item_literal_string::bind_field(const char *table_name, const char
>> *alias, const char *field_name_arg, bool trump, THD
>> *thd, TABLE_LIST *jt) {
>> cout << "WHERE " << alias << "." << field_name_arg
> << "=\"" << name <<
>> "\"" << endl;
>> LEX *lex= thd->lex;
>> Item* idI = new Item_field(lex->current_context(), NullS, alias,
>> field_name_arg);
>> chooser_compare_func_creator eq = &comp_eq_creator;
>> Item* test = eq(0)->create(idI, get_item());
>> SELECT_LEX *sel= lex->current_select;
>> sel->expr_list.head()->push_back(test);
>> test->top_level_item();
>> if (jt) {
>> sel->add_joined_table(jt);
>> }
>> }
>> void Item_literal_string::print(String *str)
>> {
>> str->append('\'');
>> str->append(name);
>> str->append('\'');
>> }
>> /* </Item_literal_string> */
>>
>>
>> /* <Item_literal_int> */
>> void Item_literal_int::bind_field(const char *table_name, const char
>> *alias, const char *field_name_arg, bool trump, THD *thd,
>> TABLE_LIST *jt) {
>> cout << "WHERE " << alias << "." << field_name_arg
> << "=\"" << name <<
>> "\"" << endl;
>> LEX *lex= thd->lex;
>> Item* idI = new Item_field(lex->current_context(), NullS, alias,
>> field_name_arg);
>> chooser_compare_func_creator eq = &comp_eq_creator;
>> Item* test = eq(0)->create(idI, get_item());
>> SELECT_LEX *sel= lex->current_select;
>> sel->expr_list.head()->push_back(test);
>> test->top_level_item();
>> if (jt) {
>> sel->add_joined_table(jt);
>> }
>> }
>> void Item_literal_int::print(String *str)
>> {
>> str->append(name);
>> }
>> /* </Item_literal_int> */
>>
>>
>> /* <Item_literal_decimal> */
>> void Item_literal_decimal::bind_field(const char *table_name, const char
>> *alias, const char *field_name_arg, bool trump, THD
>> *thd, TABLE_LIST *jt) {
>> cout << "WHERE " << alias << "." << field_name_arg
> << "=\"" << name <<
>> "\"" << endl;
>> LEX *lex= thd->lex;
>> Item* idI = new Item_field(lex->current_context(), NullS, alias,
>> field_name_arg);
>> chooser_compare_func_creator eq = &comp_eq_creator;
>> Item* test = eq(0)->create(idI, get_item());
>> SELECT_LEX *sel= lex->current_select;
>> sel->expr_list.head()->push_back(test);
>> test->top_level_item();
>> if (jt) {
>> sel->add_joined_table(jt);
>> }
>> }
>> void Item_literal_decimal::print(String *str)
>> {
>> str->append(name);
>> }
>> /* </Item_literal_decimal> */
>>
>>
>> /* <Item_literal_float> */
>> void Item_literal_float::bind_field(const char *table_name, const char
>> *alias, const char *field_name_arg, bool trump, THD *thd,
>> TABLE_LIST *jt) {
>> cout << "WHERE " << alias << "." << field_name_arg
> << "=\"" << name <<
>> "\"" << endl;
>> LEX *lex= thd->lex;
>> Item* idI = new Item_field(lex->current_context(), NullS, alias,
>> field_name_arg);
>> chooser_compare_func_creator eq = &comp_eq_creator;
>> Item* test = eq(0)->create(idI, get_item());
>> SELECT_LEX *sel= lex->current_select;
>> sel->expr_list.head()->push_back(test);
>> test->top_level_item();
>> if (jt) {
>> sel->add_joined_table(jt);
>> }
>> }
>> void Item_literal_float::print(String *str)
>> {
>> str->append(name);
>> }
>> /* </Item_literal_float> */
>>
>>
>> /* <Item_primary_key_field> */
>> Item_primary_key_field::Item_primary_key_field (
>> Name_resolution_context *context_arg,
>> const char *db_arg, const char *table_name_arg, sparqlFrob
>> *frob_arg, const char* real_table_name_arg) :
>> Item_field(context_arg, db_arg, table_name_arg, "<pk>") {
>> frob = frob_arg;
>> real_table_name= real_table_name_arg;
>> }
>> bool Item_primary_key_field::fix_fields(THD *thd, Item **reference) {
>> field_name = frob->get_primary_key(real_table_name);
>> return Item_field::fix_fields(thd, reference);
>> }
>> /* </Item_primary_key_field> */
>>
>>
>> /* <BindingContext> */
>> void BindingContext::select_star (THD *thd) {
>> List_iterator<Item_variable> list_it(item_variables);
>> Item_variable *ptr;
>> while ((ptr= list_it++))
>> add_item_to_list(thd, ptr);
>> }
>> Alias_info* BindingContext::get_table_alias (THD *thd, Item_POS *s,
>> Item_URI *p, Item_POS *o) {
>> LEX_STRING table = p->get_table();
>> Alias_info *ai = NULL;
>> List_iterator<Alias_info> item_list_it(aliases);
>> Alias_info *t;
>> while ((t = item_list_it++)) {
>> if (t->same_table(table)) {
>> ai = t;
>> break;
>> }
>> }
>> if (!ai) {
>> ai = new Alias_info(table);
>> aliases.push_front(ai);
>> }
>> return ai;
>> }
>>
>> /* ref_count -- 0: child context looking for the variable in a parent
>> context.
>> 1: normal use
>> */
>> Item_variable* BindingContext::ensure_bound_item_variable (const char
>> *var, sparqlFrob *sparql_frob, int ref_count) {
>> List_iterator<Item_variable> item_list_it(item_variables);
>> Item_variable* ret;
>> while ((ret= item_list_it++))
>> if (ret->same_variable(var)) {
>> ret->add_ref_count(ref_count);
>> return ret;
>> }
>>
>> Item_variable *outer= parent ? parent->ensure_bound_item_variable(var,
>> sparql_frob, 0) : NULL;
>> ret= new Item_variable(name_res_context, var, outer, sparql_frob,
>> ref_count);
>> item_variables.push_back(ret);
>>
>> return ret;
>> }
>>
>> Item* BindingContext::get_bound_variable_constraints (Item
>> *conjunction_constraints, GraphContext *gc) {
>> // Will need to write down our created constraints
>> List<Item> nulls;
>> List<Item> notNulls;
>> // return NULL;
>> // Walk the list of our introduced variables.
>> List_iterator<Item_variable> item_list_it(item_variables);
>> Item_variable *t;
>> while ((t = item_list_it++)) {
>> if (gc->is_optional()) {
>> nulls.push_front(new Item_func_isnull(t));
>> }
>> notNulls.push_front(new Item_func_isnotnull(t));
>> }
>> if (conjunction_constraints)
>> notNulls.push_front(conjunction_constraints);
>> Item *nulls_cond = nulls.elements ? new Item_cond_and(nulls) : NULL;
>> Item *notNulls_cond = notNulls.elements ? new Item_cond_and(notNulls) :
>> NULL;
>> if (nulls_cond && notNulls_cond) {
>> List<Item> *or_cond = new List<Item>;
>> or_cond->push_front(nulls_cond);
>> or_cond->push_front(notNulls_cond);
>> return new Item_cond_or(*or_cond);
>> }
>> // It is impossible that we have nulls and no notNulls to return
>> notNulls.
>> return notNulls_cond;
>> }
>> void BindingContext::start_constraints () {
>> mysql_init_select(lex);
>> name_res_context= lex->current_context();
>> constraints= new List<Item>;
>> lex->select_lex.expr_list.push_front(constraints); // current_select->
>> }
>> /* </BindingContext> */
>>
>>
>> /* <GraphContext> */
>> const char* GraphContext::get_alias_string (Alias_info *ai, Item_POS *s,
>> THD *thd) {
>> List_iterator<Item_POS> item_list_it(ai->subjects);
>> Item_POS *t;
>> size_t i= 0;
>> bool found= false;
>> while ((t= item_list_it++)) {
>> if (t == s) {
>> found= true;
>> break;
>> }
>> ++i;
>> }
>> char space[ai->table.length+1+1+1];
>> strncpy(space, ai->table.str, ai->table.length);
>> space[ai->table.length]= '_';
>> space[ai->table.length+1]= '0'+i;
>> space[ai->table.length+2]= 0;
>> const char *ret= thd->strmake(space, ai->table.length+1+1+1);
>> if (!found) {
>> ai->subjects.push_front(s);
>> Table_ident* table_i= new Table_ident(ai->table);
>> LEX *lex= thd->lex;
>> SELECT_LEX* sel= lex->current_select; // &lex->select_lex;
>> LEX_STRING *alias= new LEX_STRING;
>> alias->str= (char*)ret;
>> alias->length= ai->table.length+2;
>> cout << "FROM " << ai->table.str << " AS " <<
> alias->str << endl;
>> TABLE_LIST *jt= sel->add_table_to_list(lex->thd, table_i, alias,
>> sel->get_table_join_options(),
>> lex->lock_option,
>> sel->pop_index_hints());
>> if (!jt)
>> return NULL;
>> if (is_optional())
>> jt->outer_join|=JOIN_TYPE_LEFT;
>> if (s->is_URI()) {
>> Item_URI *sURI= (Item_URI*)s;
>> chooser_compare_func_creator eq= &comp_eq_creator;
>> LEX_STRING value= sURI->get_value();
>> cout << "WHERE " << alias->str << "." <<
> sURI->get_field().str <<
>> "=" << value.str << endl;
>> Item* idI= new Item_field(lex->current_context(), NullS, alias->str,
>
>> sURI->get_field().str);
>> int error;
>> Item* val= new Item_int(value.str, (longlong)
>> my_strtoll10(value.str, NULL, &error), value.length);
>> Item* test= eq(0)->create(idI, val);
>> sel->expr_list.head()->push_back(test);
>> test->top_level_item();
>> sel->add_joined_table(jt);
>> } else if (s->is_variable()) {
>> s->bind_field(ai->table.str, ret, NULL, true, thd, jt);
>> }
>> }
>> return ret;
>> }
>> /* </GraphContext> */
>>
>>
>> /* <BindingGraphContext> */
>> BindingGraphContext::BindingGraphContext (GraphContext *parent_param,
>> sparqlFrob *sparql_frob_param) : GraphContext (parent_param,
>> sparql_frob_param) {
>> bindings= new BindingContext(this, parent ?
>> parent->get_binding_context() : NULL, sparql_frob->lex);
>> current_select= NULL;
>> }
>> void BindingGraphContext::select_var (Item_variable *var, bool exists) {
>> cout << (void*)this << " SELECTs " << (exists ? "" : "NULL AS
> ") <<
>> var->name << endl;
>> current_select->add_item_to_list(thd, exists ? var->get_item() :
>
>> var->get_null_item());
>> }
>> /* </BindingGraphContext> */
>>
>>
>> /* <RootGraphContext> */
>> RootGraphContext::RootGraphContext (GraphContext *parent,
>> sparqlFrob *sparql_frob) : BindingGraphContext(parent, sparql_frob) {
>> bindings->start_constraints();
>> current_select= sparql_frob->lex->current_select;
>> }
>> /* </RootGraphContext> */
>>
>>
>> /* <Union1GraphContext> */
>> Union1GraphContext::Union1GraphContext (GraphContext *parent,
>> sparqlFrob *sparql_frob) : BindingGraphContext(parent, sparql_frob)
>> {
>> LEX *lex= thd->lex;
>> lex->current_select->init_nested_join(thd);
>> lex->current_select->end_nested_join(thd);
>> lex->derived_tables|= DERIVED_SUBQUERY;
>> mysql_new_select(lex, 1);
>> current_select= sparql_frob->lex->current_select;
>> bindings->start_constraints();
>> lex->current_select->linkage= DERIVED_TABLE_TYPE;
>> }
>> void Union1GraphContext::close () {
>> thd->lex->current_select->init_nested_join(thd);
>> // thd->lex->current_select->init_nested_join(thd);
>> thd->lex->current_select->end_nested_join(thd);
>> bindings->end_and_check_constraints();
>> }
>> /* </Union1GraphContext> */
>>
>>
>> /* <Union1GraphContext> */
>> Union2GraphContext::Union2GraphContext (GraphContext *parent,
>> sparqlFrob *sparql_frob) : BindingGraphContext(parent, sparql_frob)
>> {
>> left= (BindingGraphContext*)sparql_frob->last_context();
>> LEX *lex= thd->lex;
>>
>> lex->current_select = left->current_select; // next function called with
>
>> left select
>> if (mysql_new_select(lex, 0)) // sets the new lex->current_select
>> assert(0);
>> current_select= sparql_frob->lex->current_select;
>> bindings->start_constraints();
>> lex->current_select->linkage=UNION_TYPE;
>> if (sparql_frob->get_distinct()) /* UNION DISTINCT - remember position
>> */
>> lex->current_select->master_unit()->union_distinct=
>> lex->current_select;
>> }
>> void Union2GraphContext::close () {
>> LEX *lex= thd->lex;
>>
>> lex->pop_context();
>> SELECT_LEX *sel= lex->current_select;
>> SELECT_LEX_UNIT *unit= sel->master_unit();
>> lex->current_select= sel= unit->outer_select();
>> TABLE_LIST *t;
>> if (!(t = sel->
>> add_table_to_list(thd, new Table_ident(unit),
>> sparql_frob->next_union_alias(), 0,
>> TL_READ,(List<Index_hint> *)0,
>> (LEX_STRING *)0)))
>> assert(0);
>> sel->add_joined_table(t);
>> lex->pop_context();
>>
>> Item *as= ((Union1GraphContext*)left)->map_variables_to_outer_context();
>> cout << "SPARQL: close Union2 {" << endl << buf->str()
> << "}" << endl;
>> bindings->end_and_check_constraints();
>> }
>> /* </Union1GraphContext> */
>>
>>
>> Item_URI *XSD_integer= NULL;
>> Item_URI *XSD_float= NULL;
>> Item_URI *XSD_decimal= NULL;
>> String Global_string;
>>
>> t_initialize initialize;
>> Dynamic_parser* initialize(THD *thd, char **ptr) {
>> return new sparqlFrob(thd, ptr);
>> }
>>
>>
>> /* <Buf> */
>> Buf::Buf(char *str) {
>> len = strlen(str);
>> data = new char[len+1];
>> strncpy(data, str, len);
>> data[len] = 0;
>> }
>> /* Build a space-separated concatonation of bufs. */
>> Buf::Buf(int count, ...) {
>> va_list bufs;
>> const Buf *src;
>>
>> // This is inefficient for a single buf as the created buf could
>> // just steal the other buf's data pointer and delete it.
>>
>> // Walk args to find the total len.
>> len = -1;
>> va_start(bufs, count);
>> for (int i = 0; i < count; i++) {
>> src = va_arg(bufs, Buf*);
>> len += src->len+1;
>> }
>> va_end(bufs);
>>
>> data = new char[len+1];
>>
>> // Walk args to fill the data buffer.
>> len = -1;
>> va_start(bufs, count);
>> for (int i = 0; i < count; i++) {
>> src = va_arg(bufs, Buf*);
>> strncpy(data + len+1, src->data, src->len);
>> len += src->len+1;
>> data[len] = ' ';
>> delete src;
>> src = 0;
>> }
>> va_end(bufs);
>> data[len] = 0;
>> }
>> /* </Buf> */
>>
>> // $Log: sparqlParser.yy,v $
>> // Revision 1.9 2007/09/05 18:40:30 eric
>> // ~ derive from Dynamic_parser
>> // ~ follow meakly behind API changes in MySQL
>> //
>> // Revision 1.8 2007/07/10 12:34:18 eric
>> // + parse ISO6801 datetimes
>> //
>> // Revision 1.7 2007/07/08 21:30:10 eric
>> // ~ surface re-org
>> //
>> // Revision 1.6 2007/07/08 18:20:45 eric
>> // + field_type
>> // + make_field
>> // ~ get primary key from "lex->select_lex" instead of recently private
>> "lex"
>> // ~ simplify Item_variable::send - have Item_field side call
>> protocol->store(result_field) instead of emulating it
>> //
>> // Revision 1.5 2006/12/17 15:45:34 eric
>> // + Assemble result values into RDF-like literals:
>> // put ""'s round strings and misc data types
>> // add ^^xsd:dateTime etc. to timeish datatypes
>> // send integers as bare numbers
>> //
>> // Left to do: handle float, double, decimal.
>> //
>> // Revision 1.4 2006/12/17 15:22:01 eric
>> // + sparqlFrob::print(String*)
>> // ~ rearranged
>> //
>> // Revision 1.3 2006/12/16 14:08:23 eric
>> // ~ beacoup aesthetic changes
>> // ~ s/Item_POS_/Item_literal_/g
>> //
>> // Revision 1.2 2006/12/16 02:22:40 eric
>> // + primary keys return the URI identifying their tuple (as they are
>> written in queries)
>> //
>> // Revision 1.1 2006/12/15 14:45:17 eric
>> // import from cvs://cvs.w3.org/WWW/2005/05/22-SPARQL-MySQL/
>> //
>> // Revision 1.35 2006/05/26 18:49:51 eric
>> // progress on UNIONs
>> //
>> // Revision 1.34 2006/05/23 09:05:24 eric
>> // UNION fleshed out, needs debugging
>> //
>> // Revision 1.33 2006/05/11 19:15:47 eric
>> // first pass at BindingContext architecture
>> //
>> // Revision 1.32 2006/05/01 06:39:56 eric
>> // + tollerance for foreign key ambiguity
>> // ~ valgrind: free[], initialize Item_variable::jt
>> //
>> // Revision 1.31 2006/04/29 22:06:17 eric
>> // + INTEGER
>> // + DECIMAL
>> // + DOUBLE (well, Item_float)
>> //
>> // Revision 1.30 2006/04/29 21:08:26 eric
>> // - pruning
>> // ~ fixed strncmp (erroneous match on substring) error and marked another
>> // - YYTHD macros
>> //
>> // Revision 1.29 2006/04/29 16:53:27 eric
>> // ~ simplified get_primary_key (complicated by previous extension tables
>> commit)
>> //
>> // Revision 1.28 2006/04/29 16:45:03 eric
>> // + extension tables (tables with the same primary key as another -- both
>> are likely to be ?s)
>> //
>> // Revision 1.27 2006/04/23 01:34:25 eric
>> // ~ OPTIONAL using nested JOINs
>> //
>> // Revision 1.26 2006/04/17 09:53:57 eric
>> // + postpone putting variables in a context until we have the context
>> //
>> // Revision 1.25 2006/04/17 01:13:22 eric
>> // + OPTIONAL
>> //
>> // Revision 1.24 2006/04/16 23:29:00 eric
>> // + start on OPTIONALS
>> //
>> // Revision 1.23 2006/04/16 11:23:16 eric
>> // + DISTINCT
>> // + ORDER BY
>> // + LIMIT
>> // + OFFSET
>> //
>> // Revision 1.22 2006/04/16 08:44:03 eric
>> // + labeled blank nodes
>> //
>> // Revision 1.21 2006/04/15 20:27:59 eric
>> // + active POS casting to make exprs work
>> //
>> // Revision 1.20 2006/04/15 16:18:12 eric
>> // - cleaned slightly
>> //
>> // Revision 1.19 2006/04/15 15:32:20 eric
>> // + late-binding primary keys
>> //
>> // Revision 1.18 2006/04/13 23:52:11 eric
>> // + framed out Item_primary_key_field
>> // + expr on down compiling -- need to re-derive POS_string from a
>> constant Item_ class
>> //
>> // Revision 1.17 2006/04/12 16:24:35 eric
>> // + using sel->expr_list to collect outermost WHERE conjunction
>> //
>> // Revision 1.16 2006/04/12 14:48:03 eric
>> // - reduced casting
>> //
>> // Revision 1.15 2006/04/11 13:20:02 eric
>> // + parser errors => YYABORT
>> //
>> // Revision 1.14 2006/04/11 11:46:45 eric
>> // added CVS tags
>> //
>> //
>> ------------------------------------------------------------------------
>>
>> %{ #ifndef FLEXFIX
>> #define FLEXFIX YY_sparqlParser_STYPE *val
>> #define FLEXFIX2 val
>> #endif
>> #include "sparqlParser.h"
>>
>> #define YY_INPUT(buf,result,max_size) \
>> if ( (result = LexerReadStatic( (char *) buf, max_size )) < 0 ) \
>> YY_FATAL_ERROR( "input in flex scanner failed" );
>> %}
>>
>> IT_BASE "BASE"
>> IT_PREFIX "PREFIX"
>> IT_SELECT "SELECT"
>> IT_DISTINCT "DISTINCT"
>> GT_TIMES "*"
>> IT_CONSTRUCT "CONSTRUCT"
>> IT_DESCRIBE "DESCRIBE"
>> IT_ASK "ASK"
>> IT_FROM "FROM"
>> IT_NAMED "NAMED"
>> IT_WHERE "WHERE"
>> IT_ORDER "ORDER"
>> IT_BY "BY"
>> IT_ASC "ASC"
>> IT_DESC "DESC"
>> IT_LIMIT "LIMIT"
>> IT_OFFSET "OFFSET"
>> GT_LCURLEY "{"
>> GT_RCURLEY "}"
>> GT_DOT "."
>> IT_OPTIONAL "OPTIONAL"
>> IT_GRAPH "GRAPH"
>> IT_UNION "UNION"
>> IT_FILTER "FILTER"
>> GT_COMMA ","
>> GT_LPAREN "("
>> GT_RPAREN ")"
>> GT_SEMI ";"
>> IT_a "a"
>> GT_LBRACKET "\["
>> GT_RBRACKET "\]"
>> GT_MINUS "-"
>> GT_PLUS "+"
>> GT_OR "||"
>> GT_AND "&&"
>> GT_EQUAL "="
>> GT_NEQUAL "!="
>> GT_LT "<"
>> GT_GT ">"
>> GT_LE "<="
>> GT_GE ">="
>> GT_DIVIDE "/"
>> GT_NOT "!"
>> IT_STR "STR"
>> IT_LANG "LANG"
>> IT_LANGMATCHES "LANGMATCHES"
>> IT_DATATYPE "DATATYPE"
>> IT_BOUND "BOUND"
>> IT_isIRI "isIRI"
>> IT_isURI "isURI"
>> IT_isBLANK "isBLANK"
>> IT_isLITERAL "isLITERAL"
>> IT_REGEX "REGEX"
>> GT_DTYPE "^^"
>> IT_true "true"
>> IT_false "false"
>>
> Q_IRI_REF "<"(([!-&(-;=?-\]_a-z~-\x7F]|([\xC2-\xDF][\x80-\xBF])|(\xE0([\xA0-\xBF][\x80-\xBF]))|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|(\xED([\x80-\x9F][\x80-\xBF]))|([\xEE-\xEF][\x80-\xBF][\x80-\xBF])|(\xF0([\x90-\xBF][\x80-\xBF][\x80-\xBF]))|([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF])|(\xF4([\x80-\x8E][\x80-\xBF][\x80-\xBF])|(\x8F([\x80-\xBE][\x80-\xBF])|(\xBF[\x80-\xBE])))]))*">"
>> LANGTAG "@"([A-Za-z])+(("-"([0-9A-Za-z])+))*
>> INTEGER ([0-9])+
>> DECIMAL (([0-9])+"."([0-9])*)|("."([0-9])+)
>> EXPONENT [Ee]([+-])?([0-9])+
>>
> DOUBLE (([0-9])+"."([0-9])*({EXPONENT}))|(("."(([0-9]))+({EXPONENT}))|((([0-9]))+({EXPONENT})))
>> ECHAR "\\"[\"'\\bfnrt]
>> HEX ([0-9])|(([A-F])|([a-f]))
>>
> UCHAR "\\"(("u"({HEX})({HEX})({HEX})({HEX}))|("U"({HEX})({HEX})({HEX})({HEX})({HEX})({HEX})({HEX})({HEX})))
>>
> STRING_LITERAL1 "'"(((([\x00-\t\x0B-\x0C\x0E-&(-\[\]-\x7F]|([\xC2-\xDF][\x80-\xBF])|(\xE0([\xA0-\xBF][\x80-\xBF]))|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|(\xED([\x80-\x9F][\x80-\xBF]))|([\xEE-\xEF][\x80-\xBF][\x80-\xBF])|(\xF0([\x90-\xBF][\x80-\xBF][\x80-\xBF]))|([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF])|(\xF4([\x80-\x8E][\x80-\xBF][\x80-\xBF])|(\x8F([\x80-\xBE][\x80-\xBF])|(\xBF[\x80-\xBE])))]))|((({ECHAR}))|(({UCHAR})))))*"'"
>>
> STRING_LITERAL2 "\""(((([\x00-\t\x0B-\x0C\x0E-!#-\[\]-\x7F]|([\xC2-\xDF][\x80-\xBF])|(\xE0([\xA0-\xBF][\x80-\xBF]))|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|(\xED([\x80-\x9F][\x80-\xBF]))|([\xEE-\xEF][\x80-\xBF][\x80-\xBF])|(\xF0([\x90-\xBF][\x80-\xBF][\x80-\xBF]))|([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF])|(\xF4([\x80-\x8E][\x80-\xBF][\x80-\xBF])|(\x8F([\x80-\xBE][\x80-\xBF])|(\xBF[\x80-\xBE])))]))|((({ECHAR}))|(({UCHAR})))))*"\""
>>
> STRING_LITERAL_LONG1 "'''"((((("'")|("''")))?(([\x00-&(-\[\]-\x7F]|([\xC2-\xDF][\x80-\xBF])|(\xE0([\xA0-\xBF][\x80-\xBF]))|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|(\xED([\x80-\x9F][\x80-\xBF]))|([\xEE-\xEF][\x80-\xBF][\x80-\xBF])|(\xF0([\x90-\xBF][\x80-\xBF][\x80-\xBF]))|([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF])|(\xF4([\x80-\x8E][\x80-\xBF][\x80-\xBF])|(\x8F([\x80-\xBE][\x80-\xBF])|(\xBF[\x80-\xBE])))])|((({ECHAR}))|(({UCHAR}))))))*"'''"
>>
> STRING_LITERAL_LONG2 "\"\"\""((((("\"")|("\"\"")))?(([\x00-!#-\[\]-\x7F]|([\xC2-\xDF][\x80-\xBF])|(\xE0([\xA0-\xBF][\x80-\xBF]))|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|(\xED([\x80-\x9F][\x80-\xBF]))|([\xEE-\xEF][\x80-\xBF][\x80-\xBF])|(\xF0([\x90-\xBF][\x80-\xBF][\x80-\xBF]))|([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF])|(\xF4([\x80-\x8E][\x80-\xBF][\x80-\xBF])|(\x8F([\x80-\xBE][\x80-\xBF])|(\xBF[\x80-\xBE])))])|((({ECHAR}))|(({UCHAR}))))))*"\"\"\""
>> WS (" ")|(("\t")|(("\r")|("\n")))
>> NIL "("(({WS}))*")"
>> ANON "\["(({WS}))*"\]"
>>
> NCCHAR1p ([A-Z])|(([a-z])|(((\xC3[\x80-\x96]))|(((\xC3[\x98-\xB6]))|(((\xC3[\xB8-\xBF])|([\xC4-\xCB][\x80-\xBF]))|(((\xCD[\xB0-\xBD]))|(((\xCD\xBF)|([\xCE-\xDF][\x80-\xBF])|(\xE0([\xA0-\xBF][\x80-\xBF]))|(\xE1([\x80-\xBF][\x80-\xBF])))|(((\xE2(\x80[\x8C-\x8D])))|(((\xE2(\x81[\xB0-\xBF])|([\x82-\x85][\x80-\xBF])|(\x86[\x80-\x8F])))|(((\xE2([\xB0-\xBE][\x80-\xBF])|(\xBF[\x80-\xAF])))|(((\xE3(\x80[\x81-\xBF])|([\x81-\xBF][\x80-\xBF]))|([\xE4-\xEC][\x80-\xBF][\x80-\xBF])|([\xE1-\xEC][\x80-\xBF][\x80-\xBF])|(\xED([\x80-\x9F][\x80-\xBF])))|(((\xEF([\xA4-\xB6][\x80-\xBF])|(\xB7[\x80-\x8F])))|(((\xEF(\xB7[\xB0-\xBF])|([\xB8-\xBE][\x80-\xBF])|(\xBF[\x80-\xBD])))|(((\xF0([\x90-\xBF][\x80-\xBF][\x80-\xBF]))|([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]))|(({UCHAR})))))))))))))))
>> NCCHAR1 (({NCCHAR1p}))|("_")
>>
> VARNAME ((({NCCHAR1}))|([0-9]))(((({NCCHAR1}))|(([0-9])|((\xC2\xB7)|(((\xCD[\x80-\xAF]))|((\xE2(\x80\xBF)|(\x81\x80))))))))*
>> VAR2 "$"({VARNAME})
>> VAR1 "?"({VARNAME})
>>
> NCCHAR (({NCCHAR1}))|(("-")|(([0-9])|((\xC2\xB7)|(((\xCD[\x80-\xAF]))|((\xE2(\x80\xBF)|(\x81\x80)))))))
>> NCNAME_PREFIX ({NCCHAR1p})(((((({NCCHAR}))|(".")))*({NCCHAR})))?
>> QNAME_NS (({NCNAME_PREFIX}))?":"
>> NCNAME ({NCCHAR1})(((((({NCCHAR}))|(".")))*({NCCHAR})))?
>> BLANK_NODE_LABEL "_:"({NCNAME})
>> QNAME (({NCNAME_PREFIX}))?":"(({NCNAME}))?
>> PASSED_TOKENS ([\t\n\r ])+
>> %%
>> {PASSED_TOKENS}
>> {IT_BASE} {return sparqlParser::IT_BASE;}
>> {IT_PREFIX} {val->buf = new Buf(yytext); return sparqlParser::IT_PREFIX;}
>> {IT_SELECT} {return sparqlParser::IT_SELECT;}
>> {IT_DISTINCT} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_DISTINCT;}
>> {GT_TIMES} {val->buf = new Buf(yytext); return sparqlParser::GT_TIMES;}
>> {IT_CONSTRUCT} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_CONSTRUCT;}
>> {IT_DESCRIBE} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_DESCRIBE;}
>> {IT_ASK} {val->buf = new Buf(yytext); return sparqlParser::IT_ASK;}
>> {IT_FROM} {val->buf = new Buf(yytext); return sparqlParser::IT_FROM;}
>> {IT_NAMED} {val->buf = new Buf(yytext); return sparqlParser::IT_NAMED;}
>> {IT_WHERE} {val->buf = new Buf(yytext); return sparqlParser::IT_WHERE;}
>> {IT_ORDER} {val->buf = new Buf(yytext); return sparqlParser::IT_ORDER;}
>> {IT_BY} {val->buf = new Buf(yytext); return sparqlParser::IT_BY;}
>> {IT_ASC} {val->buf = new Buf(yytext); return sparqlParser::IT_ASC;}
>> {IT_DESC} {val->buf = new Buf(yytext); return sparqlParser::IT_DESC;}
>> {IT_LIMIT} {val->buf = new Buf(yytext); return sparqlParser::IT_LIMIT;}
>> {IT_OFFSET} {val->buf = new Buf(yytext); return sparqlParser::IT_OFFSET;}
>> {GT_LCURLEY} {val->buf = new Buf(yytext); return
>> sparqlParser::GT_LCURLEY;}
>> {GT_RCURLEY} {val->buf = new Buf(yytext); return
>> sparqlParser::GT_RCURLEY;}
>> {GT_DOT} {val->buf = new Buf(yytext); return sparqlParser::GT_DOT;}
>> {IT_OPTIONAL} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_OPTIONAL;}
>> {IT_GRAPH} {val->buf = new Buf(yytext); return sparqlParser::IT_GRAPH;}
>> {IT_UNION} {val->buf = new Buf(yytext); return sparqlParser::IT_UNION;}
>> {IT_FILTER} {val->buf = new Buf(yytext); return sparqlParser::IT_FILTER;}
>> {GT_COMMA} {val->buf = new Buf(yytext); return sparqlParser::GT_COMMA;}
>> {GT_LPAREN} {val->buf = new Buf(yytext); return sparqlParser::GT_LPAREN;}
>> {GT_RPAREN} {val->buf = new Buf(yytext); return sparqlParser::GT_RPAREN;}
>> {GT_SEMI} {val->buf = new Buf(yytext); return sparqlParser::GT_SEMI;}
>> {IT_a} {val->buf = new Buf(yytext); return sparqlParser::IT_a;}
>> {GT_LBRACKET} {val->buf = new Buf(yytext); return
>> sparqlParser::GT_LBRACKET;}
>> {GT_RBRACKET} {val->buf = new Buf(yytext); return
>> sparqlParser::GT_RBRACKET;}
>> {GT_MINUS} {val->buf = new Buf(yytext); return sparqlParser::GT_MINUS;}
>> {GT_PLUS} {val->buf = new Buf(yytext); return sparqlParser::GT_PLUS;}
>> {GT_OR} {val->buf = new Buf(yytext); return sparqlParser::GT_OR;}
>> {GT_AND} {val->buf = new Buf(yytext); return sparqlParser::GT_AND;}
>> {GT_EQUAL} {val->buf = new Buf(yytext); return sparqlParser::GT_EQUAL;}
>> {GT_NEQUAL} {val->buf = new Buf(yytext); return sparqlParser::GT_NEQUAL;}
>> {GT_LT} {val->buf = new Buf(yytext); return sparqlParser::GT_LT;}
>> {GT_GT} {val->buf = new Buf(yytext); return sparqlParser::GT_GT;}
>> {GT_LE} {val->buf = new Buf(yytext); return sparqlParser::GT_LE;}
>> {GT_GE} {val->buf = new Buf(yytext); return sparqlParser::GT_GE;}
>> {GT_DIVIDE} {val->buf = new Buf(yytext); return sparqlParser::GT_DIVIDE;}
>> {GT_NOT} {val->buf = new Buf(yytext); return sparqlParser::GT_NOT;}
>> {IT_STR} {val->buf = new Buf(yytext); return sparqlParser::IT_STR;}
>> {IT_LANG} {val->buf = new Buf(yytext); return sparqlParser::IT_LANG;}
>> {IT_LANGMATCHES} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_LANGMATCHES;}
>> {IT_DATATYPE} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_DATATYPE;}
>> {IT_BOUND} {val->buf = new Buf(yytext); return sparqlParser::IT_BOUND;}
>> {IT_isIRI} {val->buf = new Buf(yytext); return sparqlParser::IT_isIRI;}
>> {IT_isURI} {val->buf = new Buf(yytext); return sparqlParser::IT_isURI;}
>> {IT_isBLANK} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_isBLANK;}
>> {IT_isLITERAL} {val->buf = new Buf(yytext); return
>> sparqlParser::IT_isLITERAL;}
>> {IT_REGEX} {val->buf = new Buf(yytext); return sparqlParser::IT_REGEX;}
>> {GT_DTYPE} {val->buf = new Buf(yytext); return sparqlParser::GT_DTYPE;}
>> {IT_true} {val->buf = new Buf(yytext); return sparqlParser::IT_true;}
>> {IT_false} {val->buf = new Buf(yytext); return sparqlParser::IT_false;}
>> {Q_IRI_REF} {val->lex_str = get_token(1, 1); return
>> sparqlParser::Q_IRI_REF;}
>> {QNAME_NS} {val->lex_str = get_token(1, 0); return
>> sparqlParser::QNAME_NS;}
>> {QNAME} {val->lex_str = get_token(0, 0); return sparqlParser::QNAME;}
>> {BLANK_NODE_LABEL} {val->lex_str = get_token(2, 0); return
>> sparqlParser::BLANK_NODE_LABEL;}
>> {VAR1} {val->lex_str = get_token(1, 0); return sparqlParser::VAR1;}
>> {VAR2} {val->lex_str = get_token(1, 0); return sparqlParser::VAR2;}
>> {LANGTAG} {val->lex_str = get_token(0, 0); return sparqlParser::LANGTAG;}
>> {INTEGER} {val->lex_str = get_token(0, 0); return sparqlParser::INTEGER;}
>> {DECIMAL} {val->lex_str = get_token(0, 0); return sparqlParser::DECIMAL;}
>> {DOUBLE} {val->lex_str = get_token(0, 0); return sparqlParser::DOUBLE;}
>> {STRING_LITERAL1} {val->lex_str = get_token(1, 1); return
>> sparqlParser::STRING_LITERAL1;}
>> {STRING_LITERAL2} {val->lex_str = get_token(1, 1); return
>> sparqlParser::STRING_LITERAL2;}
>> {STRING_LITERAL_LONG1} {val->lex_str = get_token(1, 1); return
>> sparqlParser::STRING_LITERAL_LONG1;}
>> {STRING_LITERAL_LONG2} {val->lex_str = get_token(1, 1); return
>> sparqlParser::STRING_LITERAL_LONG2;}
>> {NIL} {val->buf = new Buf(yytext); return sparqlParser::NIL;}
>> {ANON} {val->buf = new Buf(yytext); return sparqlParser::ANON;}
>> <<EOF>> { yyterminate();}
>> %%
>> int yywrap()
>> {
>> return(1);
>> }
>>
>> int sparqlFlexLexer::LexerReadStatic( char* buf, int max_size )
>> {
>> char** cur = yyptr;
>> char* start = *cur;
>> #if 0
>> for (; **cur && max_size > 0; (*cur)++, buf++) {
>> *buf = **cur;
>> max_size--;
>> }
>> #else
>> if (**cur && max_size > 0) {
>> *buf = **cur;
>> (*cur)++, buf++;
>> }
>> #endif
>> return *cur - start;
>> }
>>
>> sparqlFlexLexer::sparqlFlexLexer( THD *thd, char** ptr)
>> {
>> this->thd = thd;
>> yyptr = ptr;
>>
>> yyin = NULL;
>> yyout = NULL;
>> yy_c_buf_p = 0;
>> yy_init = 1;
>> yy_start = 0;
>> yy_flex_debug = 0;
>> yylineno = 1; // this will only get updated if %option yylineno
>>
>> yy_did_buffer_switch_on_eof = 0;
>>
>> yy_looking_for_trail_begin = 0;
>> yy_more_flag = 0;
>> yy_more_len = 0;
>> yy_more_offset = yy_prev_more_offset = 0;
>>
>> yy_start_stack_ptr = yy_start_stack_depth = 0;
>> yy_start_stack = 0;
>>
>> yy_current_buffer = 0;
>>
>> #ifdef YY_USES_REJECT
>> yy_state_buf = new yy_state_type[YY_BUF_SIZE + 2];
>> #else
>> yy_state_buf = 0;
>> #endif
>> }
>>
>> LEX_STRING sparqlFlexLexer::get_token(size_t skip, size_t trail)
>> {
>> LEX_STRING tmp;
>> tmp.length = yyleng - skip - trail;
>> tmp.str = (char*) thd->strmake((char*) yytext + skip, tmp.length);
>> return tmp;
>> }
>>
>> ------------------------------------------------------------------------
>>
>> #include "dyn_parser.h"
>> #include <dlfcn.h>
>>
>> class Item_POS;
>> class Item_URI;
>> class Item_variable;
>> class Item_blank_node;
>> class Item_literal_string;
>> class Item_literal_int;
>> class Item_literal_decimal;
>> class Item_literal_float;
>> class Alias_info;
>> class GraphContext;
>> class BindingGraphContext;
>> class RootGraphContext;
>>
>> class sparqlFrob : public Dynamic_parser {
>> private:
>> void* parser;
>> List<Item_URI> uris;
>> List<Item_variable> variables;
>> List<Item_blank_node> blank_nodes;
>> List<Item_literal_string> strings;
>> List<Item_literal_int> ints;
>> List<Item_literal_decimal> decimals;
>> List<Item_literal_float> floats;
>> List<Item_POS> subjects;
>> List<Item_POS> predicates;
>> List<GraphContext> contexts;
>> List<Item> root_constraints;
>> List<List<BindingGraphContext> > need_selects;
>> bool distinct;
>> GraphContext *last_graph_context;
>> GraphContext *next_graph_context;
>> uchar next_union_alias_index;
>>
>> public:
>> sparqlFrob(THD *thd, char** ptr);
>> ~sparqlFrob();
>> int parse();
>>
>> Item_variable* ensure_variable (const char *var);
>> Item_URI* ensure_URI (LEX_STRING uristr);
>> Item_blank_node* make_blank_node ();
>> Item_blank_node* ensure_blank_node (const char *label);
>> Item_literal_string* ensure_string (LEX_STRING str, Item_POS
>> *lang_or_datatype);
>> Item_literal_int* ensure_int (LEX_STRING str, Item_POS
>> *lang_or_datatype);
>> Item_literal_decimal* ensure_decimal (LEX_STRING str, Item_POS
>> *lang_or_datatype);
>> Item_literal_float* ensure_float (LEX_STRING str, Item_POS
>> *lang_or_datatype);
>> void push_subject (Item_POS *subject);
>> Item_POS* pop_subject ();
>> void push_predicate (Item_POS *predicate);
>> void pop_predicate ();
>> bool object (Item_POS *object);
>> bool type_list ();
>> bool add_listElement (Item_POS *item);
>> const char* get_primary_key(const char *table_name);
>> void push_context(GraphContext *gc) {contexts.push_front(gc);}
>> GraphContext* head_context() {return contexts.head();}
>> GraphContext* pop_context() {return last_graph_context =
>> contexts.pop();}
>> void add_root_constraints (Item *constraint) {
>> if (constraint)
>> root_constraints.push_front(constraint);
>> }
>> Item* get_root_constraints () {
>> return root_constraints.elements == 0 ? NULL :
>> root_constraints.elements == 1 ? root_constraints.pop() : new
>> Item_cond_and(root_constraints);
>> }
>> void needs_select (List<BindingGraphContext> *contexts) {
>> need_selects.push_back(contexts); // Must iterate backwards through
>> list.
>> }
>> void select_variables();
>> void set_distinct (bool distinct_parm) {distinct= distinct_parm;}
>> bool get_distinct () {return distinct;}
>> GraphContext *last_context () {return last_graph_context;}
>> void set_next_GC (GraphContext *gc) {next_graph_context= gc;}
>> GraphContext *was_next_GC () {GraphContext *ret= next_graph_context;
>> next_graph_context= NULL; return ret;}
>> LEX_STRING* next_union_alias ();
>> void print(String *str);
>>
>> LEX *lex;
>> };
>>
>> t_initialize initialize;
>>
--
-eric
office: +1.617.258.5741 NE43-344, MIT, Cambridge, MA 02144 USA
mobile: +1.617.599.3509
(eric@stripped)
Feel free to forward this message to any list for any purpose other than
email address distribution.
Attachment: [application/pgp-signature] Digital signature signature.asc