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