629 lines
17 KiB
Plaintext
629 lines
17 KiB
Plaintext
%include
|
|
{
|
|
/*
|
|
* Copyright (C) 2012 - Juan Ferrer Toribio
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <sql/sql.h>
|
|
#include "gram.h"
|
|
|
|
typedef struct
|
|
{
|
|
SqlObject * object;
|
|
gchar * string;
|
|
gchar * current;
|
|
gboolean failed;
|
|
GError ** error;
|
|
}
|
|
ParseState;
|
|
|
|
typedef enum
|
|
{
|
|
SQL_PARSER_ERROR_EMPTY_QUERY = 1 << 0,
|
|
SQL_PARSER_ERROR_PARSING = 1 << 1,
|
|
SQL_PARSER_ERROR_STACK_OVERFLOW = 1 << 2,
|
|
}
|
|
SqlParserError;
|
|
|
|
static inline SqlList * list_add (gpointer item, SqlList * list)
|
|
{
|
|
sql_list_add (list, item);
|
|
return list;
|
|
}
|
|
|
|
static inline SqlList * list_new (gpointer item, GType gtype)
|
|
{
|
|
SqlList * list = sql_list_new (gtype);
|
|
return list_add (item, list);
|
|
}
|
|
}
|
|
|
|
%default_type {SqlObject *}
|
|
%token_type {gchar *}
|
|
%token_destructor {g_free ($$);}
|
|
%token_prefix SQL_PARSER_
|
|
|
|
// Return pointer
|
|
%extra_argument { ParseState * state }
|
|
|
|
// Error treatment
|
|
%syntax_error
|
|
{
|
|
gchar * pref = ".", * err_str = NULL;
|
|
|
|
if (state->current)
|
|
{
|
|
err_str = state->current - 15 >= state->string ?
|
|
state->current - 10 : state->string;
|
|
pref = err_str == state->string ? " near: " : " near: [...]";
|
|
}
|
|
|
|
g_set_error (state->error, SQL_PARSER_LOG_DOMAIN, SQL_PARSER_ERROR_PARSING,
|
|
"Parsing error%s%s", pref, err_str);
|
|
state->failed = TRUE;
|
|
}
|
|
|
|
%stack_overflow
|
|
{
|
|
g_set_error (state->error, SQL_PARSER_LOG_DOMAIN, SQL_PARSER_ERROR_STACK_OVERFLOW,
|
|
"Parser stack overflow. Parsing terminated.\n");
|
|
state->failed = TRUE;
|
|
}
|
|
|
|
// Operator precedence
|
|
%left UNION EXCEPT.
|
|
%left INSERSECT.
|
|
%left OR.
|
|
%left XOR.
|
|
%left AND.
|
|
%right NOT.
|
|
%right EQ NE.
|
|
%left GT GE LT LE.
|
|
%left LIKE.
|
|
%left IS.
|
|
%left PLUS MINUS.
|
|
%left STAR DIV MOD.
|
|
%right SIGN.
|
|
|
|
// Start symbol:
|
|
%start_symbol start
|
|
|
|
start ::= multi_stmt (A).
|
|
{
|
|
state->object = SQL_OBJECT (A);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Multi statement
|
|
|
|
multi_stmt(A) ::= stmt_list(stmt_list).
|
|
{
|
|
guint len = sql_list_length (stmt_list);
|
|
|
|
if (len == 1)
|
|
{
|
|
A = sql_list_get (stmt_list, 0);
|
|
g_object_ref_sink (G_OBJECT (A));
|
|
g_object_unref (g_object_ref_sink (stmt_list));
|
|
}
|
|
else
|
|
// FIXME Reverse list!
|
|
A = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmt_list, NULL);
|
|
}
|
|
|
|
%type stmt_list {SqlList *}
|
|
stmt_list(A) ::= stmt(X). { A = list_new (X, SQL_TYPE_STMT); }
|
|
stmt_list(A) ::= stmt(X) SC. { A = list_new (X, SQL_TYPE_STMT); }
|
|
stmt_list(A) ::= stmt(X) SC stmt_list(B). { A = list_add (X, B); }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Statemet
|
|
|
|
stmt(A) ::= select_stmt(X). { A = X; }
|
|
stmt(A) ::= delete_stmt(X). { A = X; }
|
|
stmt(A) ::= update_stmt(X). { A = X; }
|
|
stmt(A) ::= insert_stmt(X). { A = X; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Select
|
|
|
|
select_stmt(A) ::= select_stmt(B) set_op(type) simple_select(X).
|
|
{
|
|
g_object_set (B, "exprs", type, "next", X, NULL);
|
|
A = B;
|
|
}
|
|
select_stmt(A) ::= simple_select(X). { A = X; }
|
|
|
|
%type set_op {SqlSelectType}
|
|
set_op(A) ::= UNION ANY. { A = SQL_SELECT_UNION_ANY; }
|
|
set_op(A) ::= UNION ALL. { A = SQL_SELECT_UNION_ALL; }
|
|
set_op(A) ::= UNION. { A = SQL_SELECT_UNION_ALL; }
|
|
set_op(A) ::= INTERSECT. { A = SQL_SELECT_INTERSECT; }
|
|
set_op(A) ::= EXCEPT. { A = SQL_SELECT_EXCEPT; }
|
|
|
|
simple_select(A) ::= LP simple_select(X) RP. { A = X; }
|
|
simple_select(A) ::= SELECT
|
|
distinct(distinct_c)
|
|
select_field_list(field_list)
|
|
from(target)
|
|
where(where_c)
|
|
group(group_c) having(having_c)
|
|
order(order_c)
|
|
limit(limit_c).
|
|
{
|
|
A = g_object_new (SQL_TYPE_SELECT
|
|
,"distinct" ,distinct_c
|
|
,"fields" ,field_list
|
|
,"targets" ,target
|
|
,"where" ,where_c
|
|
,"group" ,group_c
|
|
,"order" ,order_c
|
|
,NULL
|
|
);
|
|
|
|
if (having_c)
|
|
g_object_set (A, "having", having_c, NULL);
|
|
|
|
if (limit_c)
|
|
g_object_set (A
|
|
,"limit-offset" ,limit_c->offset
|
|
,"limit-count" ,limit_c->count
|
|
,NULL
|
|
);
|
|
}
|
|
|
|
%type distinct {gboolean}
|
|
distinct(A) ::= DISTINCT. { A = TRUE; }
|
|
distinct(A) ::= ALL. { A = FALSE; }
|
|
distinct(A) ::= . { A = FALSE; }
|
|
|
|
select_field(A) ::= expr(X).
|
|
{ A = g_object_new (SQL_TYPE_SELECT_FIELD, "expr", X, NULL); }
|
|
select_field(A) ::= expr(X) alias(Y).
|
|
{ A = g_object_new (SQL_TYPE_SELECT_FIELD, "expr", X, "alias", Y, NULL); }
|
|
|
|
%type select_field_list {SqlList *}
|
|
select_field_list(A) ::= select_field(X). { A = list_new (X, SQL_TYPE_SELECT_FIELD); }
|
|
select_field_list(A) ::= select_field_list(B) CM select_field(X). { A = list_add (X, B); }
|
|
|
|
%type from {SqlList *}
|
|
from(A) ::= FROM target_list(X). { A = X; }
|
|
from(A) ::= . { A = NULL; }
|
|
|
|
%type group {SqlList *}
|
|
group(A) ::= GROUP expr_list(X). { A = X; }
|
|
group(A) ::= . { A = NULL; }
|
|
|
|
having(A) ::= HAVING expr(X). { A = X; }
|
|
having(A) ::= . { A = NULL; }
|
|
|
|
%type order {SqlList *}
|
|
order(A) ::= ORDER order_list (X). { A = X; }
|
|
order(A) ::= . { A = NULL; }
|
|
|
|
%type order_list {SqlList *}
|
|
order_list(A) ::= order_expr(X). { A = list_new (X, SQL_TYPE_SELECT_ORDER); }
|
|
order_list(A) ::= order_list(B) CM order_expr(X). { A = list_add (X, B); }
|
|
|
|
order_expr(A) ::= expr(X) order_way(Y). { A = g_object_new (SQL_TYPE_SELECT_ORDER, "expr", X, "way", Y, NULL); }
|
|
|
|
%type order_way {SqlSelectOrderWay}
|
|
order_way(A) ::= ASC. { A = SQL_SELECT_ORDER_ASC; }
|
|
order_way(A) ::= DESC. { A = SQL_SELECT_ORDER_DESC; }
|
|
order_way(A) ::= . { A = SQL_SELECT_ORDER_ASC; }
|
|
|
|
%type limit {SelectLimit *}
|
|
%destructor limit {g_free ($$);}
|
|
%include
|
|
{
|
|
typedef struct
|
|
{
|
|
guint offset;
|
|
guint count;
|
|
}
|
|
SelectLimit;
|
|
|
|
static inline SelectLimit * create_limit (gchar * offset, gchar * count)
|
|
{
|
|
SelectLimit * limit = g_new (SelectLimit, 1);
|
|
limit->offset = offset ? atoi (offset) : 0;
|
|
limit->count = count ? atoi (count) : 0;
|
|
return limit;
|
|
}
|
|
}
|
|
limit(A) ::= LIMIT INTEGER(X). { A = create_limit (NULL, X); }
|
|
limit(A) ::= OFFSET INTEGER(Y). { A = create_limit (Y, NULL); }
|
|
limit(A) ::= LIMIT INTEGER(X) OFFSET INTEGER(Y). { A = create_limit (Y, X); }
|
|
limit(A) ::= LIMIT INTEGER(X) CM INTEGER(Y). { A = create_limit (Y, X); }
|
|
limit(A) ::= . { A = NULL; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Delete
|
|
|
|
delete_stmt(A) ::= DELETE table_list(table_list) del_using(del_using) where(where_c).
|
|
{
|
|
A = g_object_new (SQL_TYPE_DELETE
|
|
,"targets" ,table_list
|
|
,"tables" ,del_using
|
|
,"where" ,where_c
|
|
,NULL
|
|
);
|
|
}
|
|
|
|
%type table_list {SqlList *}
|
|
table_list(A) ::= table(X). { A = list_new (X, SQL_TYPE_TABLE); }
|
|
table_list(A) ::= table_list(B) CM table(X). { A = list_add (X, B); }
|
|
|
|
%type del_using {SqlList *}
|
|
del_using(A) ::= USING target_list(X). { A = X; }
|
|
del_using(A) ::= . { A = NULL; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Update
|
|
|
|
update_stmt(A) ::= UPDATE table_list(table) SET update_list(update_list) where(where_c).
|
|
{
|
|
A = g_object_new (SQL_TYPE_UPDATE
|
|
,"targets" ,table
|
|
,"sets" ,update_list
|
|
,"where" ,where_c
|
|
,NULL
|
|
);
|
|
}
|
|
|
|
%type update_list {SqlList *}
|
|
update_list(A) ::= update_set(X). { A = list_new (X, SQL_TYPE_UPDATE_SET); }
|
|
update_list(A) ::= update_list(B) CM update_set(X). { A = list_add (X, B); }
|
|
|
|
update_set(A) ::= field(X) EQ def_expr(Y).
|
|
{
|
|
A = g_object_new (SQL_TYPE_UPDATE_SET
|
|
,"field" ,X
|
|
,"expr" ,Y
|
|
,NULL
|
|
);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Insert
|
|
|
|
insert_stmt(A) ::= INSERT table(tab) insert_fields(insert_fields) insert_values(insert_values).
|
|
{
|
|
A = g_object_new (SQL_TYPE_INSERT
|
|
,"table" ,tab
|
|
,"fields" ,insert_fields
|
|
,NULL
|
|
);
|
|
|
|
if (SQL_IS_SELECT (insert_values))
|
|
g_object_set (A, "select", insert_values, NULL);
|
|
else
|
|
g_object_set (A, "values", insert_values, NULL);
|
|
}
|
|
|
|
%type insert_fields {SqlList *}
|
|
insert_fields(A) ::= LP field_list(X) RP. { A = X; }
|
|
insert_fields(A) ::= . { A = NULL; }
|
|
|
|
%type insert_values {gpointer}
|
|
insert_values(A) ::= DEFAULT VALUES. { A = NULL; }
|
|
insert_values(A) ::= VALUES set_list(X). { A = X; }
|
|
//insert_values(A) ::= select_stmt(X). { A = X; }
|
|
|
|
%type set_list {SqlList *}
|
|
set_list(A) ::= set(X). { A = list_new (X, SQL_TYPE_SET); }
|
|
set_list(A) ::= set_list(B) CM set(X). { A = list_add (X, B); }
|
|
|
|
set(A) ::= LP def_expr_list(X) RP. { A = g_object_new (SQL_TYPE_SET, "exprs", X, NULL); }
|
|
|
|
%type def_expr_list {SqlList *}
|
|
def_expr_list(A) ::= def_expr(X). { A = list_new (X, SQL_TYPE_EXPR); }
|
|
def_expr_list(A) ::= def_expr_list(B) CM def_expr(X). { A = list_add (X, B); }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Common to statements
|
|
|
|
where(A) ::= WHERE expr(X). { A = X; }
|
|
where(A) ::= . { A = NULL; }
|
|
|
|
def_expr(A) ::= expr(X). { A = X; }
|
|
def_expr(A) ::= DEFAULT. { A = NULL; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Target
|
|
|
|
target(A) ::= unaliased_target(X). { A = X; }
|
|
target(A) ::= unaliased_target(X) alias(Y).
|
|
{
|
|
g_object_set (X, "alias", Y, NULL);
|
|
A = X;
|
|
}
|
|
//target(A) ::= LP target(X) RP. { A = X; }
|
|
|
|
%type target_list {SqlList *}
|
|
target_list(A) ::= target(X). { A = list_new (X, SQL_TYPE_TARGET); }
|
|
target_list(A) ::= target_list(B) CM target(X). { A = list_add (X, B); }
|
|
|
|
unaliased_target(A) ::= join(X). { A = X; }
|
|
unaliased_target(A) ::= subquery(X). { A = X; }
|
|
unaliased_target(A) ::= table(X). { A = X; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Join
|
|
|
|
join(A) ::= target(target_left) join_type(join_type) target(target_right) join_cond(join_cond).
|
|
{
|
|
A = g_object_new (SQL_TYPE_JOIN
|
|
,"target-left" ,target_left
|
|
,"target-right" ,target_right
|
|
,"join-type" ,join_type
|
|
,NULL
|
|
);
|
|
|
|
if (SQL_IS_LIST (join_cond)) // USING
|
|
{
|
|
GList * n;
|
|
SqlList * exprs = sql_list_new (SQL_TYPE_EXPR);
|
|
SqlOperation * op_and = g_object_new (SQL_TYPE_OPERATION
|
|
,"operator" ,SQL_OPERATION_TYPE_AND
|
|
,"operands" ,exprs
|
|
,NULL
|
|
);
|
|
|
|
for (n = sql_list_get_items (join_cond); n; n = n->next)
|
|
{
|
|
SqlList * equal = sql_list_new (SQL_TYPE_EXPR);
|
|
SqlOperation * op = g_object_new (SQL_TYPE_OPERATION
|
|
,"operator" ,SQL_OPERATION_TYPE_EQUAL
|
|
,"operands" ,equal
|
|
,NULL
|
|
);
|
|
|
|
gchar * target = SQL_TARGET (target_left)->alias ? SQL_TARGET (target_left)->alias : SQL_TABLE (target_left)->name;
|
|
gchar * schema = SQL_IS_TABLE(target_left) && SQL_TABLE (target_left)->schema ?
|
|
SQL_TABLE (target_left)->schema : NULL;
|
|
|
|
g_object_set (n->data, "target", target, "schema", schema, NULL);
|
|
sql_list_add (equal, n->data);
|
|
|
|
target = SQL_TARGET (target_right)->alias ? SQL_TARGET (target_right)->alias : SQL_TABLE (target_right)->name;
|
|
schema = SQL_IS_TABLE (target_right) && SQL_TABLE (target_right)->schema ?
|
|
SQL_TABLE (target_right)->schema : NULL;
|
|
|
|
sql_list_add (equal,
|
|
sql_field_new_with_target (SQL_FIELD (n->data)->name, target, schema));
|
|
|
|
sql_list_add (exprs, op);
|
|
}
|
|
|
|
g_object_set (A, "condition", op_and, NULL);
|
|
g_object_unref (g_object_ref_sink (join_cond));
|
|
}
|
|
else
|
|
g_object_set (A, "condition", join_cond, NULL);
|
|
}
|
|
|
|
%type join_type {SqlJoinType}
|
|
join_type(A) ::= INNER JOIN. { A = SQL_JOIN_TYPE_INNER; }
|
|
join_type(A) ::= JOIN. { A = SQL_JOIN_TYPE_INNER; }
|
|
join_type(A) ::= LEFT JOIN. { A = SQL_JOIN_TYPE_LEFT; }
|
|
join_type(A) ::= RIGHT JOIN. { A = SQL_JOIN_TYPE_RIGHT; }
|
|
|
|
%type join_cond {gpointer}
|
|
join_cond(A) ::= ON expr(X). { A = X; }
|
|
join_cond(A) ::= USING LP field_list(X) RP. { A = X; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Subquery
|
|
|
|
subquery(A) ::= LP select_stmt(stmts) RP.
|
|
{
|
|
A = g_object_new (SQL_TYPE_SUBQUERY, "stms", stmts, NULL);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Table
|
|
|
|
table(A) ::= identifier(X).
|
|
{
|
|
A = g_object_new (SQL_TYPE_TABLE, "name", X, NULL);
|
|
}
|
|
table(A) ::= identifier(Y) DOT identifier(X).
|
|
{
|
|
A = g_object_new (SQL_TYPE_TABLE, "name", X, "schema", Y, NULL);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Expr
|
|
|
|
expr(A) ::= LP expr(X) RP. { A = X; }
|
|
|
|
%type expr_list {SqlList *}
|
|
expr_list(A) ::= expr(X). { A = list_new (X, SQL_TYPE_EXPR); }
|
|
expr_list(A) ::= expr_list(B) CM expr(X). { A = list_add (X, B); }
|
|
|
|
expr(A) ::= field(X). { A = X; }
|
|
expr(A) ::= function(X). { A = X; }
|
|
expr(A) ::= operation(X). { A = X; }
|
|
expr(A) ::= value(X). { A = X; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Field
|
|
|
|
field(A) ::= unqualified_field(X). { A = X; }
|
|
field(A) ::= identifier(Y) DOT unqualified_field(X).
|
|
{
|
|
g_object_set (X, "target", Y, NULL);
|
|
A = X;
|
|
}
|
|
field(A) ::= identifier(Z) DOT identifier(Y) DOT unqualified_field(X).
|
|
{
|
|
g_object_set (X, "target", Y, "schema", Z, NULL);
|
|
A = X;
|
|
}
|
|
|
|
unqualified_field(A) ::= identifier(X).
|
|
{
|
|
A = g_object_new (SQL_TYPE_FIELD, "name", X, NULL);
|
|
}
|
|
unqualified_field(A) ::= STAR.
|
|
{
|
|
A = g_object_new (SQL_TYPE_FIELD, "name", "*", NULL);
|
|
}
|
|
|
|
%type field_list {SqlList *}
|
|
field_list(A) ::= field(X). { A = list_new (X, SQL_TYPE_FIELD); }
|
|
field_list(A) ::= field_list(B) CM field(X). { A = list_add (X, B); }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Function
|
|
|
|
function(A) ::= unqualified_function(X). { A = X; }
|
|
function(A) ::= identifier(Z) DOT unqualified_function(X).
|
|
{
|
|
g_object_set (X, "schema", Z, NULL);
|
|
A = X;
|
|
}
|
|
|
|
unqualified_function(A) ::= identifier(X) LP function_expr_list(Y) RP.
|
|
{
|
|
A = g_object_new (SQL_TYPE_FUNCTION, "name", X, "params", Y, NULL);
|
|
}
|
|
|
|
%type function_expr_list {SqlList *}
|
|
function_expr_list(A) ::= . { A = NULL; }
|
|
function_expr_list(A) ::= expr_list(X). { A = X; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Operation
|
|
|
|
%include
|
|
{
|
|
static inline SqlObject * create_operation
|
|
(const gpointer X, const gpointer Y, const SqlOperationType type)
|
|
{
|
|
SqlList * exprs = sql_list_new (SQL_TYPE_EXPR);
|
|
sql_list_add (exprs, X);
|
|
|
|
if (Y) // Binary operation
|
|
sql_list_add (exprs, Y);
|
|
|
|
return g_object_new (SQL_TYPE_OPERATION, "operator", type, "operands", exprs, NULL);
|
|
}
|
|
}
|
|
operation(A) ::= MINUS expr(X). [SIGN]
|
|
{
|
|
GValue value = {0};
|
|
SqlObject * minus = sql_value_new ();
|
|
g_value_init (&value, G_TYPE_INT);
|
|
g_value_set_int (&value, -1);
|
|
sql_value_set_value (SQL_VALUE (minus), &value);
|
|
A = create_operation (X, minus, SQL_OPERATION_TYPE_MULTIPLICATION);
|
|
}
|
|
|
|
operation(A) ::= NOT expr(X).
|
|
{ A = create_operation (X, NULL, SQL_OPERATION_TYPE_NOT); }
|
|
|
|
operation(A) ::= PLUS expr(X). [SIGN]
|
|
{ A = create_operation (X, NULL, SQL_OPERATION_TYPE_SUM); }
|
|
|
|
operation(A) ::= expr(X) PLUS expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_SUM); }
|
|
|
|
operation(A) ::= expr(X) MINUS expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_SUBTRACTION); }
|
|
|
|
operation(A) ::= expr(X) STAR expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_MULTIPLICATION); }
|
|
|
|
operation(A) ::= expr(X) DIV expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_DIVISION); }
|
|
|
|
operation(A) ::= expr(X) OR expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_OR); }
|
|
|
|
operation(A) ::= expr(X) XOR expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_XOR); }
|
|
|
|
operation(A) ::= expr(X) AND expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_AND); }
|
|
|
|
operation(A) ::= expr(X) EQ expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_EQUAL); }
|
|
|
|
operation(A) ::= expr(X) NE expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_NOT_EQUAL); }
|
|
|
|
//XXX the following should be %nonassoc operators but are %left to avoid
|
|
// conflicts. The DB will warn about a bad use if used as %left.
|
|
operation(A) ::= expr(X) GT expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_GREATER); }
|
|
|
|
operation(A) ::= expr(X) GE expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_GREATER_EQUAL); }
|
|
|
|
operation(A) ::= expr(X) LT expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_LOWER); }
|
|
|
|
operation(A) ::= expr(X) LE expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_LOWER_EQUAL); }
|
|
|
|
operation(A) ::= expr(X) LIKE expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_LIKE); }
|
|
|
|
operation(A) ::= expr(X) IS expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_IS); }
|
|
|
|
operation(A) ::= expr(X) MOD expr(Y).
|
|
{ A = create_operation (X, Y, SQL_OPERATION_TYPE_MOD); }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Value
|
|
|
|
value(A) ::= INTEGER(X).
|
|
{
|
|
GValue value = {0};
|
|
g_value_set_int (g_value_init (&value, G_TYPE_INT), atoi (X));
|
|
A = g_object_new (SQL_TYPE_VALUE, "value", &value, NULL);
|
|
g_value_unset (&value);
|
|
}
|
|
value(A) ::= FLOAT(X).
|
|
{
|
|
GValue value = {0};
|
|
g_value_set_double
|
|
(g_value_init (&value, G_TYPE_DOUBLE), g_ascii_strtod (X, NULL));
|
|
A = g_object_new (SQL_TYPE_VALUE, "value", &value, NULL);
|
|
g_value_unset (&value);
|
|
}
|
|
value(A) ::= STRING(X).
|
|
{
|
|
GValue value = {0};
|
|
g_value_set_string (g_value_init (&value, G_TYPE_STRING), X);
|
|
A = g_object_new (SQL_TYPE_VALUE, "value", &value, NULL);
|
|
g_value_unset (&value);
|
|
}
|
|
value(A) ::= BOOLEAN(X).
|
|
{
|
|
GValue value = {0};
|
|
g_value_set_boolean (g_value_init (&value, G_TYPE_BOOLEAN)
|
|
,(!g_strcmp0 (X, "TRUE") || !g_strcmp0 (X, "true")) ? TRUE : FALSE);
|
|
A = g_object_new (SQL_TYPE_VALUE, "value", &value, NULL);
|
|
g_value_unset (&value);
|
|
}
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Alias
|
|
|
|
%type alias {gchar *}
|
|
alias(A) ::= AS identifier(X). { A = X; }
|
|
alias(A) ::= identifier(X). { A = X; }
|
|
|
|
%type identifier {gchar *}
|
|
identifier(A) ::= IDENTIFIER(X). { A = X; }
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Placeholder
|
|
|
|
placeholder(A) ::= PLACEHOLDER(X). { A = g_object_new (SQL_TYPE_HOLDER, "id", X, NULL); }
|
|
|
|
stmt ::= placeholder.
|
|
target ::= placeholder.
|
|
expr ::= placeholder.
|