summaryrefslogtreecommitdiffstats
path: root/kexi/kexidb/parser/sqlparser.y
diff options
context:
space:
mode:
Diffstat (limited to 'kexi/kexidb/parser/sqlparser.y')
-rw-r--r--kexi/kexidb/parser/sqlparser.y1368
1 files changed, 1368 insertions, 0 deletions
diff --git a/kexi/kexidb/parser/sqlparser.y b/kexi/kexidb/parser/sqlparser.y
new file mode 100644
index 00000000..5a8357f2
--- /dev/null
+++ b/kexi/kexidb/parser/sqlparser.y
@@ -0,0 +1,1368 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Lucijan Busch <[email protected]>
+ Copyright (C) 2004, 2006 Jaroslaw Staniek <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+%token UMINUS
+
+%token SQL_TYPE
+%token SQL_ABS
+%token ACOS
+%token AMPERSAND
+%token SQL_ABSOLUTE
+%token ADA
+%token ADD
+%token ADD_DAYS
+%token ADD_HOURS
+%token ADD_MINUTES
+%token ADD_MONTHS
+%token ADD_SECONDS
+%token ADD_YEARS
+%token ALL
+%token ALLOCATE
+%token ALTER
+%token AND
+%token ANY
+%token ARE
+%token AS
+%token ASIN
+%token ASC
+%token ASCII
+%token ASSERTION
+%token ATAN
+%token ATAN2
+%token AUTHORIZATION
+%token AUTO_INCREMENT
+%token AVG
+%token BEFORE
+%token SQL_BEGIN
+%token BETWEEN
+%token BIGINT
+%token BINARY
+%token BIT
+%token BIT_LENGTH
+%token BITWISE_SHIFT_LEFT
+%token BITWISE_SHIFT_RIGHT
+%token BREAK
+%token BY
+%token CASCADE
+%token CASCADED
+%token CASE
+%token CAST
+%token CATALOG
+%token CEILING
+%token CENTER
+%token SQL_CHAR
+%token CHAR_LENGTH
+%token CHARACTER_STRING_LITERAL
+%token CHECK
+%token CLOSE
+%token COALESCE
+%token COBOL
+%token COLLATE
+%token COLLATION
+%token COLUMN
+%token COMMIT
+%token COMPUTE
+%token CONCAT
+%token CONCATENATION /* || */
+%token CONNECT
+%token CONNECTION
+%token CONSTRAINT
+%token CONSTRAINTS
+%token CONTINUE
+%token CONVERT
+%token CORRESPONDING
+%token COS
+%token COT
+%token COUNT
+%token CREATE
+%token CURDATE
+%token CURRENT
+%token CURRENT_DATE
+%token CURRENT_TIME
+%token CURRENT_TIMESTAMP
+%token CURTIME
+%token CURSOR
+%token DATABASE
+%token SQL_DATE
+%token DATE_FORMAT
+%token DATE_REMAINDER
+%token DATE_VALUE
+%token DAY
+%token DAYOFMONTH
+%token DAYOFWEEK
+%token DAYOFYEAR
+%token DAYS_BETWEEN
+%token DEALLOCATE
+%token DEC
+%token DECLARE
+%token DEFAULT
+%token DEFERRABLE
+%token DEFERRED
+%token SQL_DELETE
+%token DESC
+%token DESCRIBE
+%token DESCRIPTOR
+%token DIAGNOSTICS
+%token DICTIONARY
+%token DIRECTORY
+%token DISCONNECT
+%token DISPLACEMENT
+%token DISTINCT
+%token DOMAIN_TOKEN
+%token SQL_DOUBLE
+%token DOUBLE_QUOTED_STRING
+%token DROP
+%token ELSE
+%token END
+%token END_EXEC
+%token EQUAL
+%token ESCAPE
+%token EXCEPT
+%token SQL_EXCEPTION
+%token EXEC
+%token EXECUTE
+%token EXISTS
+%token EXP
+%token EXPONENT
+%token EXTERNAL
+%token EXTRACT
+%token SQL_FALSE
+%token FETCH
+%token FIRST
+%token SQL_FLOAT
+%token FLOOR
+%token FN
+%token FOR
+%token FOREIGN
+%token FORTRAN
+%token FOUND
+%token FOUR_DIGITS
+%token FROM
+%token FULL
+%token GET
+%token GLOBAL
+%token GO
+%token GOTO
+%token GRANT
+%token GREATER_OR_EQUAL
+//%token GREATER_THAN
+//conflict %token GROUP
+%token HAVING
+%token HOUR
+%token HOURS_BETWEEN
+%token IDENTITY
+%token IFNULL
+%token SQL_IGNORE
+%token IMMEDIATE
+%token SQL_IN
+%token INCLUDE
+%token INDEX
+%token INDICATOR
+%token INITIALLY
+%token INNER
+%token INPUT
+%token INSENSITIVE
+%token INSERT
+%token INTEGER
+%token INTERSECT
+%token INTERVAL
+%token INTO
+%token IS
+%token ISOLATION
+%token JOIN
+%token JUSTIFY
+%token KEY
+%token LANGUAGE
+%token LAST
+%token LCASE
+%token LEFT
+%token LENGTH
+%token LESS_OR_EQUAL
+//%token LESS_THAN
+%token LEVEL
+%token LIKE
+%token LINE_WIDTH
+%token LOCAL
+%token LOCATE
+%token LOG
+%token SQL_LONG
+%token LOWER
+%token LTRIM
+%token LTRIP
+%token MATCH
+%token SQL_MAX
+%token MICROSOFT
+%token SQL_MIN
+%token MINUS
+%token MINUTE
+%token MINUTES_BETWEEN
+%token MOD
+%token MODIFY
+%token MODULE
+%token MONTH
+%token MONTHS_BETWEEN
+%token MUMPS
+%token NAMES
+%token NATIONAL
+%token NCHAR
+%token NEXT
+%token NODUP
+%token NONE
+%token NOT
+%token NOT_EQUAL //<>
+%token NOT_EQUAL2 //!=
+%token NOW
+%token SQL_NULL
+%token SQL_IS
+%token SQL_IS_NULL /*helper */
+%token SQL_IS_NOT_NULL /*helper */
+%token NULLIF
+%token NUMERIC
+%token OCTET_LENGTH
+%token ODBC
+%token OF
+%token SQL_OFF
+%token SQL_ON
+%token ONLY
+%token OPEN
+%token OPTION
+%token OR
+%token ORDER
+%token OUTER
+%token OUTPUT
+%token OVERLAPS
+%token PAGE
+%token PARTIAL
+%token SQL_PASCAL
+%token PERSISTENT
+%token CQL_PI
+%token PLI
+%token POSITION
+%token PRECISION
+%token PREPARE
+%token PRESERVE
+%token PRIMARY
+%token PRIOR
+%token PRIVILEGES
+%token PROCEDURE
+%token PRODUCT
+%token PUBLIC
+%token QUARTER
+%token QUIT
+%token RAND
+%token READ_ONLY
+%token REAL
+%token REFERENCES
+%token REPEAT
+%token REPLACE
+%token RESTRICT
+%token REVOKE
+%token RIGHT
+%token ROLLBACK
+%token ROWS
+%token RPAD
+%token RTRIM
+%token SCHEMA
+%token SCREEN_WIDTH
+%token SCROLL
+%token SECOND
+%token SECONDS_BETWEEN
+%token SELECT
+%token SEQUENCE
+%token SETOPT
+%token SET
+%token SHOWOPT
+%token SIGN
+//%token SIMILAR
+%token SIMILAR_TO /* helper */
+%token NOT_SIMILAR_TO /* helper */
+%token INTEGER_CONST
+%token REAL_CONST
+%token DATE_CONST
+%token DATETIME_CONST
+%token TIME_CONST
+%token SIN
+%token SQL_SIZE
+%token SMALLINT
+%token SOME
+%token SPACE
+%token SQL
+%token SQL_TRUE
+%token SQLCA
+%token SQLCODE
+%token SQLERROR
+%token SQLSTATE
+%token SQLWARNING
+%token SQRT
+%token STDEV
+%token SUBSTRING
+%token SUM
+%token SYSDATE
+%token SYSDATE_FORMAT
+%token SYSTEM
+%token TABLE
+%token TAN
+%token TEMPORARY
+%token THEN
+%token THREE_DIGITS
+%token TIME
+%token TIMESTAMP
+%token TIMEZONE_HOUR
+%token TIMEZONE_MINUTE
+%token TINYINT
+%token TO
+%token TO_CHAR
+%token TO_DATE
+%token TRANSACTION
+%token TRANSLATE
+%token TRANSLATION
+%token TRUNCATE
+%token GENERAL_TITLE
+%token TWO_DIGITS
+%token UCASE
+%token UNION
+%token UNIQUE
+%token SQL_UNKNOWN
+//%token UNSIGNED_INTEGER
+%token UPDATE
+%token UPPER
+%token USAGE
+%token USER
+%token IDENTIFIER
+%token IDENTIFIER_DOT_ASTERISK
+%token QUERY_PARAMETER
+//%token ERROR_DIGIT_BEFORE_IDENTIFIER
+%token USING
+%token VALUE
+%token VALUES
+%token VARBINARY
+%token VARCHAR
+%token VARYING
+%token VENDOR
+%token VIEW
+%token WEEK
+%token WHEN
+%token WHENEVER
+%token WHERE
+%token WHERE_CURRENT_OF
+%token WITH
+%token WORD_WRAPPED
+%token WORK
+%token WRAPPED
+%token XOR
+%token YEAR
+%token YEARS_BETWEEN
+
+%token SCAN_ERROR
+%token __LAST_TOKEN /* sentinel */
+
+%token '-' '+'
+%token '*'
+%token '%'
+%token '@'
+%token ';'
+%token ','
+%token '.'
+%token '$'
+//%token '<'
+//%token '>'
+%token '(' ')'
+%token '?'
+%token '\''
+%token '/'
+
+%type <stringValue> IDENTIFIER
+%type <stringValue> IDENTIFIER_DOT_ASTERISK
+%type <stringValue> QUERY_PARAMETER
+%type <stringValue> CHARACTER_STRING_LITERAL
+%type <stringValue> DOUBLE_QUOTED_STRING
+
+/*
+%type <field> ColExpression
+%type <field> ColView
+*/
+%type <expr> ColExpression
+%type <expr> ColWildCard
+//%type <expr> ColView
+%type <expr> ColItem
+%type <exprList> ColViews
+%type <expr> aExpr
+%type <expr> aExpr2
+%type <expr> aExpr3
+%type <expr> aExpr4
+%type <expr> aExpr5
+%type <expr> aExpr6
+%type <expr> aExpr7
+%type <expr> aExpr8
+%type <expr> aExpr9
+%type <expr> aExpr10
+%type <exprList> aExprList
+%type <exprList> aExprList2
+%type <expr> WhereClause
+%type <orderByColumns> OrderByClause
+%type <booleanValue> OrderByOption
+%type <variantValue> OrderByColumnId
+%type <selectOptions> SelectOptions
+%type <expr> FlatTable
+%type <exprList> Tables
+%type <exprList> FlatTableList
+%type <querySchema> SelectStatement
+%type <querySchema> Select
+/*todo : list*/
+%type <querySchema> StatementList
+/*todo: not onlu select*/
+%type <querySchema> Statement
+
+%type <colType> SQL_TYPE
+%type <integerValue> INTEGER_CONST
+%type <realValue> REAL_CONST
+/*%type <integerValue> SIGNED_INTEGER */
+
+%{
+#ifndef YYDEBUG /* compat. */
+# define YYDEBUG 0
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <string>
+#include <iostream>
+#include <assert.h>
+#include <limits.h>
+//TODO OK?
+#ifdef Q_WS_WIN
+//workaround for bug on msvc
+# undef LLONG_MIN
+#endif
+#ifndef LLONG_MAX
+# define LLONG_MAX 0x7fffffffffffffffLL
+#endif
+#ifndef LLONG_MIN
+# define LLONG_MIN 0x8000000000000000LL
+#endif
+#ifndef LLONG_MAX
+# define ULLONG_MAX 0xffffffffffffffffLL
+#endif
+
+#ifdef _WIN32
+# include <malloc.h>
+#endif
+
+#include <qobject.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <qptrlist.h>
+#include <qcstring.h>
+#include <qvariant.h>
+
+#include <connection.h>
+#include <queryschema.h>
+#include <field.h>
+#include <tableschema.h>
+
+#include "parser.h"
+#include "parser_p.h"
+#include "sqltypes.h"
+
+int yylex();
+
+// using namespace std;
+using namespace KexiDB;
+
+#define YY_NO_UNPUT
+#define YYSTACK_USE_ALLOCA 1
+#define YYMAXDEPTH 255
+
+ extern "C"
+ {
+ int yywrap()
+ {
+ return 1;
+ }
+ }
+
+#if 0
+ struct yyval
+ {
+ QString parserUserName;
+ int integerValue;
+ KexiDBField::ColumnType coltype;
+ }
+#endif
+
+%}
+
+%union {
+ QString* stringValue;
+ Q_LLONG integerValue;
+ bool booleanValue;
+ struct realType realValue;
+ KexiDB::Field::Type colType;
+ KexiDB::Field *field;
+ KexiDB::BaseExpr *expr;
+ KexiDB::NArgExpr *exprList;
+ KexiDB::ConstExpr *constExpr;
+ KexiDB::QuerySchema *querySchema;
+ SelectOptionsInternal *selectOptions;
+ OrderByColumnInternal::List *orderByColumns;
+ QVariant *variantValue;
+}
+
+//%left '=' NOT_EQUAL '>' GREATER_OR_EQUAL '<' LESS_OR_EQUAL LIKE '%' NOT
+//%left '+' '-'
+//%left ASTERISK SLASH
+
+/* precedence: lowest to highest */
+%left UNION EXCEPT
+%left INTERSECT
+%left OR
+%left AND XOR
+%right NOT
+//%right '='
+//%nonassoc '<' '>'
+//%nonassoc '=' '<' '>' "<=" ">=" "<>" ":=" LIKE ILIKE SIMILAR
+//%nonassoc '=' LESS_THAN GREATER_THAN LESS_OR_EQUAL GREATER_OR_EQUAL NOT_EQUAL
+%nonassoc '=' '<' '>'
+//LESS_THAN GREATER_THAN
+%nonassoc LESS_OR_EQUAL GREATER_OR_EQUAL
+%nonassoc NOT_EQUAL NOT_EQUAL2
+%nonassoc SQL_IN LIKE ILIKE SIMILAR_TO NOT_SIMILAR_TO
+//%nonassoc LIKE ILIKE SIMILAR
+//%nonassoc ESCAPE
+//%nonassoc OVERLAPS
+%nonassoc BETWEEN
+//%nonassoc IN_P
+//%left POSTFIXOP // dummy for postfix Op rules
+//%left Op OPERATOR // multi-character ops and user-defined operators
+//%nonassoc NOTNULL
+//%nonassoc ISNULL
+//%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN // sets precedence for IS NULL, etc
+%left '+' '-'
+%left '*' '/' '%'
+%left '^'
+%left UMINUS
+// Unary Operators
+//%left AT ZONE // sets precedence for AT TIME ZONE
+//%right UMINUS
+%left '[' ']'
+%left '(' ')'
+//%left TYPECAST
+%left '.'
+
+/*
+ * These might seem to be low-precedence, but actually they are not part
+ * of the arithmetic hierarchy at all in their use as JOIN operators.
+ * We make them high-precedence to support their use as function names.
+ * They wouldn't be given a precedence at all, were it not that we need
+ * left-associativity among the JOIN rules themselves.
+ */
+/*%left JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
+*/
+%%
+
+TopLevelStatement :
+StatementList
+{
+//todo: multiple statements
+//todo: not only "select" statements
+ parser->setOperation(Parser::OP_Select);
+ parser->setQuerySchema($1);
+}
+;
+
+StatementList:
+Statement ';' StatementList
+{
+//todo: multiple statements
+}
+| Statement
+| Statement ';'
+{
+ $$ = $1;
+}
+;
+
+/* Statement CreateTableStatement { YYACCEPT; }
+ | Statement SelectStatement { }
+*/
+Statement :
+CreateTableStatement
+{
+YYACCEPT;
+}
+| SelectStatement
+{
+ $$ = $1;
+}
+;
+
+CreateTableStatement :
+CREATE TABLE IDENTIFIER
+{
+ parser->setOperation(Parser::OP_CreateTable);
+ parser->createTable($3->latin1());
+ delete $3;
+}
+'(' ColDefs ')'
+;
+
+ColDefs:
+ColDefs ',' ColDef|ColDef
+{
+}
+;
+
+ColDef:
+IDENTIFIER ColType
+{
+ KexiDBDbg << "adding field " << *$1 << endl;
+ field->setName($1->latin1());
+ parser->table()->addField(field);
+ field = 0;
+ delete $1;
+}
+| IDENTIFIER ColType ColKeys
+{
+ KexiDBDbg << "adding field " << *$1 << endl;
+ field->setName(*$1);
+ delete $1;
+ parser->table()->addField(field);
+
+// if(field->isPrimaryKey())
+// parser->table()->addPrimaryKey(field->name());
+
+// delete field;
+// field = 0;
+}
+;
+
+ColKeys:
+ColKeys ColKey|ColKey
+{
+}
+;
+
+ColKey:
+PRIMARY KEY
+{
+ field->setPrimaryKey(true);
+ KexiDBDbg << "primary" << endl;
+}
+| NOT SQL_NULL
+{
+ field->setNotNull(true);
+ KexiDBDbg << "not_null" << endl;
+}
+| AUTO_INCREMENT
+{
+ field->setAutoIncrement(true);
+ KexiDBDbg << "ainc" << endl;
+}
+;
+
+ColType:
+SQL_TYPE
+{
+ field = new Field();
+ field->setType($1);
+}
+| SQL_TYPE '(' INTEGER_CONST ')'
+{
+ KexiDBDbg << "sql + length" << endl;
+ field = new Field();
+ field->setPrecision($3);
+ field->setType($1);
+}
+| VARCHAR '(' INTEGER_CONST ')'
+{
+ field = new Field();
+ field->setPrecision($3);
+ field->setType(Field::Text);
+}
+|
+{
+ // SQLITE compatibillity
+ field = new Field();
+ field->setType(Field::InvalidType);
+}
+;
+
+SelectStatement:
+Select ColViews
+{
+ KexiDBDbg << "Select ColViews=" << $2->debugString() << endl;
+
+ if (!($$ = buildSelectQuery( $1, $2 )))
+ return 0;
+}
+| Select ColViews Tables
+{
+ if (!($$ = buildSelectQuery( $1, $2, $3 )))
+ return 0;
+}
+| Select Tables
+{
+ KexiDBDbg << "Select ColViews Tables" << endl;
+ if (!($$ = buildSelectQuery( $1, 0, $2 )))
+ return 0;
+}
+| Select ColViews SelectOptions
+{
+ KexiDBDbg << "Select ColViews Conditions" << endl;
+ if (!($$ = buildSelectQuery( $1, $2, 0, $3 )))
+ return 0;
+}
+| Select ColViews Tables SelectOptions
+{
+ KexiDBDbg << "Select ColViews Tables SelectOptions" << endl;
+ if (!($$ = buildSelectQuery( $1, $2, $3, $4 )))
+ return 0;
+}
+;
+
+Select:
+SELECT
+{
+ KexiDBDbg << "SELECT" << endl;
+// parser->createSelect();
+// parser->setOperation(Parser::OP_Select);
+ $$ = new QuerySchema();
+}
+;
+
+SelectOptions: /* todo: more options (having, group by, limit...) */
+WhereClause
+{
+ KexiDBDbg << "WhereClause" << endl;
+ $$ = new SelectOptionsInternal;
+ $$->whereExpr = $1;
+}
+| ORDER BY OrderByClause
+{
+ KexiDBDbg << "OrderByClause" << endl;
+ $$ = new SelectOptionsInternal;
+ $$->orderByColumns = $3;
+}
+| WhereClause ORDER BY OrderByClause
+{
+ KexiDBDbg << "WhereClause ORDER BY OrderByClause" << endl;
+ $$ = new SelectOptionsInternal;
+ $$->whereExpr = $1;
+ $$->orderByColumns = $4;
+}
+| ORDER BY OrderByClause WhereClause
+{
+ KexiDBDbg << "OrderByClause WhereClause" << endl;
+ $$ = new SelectOptionsInternal;
+ $$->whereExpr = $4;
+ $$->orderByColumns = $3;
+}
+;
+
+WhereClause:
+WHERE aExpr
+{
+ $$ = $2;
+}
+;
+
+/* todo: support "ORDER BY NULL" as described here http://dev.mysql.com/doc/refman/5.1/en/select.html */
+/* todo: accept expr and position as well */
+OrderByClause:
+OrderByColumnId
+{
+ KexiDBDbg << "ORDER BY IDENTIFIER" << endl;
+ $$ = new OrderByColumnInternal::List;
+ OrderByColumnInternal orderByColumn;
+ orderByColumn.setColumnByNameOrNumber( *$1 );
+ $$->append( orderByColumn );
+ delete $1;
+}
+| OrderByColumnId OrderByOption
+{
+ KexiDBDbg << "ORDER BY IDENTIFIER OrderByOption" << endl;
+ $$ = new OrderByColumnInternal::List;
+ OrderByColumnInternal orderByColumn;
+ orderByColumn.setColumnByNameOrNumber( *$1 );
+ orderByColumn.ascending = $2;
+ $$->append( orderByColumn );
+ delete $1;
+}
+| OrderByColumnId ',' OrderByClause
+{
+ $$ = $3;
+ OrderByColumnInternal orderByColumn;
+ orderByColumn.setColumnByNameOrNumber( *$1 );
+ $$->append( orderByColumn );
+ delete $1;
+}
+| OrderByColumnId OrderByOption ',' OrderByClause
+{
+ $$ = $4;
+ OrderByColumnInternal orderByColumn;
+ orderByColumn.setColumnByNameOrNumber( *$1 );
+ orderByColumn.ascending = $2;
+ $$->append( orderByColumn );
+ delete $1;
+}
+;
+
+OrderByColumnId:
+IDENTIFIER
+{
+ $$ = new QVariant( *$1 );
+ KexiDBDbg << "OrderByColumnId: " << *$$ << endl;
+ delete $1;
+}
+| IDENTIFIER '.' IDENTIFIER
+{
+ $$ = new QVariant( *$1 + "." + *$3 );
+ KexiDBDbg << "OrderByColumnId: " << *$$ << endl;
+ delete $1;
+ delete $3;
+}
+| INTEGER_CONST
+{
+ $$ = new QVariant($1);
+ KexiDBDbg << "OrderByColumnId: " << *$$ << endl;
+}
+
+OrderByOption:
+ASC
+{
+ $$ = true;
+}
+| DESC
+{
+ $$ = false;
+}
+;
+
+aExpr:
+aExpr2
+;
+
+/* --- binary logical --- */
+aExpr2:
+aExpr3 AND aExpr2
+{
+// KexiDBDbg << "AND " << $3.debugString() << endl;
+ $$ = new BinaryExpr( KexiDBExpr_Logical, $1, AND, $3 );
+}
+| aExpr3 OR aExpr2
+{
+ $$ = new BinaryExpr( KexiDBExpr_Logical, $1, OR, $3 );
+}
+| aExpr3 XOR aExpr2
+{
+ $$ = new BinaryExpr( KexiDBExpr_Arithm, $1, XOR, $3 );
+}
+|
+aExpr3
+;
+
+/* relational op precedence */
+aExpr3:
+aExpr4 '>' %prec GREATER_OR_EQUAL aExpr3
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, '>', $3);
+}
+| aExpr4 GREATER_OR_EQUAL aExpr3
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, GREATER_OR_EQUAL, $3);
+}
+| aExpr4 '<' %prec LESS_OR_EQUAL aExpr3
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, '<', $3);
+}
+| aExpr4 LESS_OR_EQUAL aExpr3
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, LESS_OR_EQUAL, $3);
+}
+| aExpr4 '=' aExpr3
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, '=', $3);
+}
+|
+aExpr4
+;
+
+/* relational (equality) op precedence */
+aExpr4:
+aExpr5 NOT_EQUAL aExpr4
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_EQUAL, $3);
+}
+|
+aExpr5 NOT_EQUAL2 aExpr4
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_EQUAL2, $3);
+}
+| aExpr5 LIKE aExpr4
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, LIKE, $3);
+}
+| aExpr5 SQL_IN aExpr4
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, SQL_IN, $3);
+}
+| aExpr5 SIMILAR_TO aExpr4
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, SIMILAR_TO, $3);
+}
+| aExpr5 NOT_SIMILAR_TO aExpr4
+{
+ $$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_SIMILAR_TO, $3);
+}
+|
+aExpr5
+;
+
+/* --- unary logical right --- */
+aExpr5:
+aExpr5 SQL_IS_NULL
+{
+ $$ = new UnaryExpr( SQL_IS_NULL, $1 );
+}
+| aExpr5 SQL_IS_NOT_NULL
+{
+ $$ = new UnaryExpr( SQL_IS_NOT_NULL, $1 );
+}
+|
+aExpr6
+;
+
+/* arithm. lowest precedence */
+aExpr6:
+aExpr7 BITWISE_SHIFT_LEFT aExpr6
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, BITWISE_SHIFT_LEFT, $3);
+}
+| aExpr7 BITWISE_SHIFT_RIGHT aExpr6
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, BITWISE_SHIFT_RIGHT, $3);
+}
+|
+aExpr7
+;
+
+/* arithm. lower precedence */
+aExpr7:
+aExpr8 '+' aExpr7
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '+', $3);
+ $$->debug();
+}
+| aExpr8 '-' %prec UMINUS aExpr7
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '-', $3);
+}
+| aExpr8 '&' aExpr7
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '&', $3);
+}
+| aExpr8 '|' aExpr7
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '|', $3);
+}
+|
+aExpr8
+;
+
+/* arithm. higher precedence */
+aExpr8:
+aExpr9 '/' aExpr8
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '/', $3);
+}
+| aExpr9 '*' aExpr8
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '*', $3);
+}
+| aExpr9 '%' aExpr8
+{
+ $$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '%', $3);
+}
+|
+aExpr9
+;
+
+/* parenthesis, unary operators, and terminals precedence */
+aExpr9:
+/* --- unary logical left --- */
+'-' aExpr9
+{
+ $$ = new UnaryExpr( '-', $2 );
+}
+| '+' aExpr9
+{
+ $$ = new UnaryExpr( '+', $2 );
+}
+| '~' aExpr9
+{
+ $$ = new UnaryExpr( '~', $2 );
+}
+| NOT aExpr9
+{
+ $$ = new UnaryExpr( NOT, $2 );
+}
+| IDENTIFIER
+{
+ $$ = new VariableExpr( *$1 );
+
+//TODO: simplify this later if that's 'only one field name' expression
+ KexiDBDbg << " + identifier: " << *$1 << endl;
+ delete $1;
+}
+| QUERY_PARAMETER
+{
+ $$ = new QueryParameterExpr( *$1 );
+ KexiDBDbg << " + query parameter: " << $$->debugString() << endl;
+ delete $1;
+}
+| IDENTIFIER aExprList
+{
+ KexiDBDbg << " + function: " << *$1 << "(" << $2->debugString() << ")" << endl;
+ $$ = new FunctionExpr(*$1, $2);
+ delete $1;
+}
+/*TODO: shall we also support db name? */
+| IDENTIFIER '.' IDENTIFIER
+{
+ $$ = new VariableExpr( *$1 + "." + *$3 );
+ KexiDBDbg << " + identifier.identifier: " << *$1 << "." << *$3 << endl;
+ delete $1;
+ delete $3;
+}
+| SQL_NULL
+{
+ $$ = new ConstExpr( SQL_NULL, QVariant() );
+ KexiDBDbg << " + NULL" << endl;
+// $$ = new Field();
+ //$$->setName(QString::null);
+}
+| CHARACTER_STRING_LITERAL
+{
+ $$ = new ConstExpr( CHARACTER_STRING_LITERAL, *$1 );
+ KexiDBDbg << " + constant " << $1 << endl;
+ delete $1;
+}
+| INTEGER_CONST
+{
+ QVariant val;
+ if ($1 <= INT_MAX && $1 >= INT_MIN)
+ val = (int)$1;
+ else if ($1 <= UINT_MAX && $1 >= 0)
+ val = (uint)$1;
+ else if ($1 <= (Q_LLONG)LLONG_MAX && $1 >= (Q_LLONG)LLONG_MIN)
+ val = (Q_LLONG)$1;
+
+// if ($1 < ULLONG_MAX)
+// val = (Q_ULLONG)$1;
+//TODO ok?
+
+ $$ = new ConstExpr( INTEGER_CONST, val );
+ KexiDBDbg << " + int constant: " << val.toString() << endl;
+}
+| REAL_CONST
+{
+ $$ = new ConstExpr( REAL_CONST, QPoint( $1.integer, $1.fractional ) );
+ KexiDBDbg << " + real constant: " << $1.integer << "." << $1.fractional << endl;
+}
+|
+aExpr10
+;
+
+
+aExpr10:
+'(' aExpr ')'
+{
+ KexiDBDbg << "(expr)" << endl;
+ $$ = new UnaryExpr('(', $2);
+}
+;
+
+aExprList:
+'(' aExprList2 ')'
+{
+// $$ = new NArgExpr(0, 0);
+// $$->add( $1 );
+// $$->add( $3 );
+ $$ = $2;
+}
+;
+
+aExprList2:
+aExpr ',' aExprList2
+{
+ $$ = $3;
+ $$->prepend( $1 );
+}
+| aExpr ',' aExpr
+{
+ $$ = new NArgExpr(0, 0);
+ $$->add( $1 );
+ $$->add( $3 );
+}
+;
+
+Tables:
+FROM FlatTableList
+{
+ $$ = $2;
+}
+/*
+| Tables LEFT JOIN IDENTIFIER SQL_ON ColExpression
+{
+ KexiDBDbg << "LEFT JOIN: '" << *$4 << "' ON " << $6 << endl;
+ addTable($4->toQString());
+ delete $4;
+}
+| Tables LEFT OUTER JOIN IDENTIFIER SQL_ON ColExpression
+{
+ KexiDBDbg << "LEFT OUTER JOIN: '" << $5 << "' ON " << $7 << endl;
+ addTable($5);
+}
+| Tables INNER JOIN IDENTIFIER SQL_ON ColExpression
+{
+ KexiDBDbg << "INNER JOIN: '" << *$4 << "' ON " << $6 << endl;
+ addTable($4->toQString());
+ delete $4;
+}
+| Tables RIGHT JOIN IDENTIFIER SQL_ON ColExpression
+{
+ KexiDBDbg << "RIGHT JOIN: '" << *$4 << "' ON " << $6 << endl;
+ addTable(*$4);
+ delete $4;
+}
+| Tables RIGHT OUTER JOIN IDENTIFIER SQL_ON ColExpression
+{
+ KexiDBDbg << "RIGHT OUTER JOIN: '" << *$5 << "' ON " << $7 << endl;
+ addTable($5->toQString());
+ delete $5;
+}*/
+;
+
+/*
+FlatTableList:
+aFlatTableList
+{
+ $$
+}
+;*/
+
+FlatTableList:
+FlatTableList ',' FlatTable
+{
+ $$ = $1;
+ $$->add($3);
+}
+|FlatTable
+{
+ $$ = new NArgExpr(KexiDBExpr_TableList, IDENTIFIER); //ok?
+ $$->add($1);
+}
+;
+
+FlatTable:
+IDENTIFIER
+{
+ KexiDBDbg << "FROM: '" << *$1 << "'" << endl;
+ $$ = new VariableExpr(*$1);
+
+ /*
+//TODO: this isn't ok for more tables:
+ Field::ListIterator it = parser->select()->fieldsIterator();
+ for(Field *item; (item = it.current()); ++it)
+ {
+ if(item->table() == dummy)
+ {
+ item->setTable(schema);
+ }
+
+ if(item->table() && !item->isQueryAsterisk())
+ {
+ Field *f = item->table()->field(item->name());
+ if(!f)
+ {
+ ParserError err(i18n("Field List Error"), i18n("Unknown column '%1' in table '%2'").arg(item->name()).arg(schema->name()), ctoken, current);
+ parser->setError(err);
+ yyerror("fieldlisterror");
+ }
+ }
+ }*/
+ delete $1;
+}
+| IDENTIFIER IDENTIFIER
+{
+ //table + alias
+ $$ = new BinaryExpr(
+ KexiDBExpr_SpecialBinary,
+ new VariableExpr(*$1), 0,
+ new VariableExpr(*$2)
+ );
+ delete $1;
+ delete $2;
+}
+| IDENTIFIER AS IDENTIFIER
+{
+ //table + alias
+ $$ = new BinaryExpr(
+ KexiDBExpr_SpecialBinary,
+ new VariableExpr(*$1), AS,
+ new VariableExpr(*$3)
+ );
+ delete $1;
+ delete $3;
+}
+;
+
+
+
+ColViews:
+ColViews ',' ColItem
+{
+ $$ = $1;
+ $$->add( $3 );
+ KexiDBDbg << "ColViews: ColViews , ColItem" << endl;
+}
+|ColItem
+{
+ $$ = new NArgExpr(0,0);
+ $$->add( $1 );
+ KexiDBDbg << "ColViews: ColItem" << endl;
+}
+;
+
+ColItem:
+ColExpression
+{
+// $$ = new Field();
+// dummy->addField($$);
+// $$->setExpression( $1 );
+// parser->select()->addField($$);
+ $$ = $1;
+ KexiDBDbg << " added column expr: '" << $1->debugString() << "'" << endl;
+}
+| ColWildCard
+{
+ $$ = $1;
+ KexiDBDbg << " added column wildcard: '" << $1->debugString() << "'" << endl;
+}
+| ColExpression AS IDENTIFIER
+{
+ $$ = new BinaryExpr(
+ KexiDBExpr_SpecialBinary, $1, AS,
+ new VariableExpr(*$3)
+ );
+ KexiDBDbg << " added column expr: " << $$->debugString() << endl;
+ delete $3;
+}
+| ColExpression IDENTIFIER
+{
+ $$ = new BinaryExpr(
+ KexiDBExpr_SpecialBinary, $1, 0,
+ new VariableExpr(*$2)
+ );
+ KexiDBDbg << " added column expr: " << $$->debugString() << endl;
+ delete $2;
+}
+;
+
+ColExpression:
+aExpr
+{
+ $$ = $1;
+}
+/* HANDLED BY 'IDENTIFIER aExprList'
+| IDENTIFIER '(' ColViews ')'
+{
+ $$ = new FunctionExpr( $1, $3 );
+}*/
+/*
+| SUM '(' ColExpression ')'
+{
+ FunctionExpr(
+// $$ = new AggregationExpr( SUM, );
+//TODO
+// $$->setName("SUM(" + $3->name() + ")");
+//wait $$->containsGroupingAggregate(true);
+//wait parser->select()->grouped(true);
+}
+| SQL_MIN '(' ColExpression ')'
+{
+ $$ = $3;
+//TODO
+// $$->setName("MIN(" + $3->name() + ")");
+//wait $$->containsGroupingAggregate(true);
+//wait parser->select()->grouped(true);
+}
+| SQL_MAX '(' ColExpression ')'
+{
+ $$ = $3;
+//TODO
+// $$->setName("MAX(" + $3->name() + ")");
+//wait $$->containsGroupingAggregate(true);
+//wait parser->select()->grouped(true);
+}
+| AVG '(' ColExpression ')'
+{
+ $$ = $3;
+//TODO
+// $$->setName("AVG(" + $3->name() + ")");
+//wait $$->containsGroupingAggregate(true);
+//wait parser->select()->grouped(true);
+}*/
+//?
+| DISTINCT '(' ColExpression ')'
+{
+ $$ = $3;
+//TODO
+// $$->setName("DISTINCT(" + $3->name() + ")");
+}
+;
+
+ColWildCard:
+'*'
+{
+ $$ = new VariableExpr("*");
+ KexiDBDbg << "all columns" << endl;
+
+// QueryAsterisk *ast = new QueryAsterisk(parser->select(), dummy);
+// parser->select()->addAsterisk(ast);
+// requiresTable = true;
+}
+| IDENTIFIER '.' '*'
+{
+ QString s( *$1 );
+ s += ".*";
+ $$ = new VariableExpr(s);
+ KexiDBDbg << " + all columns from " << s << endl;
+ delete $1;
+}
+/*| ERROR_DIGIT_BEFORE_IDENTIFIER
+{
+ $$ = new VariableExpr($1);
+ KexiDBDbg << " Invalid identifier! " << $1 << endl;
+ setError(i18n("Invalid identifier \"%1\"").arg($1));
+}*/
+;
+
+%%
+