List:Internals« Previous MessageNext Message »
From:Eric Prud'hommeaux Date:September 5 2007 11:03pm
Subject:Re: [PATCH] (super)user-loadable mysqld parsers
View as plain text  
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.
-- 
-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: [text/x-diff] dynParser-5.2-1.patch dynParser-5.2-1.patch
%{ #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; } Attachment: [text/x-chdr] sparqlFrob.h sparqlFrob.h
Attachment: [text/x-chdr]
Attachment: [application/pgp-signature] Digital signature signature.asc
Thread
Re: [PATCH] (super)user-loadable mysqld parsersEric Prud'hommeaux5 Sep
  • Re: [PATCH] (super)user-loadable mysqld parsersKonstantin Osipov10 Sep