/* This file is part of the KDE project Copyright (C) 2004 Lucijan Busch Copyright (C) 2004, 2006 Jaroslaw Staniek 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 IDENTIFIER %type IDENTIFIER_DOT_ASTERISK %type QUERY_PARAMETER %type CHARACTER_STRING_LITERAL %type DOUBLE_QUOTED_STRING /* %type ColExpression %type ColView */ %type ColExpression %type ColWildCard //%type ColView %type ColItem %type ColViews %type aExpr %type aExpr2 %type aExpr3 %type aExpr4 %type aExpr5 %type aExpr6 %type aExpr7 %type aExpr8 %type aExpr9 %type aExpr10 %type aExprList %type aExprList2 %type WhereClause %type OrderByClause %type OrderByOption %type OrderByColumnId %type SelectOptions %type FlatTable %type Tables %type FlatTableList %type SelectStatement %type Select /*todo : list*/ %type StatementList /*todo: not onlu select*/ %type Statement %type SQL_TYPE %type INTEGER_CONST %type REAL_CONST /*%type SIGNED_INTEGER */ %{ #ifndef YYDEBUG /* compat. */ # define YYDEBUG 0 #endif #include #include #include #include #include #include //TODO OK? #ifdef TQ_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 #endif #include #include #include #include #include #include #include #include #include #include #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 { TQString parserUserName; int integerValue; KexiDBField::ColumnType coltype; } #endif %} %union { TQString* stringValue; TQ_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 TQuerySchema(); } ; 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 TQVariant( *$1 ); KexiDBDbg << "OrderByColumnId: " << *$$ << endl; delete $1; } | IDENTIFIER '.' IDENTIFIER { $$ = new TQVariant( *$1 + "." + *$3 ); KexiDBDbg << "OrderByColumnId: " << *$$ << endl; delete $1; delete $3; } | INTEGER_CONST { $$ = new TQVariant($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, TQVariant() ); KexiDBDbg << " + NULL" << endl; // $$ = new Field(); //$$->setName(TQString::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 <= (TQ_LLONG)LLONG_MAX && $1 >= (TQ_LLONG)LLONG_MIN) val = (TQ_LLONG)$1; // if ($1 < ULLONG_MAX) // val = (TQ_ULLONG)$1; //TODO ok? $$ = new ConstExpr( INTEGER_CONST, val ); KexiDBDbg << " + int constant: " << val.toString() << endl; } | REAL_CONST { $$ = new ConstExpr( REAL_CONST, TQPoint( $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 '.' '*' { TQString 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)); }*/ ; %%