1 /* This file is part of the KDE project
2    Copyright (C) 2004 Lucijan Busch <lucijan@kde.org>
3    Copyright (C) 2004-2018 Jarosław Staniek <staniek@kde.org>
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public License
16    along with this library; see the file COPYING.LIB.  If not, write to
17    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19 */
20 
21 // To keep binary compatibility, do not reorder tokens! Add new only at the end.
22 %token SQL_TYPE
23 %token AS
24 %token AS_EMPTY /* used for aliases with skipped AS keyword */
25 %token ASC
26 %token AUTO_INCREMENT
27 %token BIT
28 %token BITWISE_SHIFT_LEFT
29 %token BITWISE_SHIFT_RIGHT
30 %token BY
31 %token CHARACTER_STRING_LITERAL
32 %token CONCATENATION /* || */
33 %token CREATE
34 %token DESC
35 %token DISTINCT
36 %token DOUBLE_QUOTED_STRING
37 %token FROM
38 %token JOIN
39 %token KEY
40 %token LEFT
41 %token LESS_OR_EQUAL
42 %token GREATER_OR_EQUAL
43 %token SQL_NULL
44 %token SQL_IS
45 %token SQL_IS_NULL /*helper */
46 %token SQL_IS_NOT_NULL /*helper */
47 %token ORDER
48 %token PRIMARY
49 %token SELECT
50 %token INTEGER_CONST
51 %token REAL_CONST
52 %token RIGHT
53 %token SQL_ON
54 %token DATE_CONST
55 %token DATETIME_CONST
56 %token TIME_CONST
57 %token TABLE
58 %token IDENTIFIER
59 %token IDENTIFIER_DOT_ASTERISK
60 %token QUERY_PARAMETER
61 %token VARCHAR
62 %token WHERE
63 %token SQL
64 %token SQL_TRUE
65 %token SQL_FALSE
66 %token UNION
67 
68 %token SCAN_ERROR
69 
70 //%token SQL_ABS
71 //%token ACOS
72 //%token AMPERSAND
73 //%token SQL_ABSOLUTE
74 //%token ADA
75 //%token ADD
76 //%token ADD_DAYS
77 //%token ADD_HOURS
78 //%token ADD_MINUTES
79 //%token ADD_MONTHS
80 //%token ADD_SECONDS
81 //%token ADD_YEARS
82 //%token ALL
83 //%token ALLOCATE
84 //%token ALTER
85 %token AND
86 //%token ANY
87 //%token ARE
88 //%token ASIN
89 //%token ASCII
90 //%token ASSERTION
91 //%token ATAN
92 //%token ATAN2
93 //%token AUTHORIZATION
94 //%token AVG
95 //%token BEFORE
96 %token BETWEEN
97 %token NOT_BETWEEN
98 //%token SQL_BEGIN
99 //%token BIGINT
100 //%token BINARY
101 //%token BIT_LENGTH
102 //%token BREAK
103 //%token CASCADE
104 //%token CASCADED
105 //%token CASE
106 //%token CAST
107 //%token CATALOG
108 //%token CEILING
109 //%token CENTER
110 //%token SQL_CHAR
111 //%token CHAR_LENGTH
112 //%token CHECK
113 //%token CLOSE
114 //%token COALESCE
115 //%token COBOL
116 //%token COLLATE
117 //%token COLLATION
118 //%token COLUMN
119 //%token COMMIT
120 //%token COMPUTE
121 //%token CONCAT
122 //%token CONNECT
123 //%token CONNECTION
124 //%token CONSTRAINT
125 //%token CONSTRAINTS
126 //%token CONTINUE
127 //%token CONVERT
128 //%token CORRESPONDING
129 //%token COS
130 //%token COT
131 //%token COUNT
132 //%token CURDATE
133 //%token CURRENT
134 //%token CURRENT_DATE
135 //%token CURRENT_TIME
136 //%token CURRENT_TIMESTAMP
137 //%token CURTIME
138 //%token CURSOR
139 //%token DATABASE
140 //%token SQL_DATE
141 //%token DATE_FORMAT
142 //%token DATE_REMAINDER
143 //%token DATE_VALUE
144 //%token DAY
145 //%token DAYOFMONTH
146 //%token DAYOFWEEK
147 //%token DAYOFYEAR
148 //%token DAYS_BETWEEN
149 //%token DEALLOCATE
150 //%token DEC
151 //%token DECLARE
152 //%token DEFAULT
153 //%token DEFERRABLE
154 //%token DEFERRED
155 //%token SQL_DELETE
156 //%token DESCRIBE
157 //%token DESCRIPTOR
158 //%token DIAGNOSTICS
159 //%token DICTIONARY
160 //%token DIRECTORY
161 //%token DISCONNECT
162 //%token DISPLACEMENT
163 //%token DOMAIN_TOKEN
164 //%token SQL_DOUBLE
165 //%token DROP
166 //%token ELSE
167 //%token END
168 //%token END_EXEC
169 //%token ESCAPE
170 %token EXCEPT
171 //%token SQL_EXCEPTION
172 //%token EXEC
173 //%token EXECUTE
174 //%token EXISTS
175 //%token EXP
176 //%token EXPONENT
177 //%token EXTERNAL
178 //%token EXTRACT
179 //%token FETCH
180 //%token FIRST
181 //%token SQL_FLOAT
182 //%token FLOOR
183 //%token FN
184 //%token FOR
185 //%token FOREIGN
186 //%token FORTRAN
187 //%token FOUND
188 //%token FOUR_DIGITS
189 //%token FULL
190 //%token GET
191 //%token GLOBAL
192 //%token GO
193 //%token GOTO
194 //%token GRANT
195 //conflict %token GROUP
196 //%token HAVING
197 //%token HOUR
198 //%token HOURS_BETWEEN
199 //%token IDENTITY
200 //%token IFNULL
201 //%token SQL_IGNORE
202 //%token IMMEDIATE
203 //%token INCLUDE
204 //%token INDEX
205 //%token INDICATOR
206 //%token INITIALLY
207 //%token INNER
208 //%token SQL_INPUT
209 %token SQL_IN
210 //%token INSENSITIVE
211 //%token INSERT
212 //%token INTEGER
213 %token INTERSECT
214 //%token INTERVAL
215 //%token INTO
216 //%token IS
217 //%token ISOLATION
218 //%token JUSTIFY
219 //%token LANGUAGE
220 //%token LAST
221 //%token LCASE
222 //%token LENGTH
223 //%token LEVEL
224 %token LIKE
225 %token ILIKE
226 %token NOT_LIKE
227 //%token LINE_WIDTH
228 //%token LOCAL
229 //%token LOCATE
230 //%token LOG
231 //%token SQL_LONG
232 //%token LOWER
233 //%token LTRIM
234 //%token LTRIP
235 //%token MATCH
236 //%token SQL_MAX
237 //%token MICROSOFT
238 //%token SQL_MIN
239 //%token MINUTE
240 //%token MINUTES_BETWEEN
241 //%token MOD
242 //%token MODIFY
243 //%token MODULE
244 //%token MONTH
245 //%token MONTHS_BETWEEN
246 //%token MUMPS
247 //%token NAMES
248 //%token NATIONAL
249 //%token NCHAR
250 //%token NEXT
251 //%token NODUP
252 //%token NONE
253 %token NOT
254 %token NOT_EQUAL
255 %token NOT_EQUAL2
256 //%token NOW
257 //%token NULLIF
258 //%token NUMERIC
259 //%token OCTET_LENGTH
260 //%token ODBC
261 //%token OF
262 //%token SQL_OFF
263 //%token ONLY
264 //%token OPEN
265 //%token OPTION
266 //%token OUTER
267 //%token OUTPUT
268 //%token OVERLAPS
269 //%token PAGE
270 //%token PARTIAL
271 //%token SQL_PASCAL
272 //%token PERSISTENT
273 //%token CQL_PI
274 %token OR
275 //%token PLI
276 //%token POSITION
277 //%token PRECISION
278 //%token PREPARE
279 //%token PRESERVE
280 //%token PRIOR
281 //%token PRIVILEGES
282 //%token PROCEDURE
283 //%token PRODUCT
284 //%token PUBLIC
285 //%token QUARTER
286 //%token QUIT
287 //%token RAND
288 //%token READ_ONLY
289 //%token REAL
290 //%token REFERENCES
291 //%token REPEAT
292 //%token REPLACE
293 //%token RESTRICT
294 //%token REVOKE
295 //%token ROLLBACK
296 //%token ROWS
297 //%token RPAD
298 //%token RTRIM
299 //%token SCHEMA
300 //%token SCREEN_WIDTH
301 //%token SCROLL
302 //%token SECOND
303 //%token SECONDS_BETWEEN
304 //%token SEQUENCE
305 //%token SETOPT
306 //%token SET
307 //%token SHOWOPT
308 //%token SIGN
309 %token SIMILAR_TO
310 %token NOT_SIMILAR_TO
311 //%token SIN
312 //%token SQL_SIZE
313 //%token SMALLINT
314 //%token SOME
315 //%token SPACE
316 //%token SQLCA
317 //%token SQLCODE
318 //%token SQLERROR
319 //%token SQLSTATE
320 //%token SQLWARNING
321 //%token SQRT
322 //%token STDEV
323 //%token SUBSTRING
324 //%token SUM
325 //%token SYSDATE
326 //%token SYSDATE_FORMAT
327 //%token SYSTEM
328 //%token TAN
329 //%token TEMPORARY
330 //%token THEN
331 //%token THREE_DIGITS
332 //%token TIME
333 //%token TIMESTAMP
334 //%token TIMEZONE_HOUR
335 //%token TIMEZONE_MINUTE
336 //%token TINYINT
337 //%token TO
338 //%token TO_CHAR
339 //%token TO_DATE
340 //%token TRANSACTION
341 //%token TRANSLATE
342 //%token TRANSLATION
343 //%token TRUNCATE
344 //%token GENERAL_TITLE
345 //%token TWO_DIGITS
346 //%token UCASE
347 //%token UNIQUE
348 //%token SQL_UNKNOWN
349 //%token UNSIGNED_INTEGER
350 //%token UPDATE
351 //%token UPPER
352 //%token USAGE
353 //%token USER
354 //%token ERROR_DIGIT_BEFORE_IDENTIFIER
355 //%token USING
356 //%token VALUE
357 //%token VALUES
358 //%token VARBINARY
359 //%token VARYING
360 //%token VENDOR
361 //%token VIEW
362 //%token WEEK
363 //%token WHEN
364 //%token WHENEVER
365 //%token WHERE_CURRENT_OF
366 //%token WITH
367 //%token WORD_WRAPPED
368 //%token WORK
369 //%token WRAPPED
370 %token XOR
371 //%token YEAR
372 //%token YEARS_BETWEEN
373 %token UMINUS
374 %token TABS_OR_SPACES    // e.g. inside of date or time constants
375 %token DATE_TIME_INTEGER // inside of date or time constants
376 %token TIME_AM
377 %token TIME_PM
378 
379 %type <stringValue> IDENTIFIER
380 %type <stringValue> IDENTIFIER_DOT_ASTERISK
381 %type <stringValue> QUERY_PARAMETER
382 %type <stringValue> CHARACTER_STRING_LITERAL
383 %type <stringValue> DOUBLE_QUOTED_STRING
384 
385 /*
386 %type <field> ColExpression
387 %type <field> ColView
388 */
389 %type <expr> ColExpression
390 %type <expr> ColWildCard
391 //%type <expr> ColView
392 %type <expr> ColItem
393 %type <exprList> ColViews
394 %type <expr> aExpr
395 %type <expr> aExpr2
396 %type <expr> aExpr3
397 %type <expr> aExpr4
398 %type <expr> aExpr5
399 %type <expr> aExpr6
400 %type <expr> aExpr7
401 %type <expr> aExpr8
402 %type <expr> aExpr9
403 %type <expr> aExpr10
404 %type <dateValue> DateConst
405 %type <dateValue> DateValue
406 %type <yearValue> YearConst
407 %type <timeValue> TimeConst
408 %type <timeValue> TimeValue
409 %type <dateTimeValue> DateTimeConst
410 %type <binaryValue> TimeMs
411 %type <timePeriodValue> TimePeriod
412 %type <exprList> aExprList
413 %type <exprList> aExprList2
414 %type <expr> WhereClause
415 %type <orderByColumns> OrderByClause
416 %type <sortOrderValue> OrderByOption
417 %type <variantValue> OrderByColumnId
418 %type <selectOptions> SelectOptions
419 %type <expr> FlatTable
420 %type <exprList> Tables
421 %type <exprList> FlatTableList
422 %type <querySchema> SelectStatement
423 %type <querySchema> Select
424 /*todo : list*/
425 %type <querySchema> StatementList
426 /*todo: not only select*/
427 %type <querySchema> Statement
428 
429 %type <colType> SQL_TYPE
430 %type <integerValue> INTEGER_CONST
431 %type <binaryValue> REAL_CONST
432 %type <binaryValue> DATE_TIME_INTEGER
433 /*%type <integerValue> SIGNED_INTEGER */
434 
435 %{
436 #include <stdio.h>
437 #include <string.h>
438 #include <string>
439 #include <iostream>
440 #include <limits.h>
441 //! @todo OK?
442 #ifdef Q_OS_WIN
443 //workaround for bug on msvc
444 # undef LLONG_MIN
445 #endif
446 #ifndef LLONG_MAX
447 # define LLONG_MAX     0x7fffffffffffffffLL
448 #endif
449 #ifndef LLONG_MIN
450 # define LLONG_MIN     0x8000000000000000LL
451 #endif
452 #ifndef LLONG_MAX
453 # define ULLONG_MAX    0xffffffffffffffffLL
454 #endif
455 
456 #ifdef _WIN32
457 # include <malloc.h>
458 #endif
459 
460 #include <QObject>
461 #include <QVariant>
462 #include <QPoint>
463 
464 #include "KDbConnection.h"
465 #include "KDbDateTime.h"
466 #include "KDbExpression.h"
467 #include "KDbField.h"
468 #include "KDbOrderByColumn.h"
469 #include "KDbParser.h"
470 #include "KDbParser_p.h"
471 #include "KDbQuerySchema.h"
472 #include "KDbQuerySchema_p.h"
473 #include "KDbSqlTypes.h"
474 #include "KDbTableSchema.h"
475 #include "kdb_debug.h"
476 
477 struct OrderByColumnInternal;
478 
479 #ifdef Q_OS_SOLARIS
480 #include <alloca.h>
481 #endif
482 
483 QDebug operator<<(QDebug dbg, const KDbExpressionPtr& expr)
484 {
485     dbg.nospace() << expr.e;
486     return dbg.space();
487 }
488 
489 int yylex();
490 
491 #define YY_NO_UNPUT
492 #define YYSTACK_USE_ALLOCA 1
493 #define YYMAXDEPTH 255
494 
495     extern "C"
496     {
yywrap()497         int yywrap()
498         {
499             return 1;
500         }
501     }
502 
503 %}
504 
505 %union {
506     QString* stringValue;
507     QByteArray* binaryValue;
508     qint64 integerValue;
509     bool booleanValue;
510     KDbDate* dateValue;
511     KDbYear* yearValue;
512     KDbTime* timeValue;
513     KDbTime::Period timePeriodValue;
514     KDbDateTime* dateTimeValue;
515     KDbOrderByColumn::SortOrder sortOrderValue;
516     KDbField::Type colType;
517     KDbField *field;
518     KDbExpression *expr;
519     KDbNArgExpression *exprList;
520     KDbConstExpression *constExpression;
521     KDbQuerySchema *querySchema;
522     SelectOptionsInternal *selectOptions;
523     QList<OrderByColumnInternal> *orderByColumns;
524     QVariant *variantValue;
525 }
526 
527 /* precedence: lowest to highest */
528 //%nonassoc    SIMILAR
529 //%nonassoc    ESCAPE
530 //%nonassoc    OVERLAPS
531 //%nonassoc    IN_P
532 //%left        POSTFIXOP        // dummy for postfix Op rules
533 //%left        Op OPERATOR        // multi-character ops and user-defined operators
534 //%nonassoc    NOTNULL
535 //%nonassoc    ISNULL
536 //%nonassoc    IS               // sets precedence for IS NULL, etc
537 //%nonassoc    NULL_P
538 //%nonassoc    TRUE_P
539 //%nonassoc    FALSE_P
540 
541 // <-- To keep binary compatibility insert new tokens here.
542 
543 /*
544  * These might seem to be low-precedence, but actually they are not part
545  * of the arithmetic hierarchy at all in their use as JOIN operators.
546  * We make them high-precedence to support their use as function names.
547  * They wouldn't be given a precedence at all, were it not that we need
548  * left-associativity among the JOIN rules themselves.
549  */
550 /*
551 %left JOIN
552 %left UNIONJOIN
553 %left CROSS
554 %left LEFT
555 %left FULL
556 %left RIGHT
557 %left INNER_P
558 %left NATURAL
559 */
560 
561 %%
562 
563 TopLevelStatement :
564 StatementList
565 {
566 //todo: multiple statements
567 //todo: not only "select" statements
568     KDbParserPrivate::get(globalParser)->setStatementType(KDbParser::Select);
569     KDbParserPrivate::get(globalParser)->setQuerySchema($1);
570 }
571 ;
572 
573 StatementList:
574 Statement ';' StatementList
575 {
576 //todo: multiple statements
577 }
578 | Statement
579 | Statement ';'
580 {
581     $$ = $1;
582 }
583 ;
584 
585 /*        Statement CreateTableStatement         { YYACCEPT; }
586     | Statement SelectStatement         {  }
587 */
588 Statement :
589 /*CreateTableStatement
590 {
591 YYACCEPT;
592 }
593 | */
594 SelectStatement
595 {
596     $$ = $1;
597 }
598 ;
599 
600 /*CreateTableStatement :
601 CREATE TABLE IDENTIFIER
602 {
603     globalParser->setStatementType(KDbParser::CreateTable);
604     globalParser->createTable($3->toLatin1());
605     delete $3;
606 }
607 '(' ColDefs ')'
608 ;
609 
610 ColDefs:
611 ColDefs ',' ColDef|ColDef
612 {
613 }
614 ;
615 
616 ColDef:
617 IDENTIFIER ColType
618 {
619     sqlParserDebug() << "adding field " << *$1;
620     globalField->setName(*$1);
621     globalParser->table()->addField(globalField);
622     globalField = nullptr;
623     delete $1;
624 }
625 | IDENTIFIER ColType ColKeys
626 {
627     sqlParserDebug() << "adding field " << *$1;
628     globalField->setName(*$1);
629     delete $1;
630     globalParser->table()->addField(globalField);
631 
632 //    if(globalField->isPrimaryKey())
633 //        globalParser->table()->addPrimaryKey(globalField->name());
634 
635 //    delete globalField;
636 //    globalField = nullptr;
637 }
638 ;
639 
640 ColKeys:
641 ColKeys ColKey|ColKey
642 {
643 }
644 ;
645 
646 ColKey:
647 PRIMARY KEY
648 {
649     globalField->setPrimaryKey(true);
650     sqlParserDebug() << "primary";
651 }
652 | NOT SQL_NULL
653 {
654     globalField->setNotNull(true);
655     sqlParserDebug() << "not_null";
656 }
657 | AUTO_INCREMENT
658 {
659     globalField->setAutoIncrement(true);
660     sqlParserDebug() << "ainc";
661 }
662 ;
663 
664 ColType:
665 SQL_TYPE
666 {
667     globalField = new KDbField();
668     globalField->setType($1);
669 }
670 | SQL_TYPE '(' INTEGER_CONST ')'
671 {
672     sqlParserDebug() << "sql + length";
673     globalField = new KDbField();
674     globalField->setPrecision($3);
675     globalField->setType($1);
676 }
677 | VARCHAR '(' INTEGER_CONST ')'
678 {
679     globalField = new KDbField();
680     globalField->setPrecision($3);
681     globalField->setType(KDbField::Text);
682 }
683 |
684 %empty
685 {
686     // SQLITE compatibillity
687     globalField = new KDbField();
688     globalField->setType(KDbField::InvalidType);
689 }
690 ;*/
691 
692 SelectStatement:
693 Select
694 {
695     sqlParserDebug() << "Select";
696     if (!($$ = buildSelectQuery( $1, nullptr )))
697         YYABORT;
698 }
699 | Select ColViews
700 {
701     sqlParserDebug() << "Select ColViews=" << *$2;
702 
703     if (!($$ = buildSelectQuery( $1, $2 )))
704         YYABORT;
705 }
706 | Select ColViews Tables
707 {
708     if (!($$ = buildSelectQuery( $1, $2, $3 )))
709         YYABORT;
710 }
711 | Select Tables
712 {
713     sqlParserDebug() << "Select ColViews Tables";
714     if (!($$ = buildSelectQuery( $1, nullptr, $2 )))
715         YYABORT;
716 }
717 | Select ColViews SelectOptions
718 {
719     sqlParserDebug() << "Select ColViews Conditions";
720     if (!($$ = buildSelectQuery( $1, $2, nullptr, $3 )))
721         YYABORT;
722 }
723 | Select Tables SelectOptions
724 {
725     sqlParserDebug() << "Select Tables SelectOptions";
726     if (!($$ = buildSelectQuery( $1, nullptr, $2, $3 )))
727         YYABORT;
728 }
729 | Select ColViews Tables SelectOptions
730 {
731     sqlParserDebug() << "Select ColViews Tables SelectOptions";
732     if (!($$ = buildSelectQuery( $1, $2, $3, $4 )))
733         YYABORT;
734 }
735 ;
736 
737 Select:
738 SELECT
739 {
740     sqlParserDebug() << "SELECT";
741     $$ = KDbParserPrivate::get(globalParser)->createQuery();
742 }
743 ;
744 
745 SelectOptions: /* todo: more options (having, group by, limit...) */
746 WhereClause
747 {
748     sqlParserDebug() << "WhereClause";
749     $$ = new SelectOptionsInternal;
750     $$->whereExpr = *$1;
751     delete $1;
752 }
753 | ORDER BY OrderByClause
754 {
755     sqlParserDebug() << "OrderByClause";
756     $$ = new SelectOptionsInternal;
757     $$->orderByColumns = $3;
758 }
759 | WhereClause ORDER BY OrderByClause
760 {
761     sqlParserDebug() << "WhereClause ORDER BY OrderByClause";
762     $$ = new SelectOptionsInternal;
763     $$->whereExpr = *$1;
764     delete $1;
765     $$->orderByColumns = $4;
766 }
767 | ORDER BY OrderByClause WhereClause
768 {
769     sqlParserDebug() << "OrderByClause WhereClause";
770     $$ = new SelectOptionsInternal;
771     $$->whereExpr = *$4;
772     delete $4;
773     $$->orderByColumns = $3;
774 }
775 ;
776 
777 WhereClause:
778 WHERE aExpr
779 {
780     $$ = $2;
781 }
782 ;
783 
784 /* todo: support "ORDER BY NULL" as described here https://dev.mysql.com/doc/refman/5.1/en/select.html */
785 /* todo: accept expr and position as well */
786 OrderByClause:
787 OrderByColumnId
788 {
789     sqlParserDebug() << "ORDER BY IDENTIFIER";
790     $$ = new QList<OrderByColumnInternal>;
791     OrderByColumnInternal orderByColumn;
792     orderByColumn.setColumnByNameOrNumber( *$1 );
793     $$->append( orderByColumn );
794     delete $1;
795 }
796 | OrderByColumnId OrderByOption
797 {
798     sqlParserDebug() << "ORDER BY IDENTIFIER OrderByOption";
799     $$ = new QList<OrderByColumnInternal>;
800     OrderByColumnInternal orderByColumn;
801     orderByColumn.setColumnByNameOrNumber( *$1 );
802     orderByColumn.order = $2;
803     $$->append( orderByColumn );
804     delete $1;
805 }
806 | OrderByColumnId ',' OrderByClause
807 {
808     $$ = $3;
809     OrderByColumnInternal orderByColumn;
810     orderByColumn.setColumnByNameOrNumber( *$1 );
811     $$->append( orderByColumn );
812     delete $1;
813 }
814 | OrderByColumnId OrderByOption ',' OrderByClause
815 {
816     $$ = $4;
817     OrderByColumnInternal orderByColumn;
818     orderByColumn.setColumnByNameOrNumber( *$1 );
819     orderByColumn.order = $2;
820     $$->append( orderByColumn );
821     delete $1;
822 }
823 ;
824 
825 OrderByColumnId:
826 IDENTIFIER
827 {
828     $$ = new QVariant( *$1 );
829     sqlParserDebug() << "OrderByColumnId: " << *$$;
830     delete $1;
831 }
832 | IDENTIFIER '.' IDENTIFIER
833 {
834     $$ = new QVariant( *$1 + QLatin1Char('.') + *$3 );
835     sqlParserDebug() << "OrderByColumnId: " << *$$;
836     delete $1;
837     delete $3;
838 }
839 | INTEGER_CONST
840 {
841     $$ = new QVariant($1);
842     sqlParserDebug() << "OrderByColumnId: " << *$$;
843 }
844 
845 OrderByOption:
846 ASC
847 {
848     $$ = KDbOrderByColumn::SortOrder::Ascending;
849 }
850 | DESC
851 {
852     $$ = KDbOrderByColumn::SortOrder::Descending;
853 }
854 ;
855 
856 aExpr:
857 aExpr2
858 ;
859 
860 /* --- binary logical --- */
861 aExpr2:
862 aExpr3 AND aExpr2
863 {
864 //    sqlParserDebug() << "AND " << $3.debugString();
865     $$ = new KDbBinaryExpression(*$1, KDbToken::AND, *$3);
866     delete $1;
867     delete $3;
868 }
869 | aExpr3 OR aExpr2
870 {
871     $$ = new KDbBinaryExpression(*$1, KDbToken::OR, *$3);
872     delete $1;
873     delete $3;
874 }
875 | aExpr3 XOR aExpr2
876 {
877     $$ = new KDbBinaryExpression(*$1, KDbToken::XOR, *$3);
878     delete $1;
879     delete $3;
880 }
881 |
882 aExpr3
883 ;
884 
885 /* relational op precedence */
886 aExpr3:
887 aExpr4 '>' %prec GREATER_OR_EQUAL aExpr3
888 {
889     $$ = new KDbBinaryExpression(*$1, '>', *$3);
890     delete $1;
891     delete $3;
892 }
893 | aExpr4 GREATER_OR_EQUAL aExpr3
894 {
895     $$ = new KDbBinaryExpression(*$1, KDbToken::GREATER_OR_EQUAL, *$3);
896     delete $1;
897     delete $3;
898 }
899 | aExpr4 '<' %prec LESS_OR_EQUAL aExpr3
900 {
901     $$ = new KDbBinaryExpression(*$1, '<', *$3);
902     delete $1;
903     delete $3;
904 }
905 | aExpr4 LESS_OR_EQUAL aExpr3
906 {
907     $$ = new KDbBinaryExpression(*$1, KDbToken::LESS_OR_EQUAL, *$3);
908     delete $1;
909     delete $3;
910 }
911 | aExpr4 '=' aExpr3
912 {
913     $$ = new KDbBinaryExpression(*$1, '=', *$3);
914     delete $1;
915     delete $3;
916 }
917 |
918 aExpr4
919 ;
920 
921 /* relational (equality) op precedence */
922 aExpr4:
923 aExpr5 NOT_EQUAL aExpr4
924 {
925     $$ = new KDbBinaryExpression(*$1, KDbToken::NOT_EQUAL, *$3);
926     delete $1;
927     delete $3;
928 }
929 | aExpr5 NOT_EQUAL2 aExpr4
930 {
931     $$ = new KDbBinaryExpression(*$1, KDbToken::NOT_EQUAL2, *$3);
932     delete $1;
933     delete $3;
934 }
935 | aExpr5 LIKE aExpr4
936 {
937     $$ = new KDbBinaryExpression(*$1, KDbToken::LIKE, *$3);
938     delete $1;
939     delete $3;
940 }
941 | aExpr5 NOT_LIKE aExpr4
942 {
943     $$ = new KDbBinaryExpression(*$1, KDbToken::NOT_LIKE, *$3);
944     delete $1;
945     delete $3;
946 }
947 | aExpr5 SQL_IN aExpr4
948 {
949     $$ = new KDbBinaryExpression(*$1, KDbToken::SQL_IN, *$3);
950     delete $1;
951     delete $3;
952 }
953 | aExpr5 SIMILAR_TO aExpr4
954 {
955     $$ = new KDbBinaryExpression(*$1, KDbToken::SIMILAR_TO, *$3);
956     delete $1;
957     delete $3;
958 }
959 | aExpr5 NOT_SIMILAR_TO aExpr4
960 {
961     $$ = new KDbBinaryExpression(*$1, KDbToken::NOT_SIMILAR_TO, *$3);
962     delete $1;
963     delete $3;
964 }
965 | aExpr5 BETWEEN aExpr4 AND aExpr4
966 {
967     $$ = new KDbNArgExpression(KDb::RelationalExpression, KDbToken::BETWEEN_AND);
968     $$->toNArg().append( *$1 );
969     $$->toNArg().append( *$3 );
970     $$->toNArg().append( *$5 );
971     delete $1;
972     delete $3;
973     delete $5;
974 }
975 | aExpr5 NOT_BETWEEN aExpr4 AND aExpr4
976 {
977     $$ = new KDbNArgExpression(KDb::RelationalExpression, KDbToken::NOT_BETWEEN_AND);
978     $$->toNArg().append( *$1 );
979     $$->toNArg().append( *$3 );
980     $$->toNArg().append( *$5 );
981     delete $1;
982     delete $3;
983     delete $5;
984 }
985 |
986 aExpr5
987 ;
988 
989 /* --- unary logical right --- */
990 aExpr5:
991 aExpr5 SQL_IS_NULL
992 {
993     $$ = new KDbUnaryExpression( KDbToken::SQL_IS_NULL, *$1 );
994     delete $1;
995 }
996 | aExpr5 SQL_IS_NOT_NULL
997 {
998     $$ = new KDbUnaryExpression( KDbToken::SQL_IS_NOT_NULL, *$1 );
999     delete $1;
1000 }
1001 |
1002 aExpr6
1003 ;
1004 
1005 /* arithm. lowest precedence */
1006 aExpr6:
1007 aExpr7 BITWISE_SHIFT_LEFT aExpr6
1008 {
1009     $$ = new KDbBinaryExpression(*$1, KDbToken::BITWISE_SHIFT_LEFT, *$3);
1010     delete $1;
1011     delete $3;
1012 }
1013 | aExpr7 BITWISE_SHIFT_RIGHT aExpr6
1014 {
1015     $$ = new KDbBinaryExpression(*$1, KDbToken::BITWISE_SHIFT_RIGHT, *$3);
1016     delete $1;
1017     delete $3;
1018 }
1019 |
1020 aExpr7
1021 ;
1022 
1023 /* arithm. lower precedence */
1024 aExpr7:
1025 aExpr8 '+' aExpr7
1026 {
1027     $$ = new KDbBinaryExpression(*$1, '+', *$3);
1028     delete $1;
1029     delete $3;
1030 }
1031 | aExpr8 CONCATENATION aExpr7
1032 {
1033     $$ = new KDbBinaryExpression(*$1, KDbToken::CONCATENATION, *$3);
1034     delete $1;
1035     delete $3;
1036 }
1037 | aExpr8 '-' %prec UMINUS aExpr7
1038 {
1039     $$ = new KDbBinaryExpression(*$1, '-', *$3);
1040     delete $1;
1041     delete $3;
1042 }
1043 | aExpr8 '&' aExpr7
1044 {
1045     $$ = new KDbBinaryExpression(*$1, '&', *$3);
1046     delete $1;
1047     delete $3;
1048 }
1049 | aExpr8 '|' aExpr7
1050 {
1051     $$ = new KDbBinaryExpression(*$1, '|', *$3);
1052     delete $1;
1053     delete $3;
1054 }
1055 |
1056 aExpr8
1057 ;
1058 
1059 /* arithm. higher precedence */
1060 aExpr8:
1061 aExpr9 '/' aExpr8
1062 {
1063     $$ = new KDbBinaryExpression(*$1, '/', *$3);
1064     delete $1;
1065     delete $3;
1066 }
1067 | aExpr9 '*' aExpr8
1068 {
1069     $$ = new KDbBinaryExpression(*$1, '*', *$3);
1070     delete $1;
1071     delete $3;
1072 }
1073 | aExpr9 '%' aExpr8
1074 {
1075     $$ = new KDbBinaryExpression(*$1, '%', *$3);
1076     delete $1;
1077     delete $3;
1078 }
1079 |
1080 aExpr9
1081 ;
1082 
1083 /* parenthesis, unary operators, and terminals precedence */
1084 aExpr9:
1085 /* --- unary logical left --- */
1086 '-' aExpr9
1087 {
1088     $$ = new KDbUnaryExpression( '-', *$2 );
1089     delete $2;
1090 }
1091 | '+' aExpr9
1092 {
1093     $$ = new KDbUnaryExpression( '+', *$2 );
1094     delete $2;
1095 }
1096 | '~' aExpr9
1097 {
1098     $$ = new KDbUnaryExpression( '~', *$2 );
1099     delete $2;
1100 }
1101 | NOT aExpr9
1102 {
1103     $$ = new KDbUnaryExpression( KDbToken::NOT, *$2 );
1104     delete $2;
1105 }
1106 | IDENTIFIER
1107 {
1108     $$ = new KDbVariableExpression( *$1 );
1109 
1110     //! @todo simplify this later if that's 'only one field name' expression
1111     sqlParserDebug() << "  + identifier: " << *$1;
1112     delete $1;
1113 }
1114 | QUERY_PARAMETER
1115 {
1116     $$ = new KDbQueryParameterExpression( *$1 );
1117     sqlParserDebug() << "  + query parameter:" << *$$;
1118     delete $1;
1119 }
1120 | IDENTIFIER aExprList
1121 {
1122     sqlParserDebug() << "  + function:" << *$1 << "(" << *$2 << ")";
1123     $$ = new KDbFunctionExpression(*$1, *$2);
1124     delete $1;
1125     delete $2;
1126 }
1127 /*! @todo shall we also support db name? */
1128 | IDENTIFIER '.' IDENTIFIER
1129 {
1130     $$ = new KDbVariableExpression( *$1 + QLatin1Char('.') + *$3 );
1131     sqlParserDebug() << "  + identifier.identifier:" << *$1 << "." << *$3;
1132     delete $1;
1133     delete $3;
1134 }
1135 | SQL_NULL
1136 {
1137     $$ = new KDbConstExpression( KDbToken::SQL_NULL, QVariant() );
1138     sqlParserDebug() << "  + NULL";
1139 //    $$ = new KDbField();
1140     //$$->setName(QString::null);
1141 }
1142 | SQL_TRUE
1143 {
1144     $$ = new KDbConstExpression( KDbToken::SQL_TRUE, true );
1145 }
1146 | SQL_FALSE
1147 {
1148     $$ = new KDbConstExpression( KDbToken::SQL_FALSE, false );
1149 }
1150 | CHARACTER_STRING_LITERAL
1151 {
1152     $$ = new KDbConstExpression( KDbToken::CHARACTER_STRING_LITERAL, *$1 );
1153     sqlParserDebug() << "  + constant " << $1;
1154     delete $1;
1155 }
1156 | INTEGER_CONST
1157 {
1158     QVariant val;
1159     if ($1 <= INT_MAX && $1 >= INT_MIN)
1160         val = (int)$1;
1161     else if ($1 <= UINT_MAX && $1 >= 0)
1162         val = (uint)$1;
1163     else if ($1 <= LLONG_MAX && $1 >= LLONG_MIN)
1164         val = (qint64)$1;
1165 
1166 //    if ($1 < ULLONG_MAX)
1167 //        val = (quint64)$1;
1168 //! @todo ok?
1169 
1170     $$ = new KDbConstExpression( KDbToken::INTEGER_CONST, val );
1171     sqlParserDebug() << "  + int constant: " << val.toString();
1172 }
1173 | REAL_CONST
1174 {
1175     $$ = new KDbConstExpression( KDbToken::REAL_CONST, *$1 );
1176     sqlParserDebug() << "  + real constant: " << *$1;
1177     delete $1;
1178 }
1179 | DateConst
1180 {
1181     $$ = new KDbConstExpression(KDbToken::DATE_CONST, QVariant::fromValue(*$1));
1182     sqlParserDebug() << "  + date constant:" << *$1;
1183     delete $1;
1184 }
1185 | TimeConst
1186 {
1187     $$ = new KDbConstExpression(KDbToken::TIME_CONST, QVariant::fromValue(*$1));
1188     sqlParserDebug() << "  + time constant:" << *$1;
1189     delete $1;
1190 }
1191 | DateTimeConst
1192 {
1193     $$ = new KDbConstExpression(KDbToken::DATETIME_CONST, QVariant::fromValue(*$1));
1194     sqlParserDebug() << "  + datetime constant:" << *$1;
1195     delete $1;
1196 }
1197 |
1198 aExpr10
1199 ;
1200 
1201 DateConst:
1202 '#' DateValue '#'
1203 {
1204     $$ = $2;
1205     sqlParserDebug() << "DateConst:" << *$$;
1206 }
1207 ;
1208 
1209 DateValue:
1210 YearConst '-' DATE_TIME_INTEGER '-' DATE_TIME_INTEGER
1211 {
1212     $$ = new KDbDate(*$1, *$3, *$5);
1213     sqlParserDebug() << "DateValue:" << *$$;
1214     delete $1;
1215     delete $3;
1216     delete $5;
1217 }
1218 | DATE_TIME_INTEGER '/' DATE_TIME_INTEGER '/' YearConst /* M/D/Y */
1219 {
1220     $$ = new KDbDate(*$5, *$1, *$3);
1221     sqlParserDebug() << "DateValue:" << *$$;
1222     delete $1;
1223     delete $3;
1224     delete $5;
1225 }
1226 ;
1227 
1228 YearConst:
1229 DATE_TIME_INTEGER
1230 {
1231     $$ = new KDbYear(KDbYear::Sign::None, *$1);
1232     sqlParserDebug() << "YearConst:" << *$$;
1233     delete $1;
1234 }
1235 | '+' DATE_TIME_INTEGER
1236 {
1237     $$ = new KDbYear(KDbYear::Sign::Plus, *$2);
1238     sqlParserDebug() << "YearConst:" << *$$;
1239     delete $2;
1240 }
1241 | '-' DATE_TIME_INTEGER
1242 {
1243     $$ = new KDbYear(KDbYear::Sign::Minus, *$2);
1244     sqlParserDebug() << "YearConst:" << *$$;
1245     delete $2;
1246 }
1247 ;
1248 
1249 TimeConst:
1250 '#' TimeValue '#'
1251 {
1252     $$ = $2;
1253     sqlParserDebug() << "TimeConst:" << *$$;
1254 }
1255 ;
1256 
1257 TimeValue:
1258 DATE_TIME_INTEGER ':' DATE_TIME_INTEGER TimeMs TimePeriod
1259 {
1260     $$ = new KDbTime(*$1, *$3, {}, *$4, $5);
1261     sqlParserDebug() << "TimeValue:" << *$$;
1262     delete $1;
1263     delete $3;
1264     delete $4;
1265 }
1266 | DATE_TIME_INTEGER ':' DATE_TIME_INTEGER ':' DATE_TIME_INTEGER TimeMs TimePeriod
1267 {
1268     $$ = new KDbTime(*$1, *$3, *$5, *$6, $7);
1269     sqlParserDebug() << "TimeValue:" << *$$;
1270     delete $1;
1271     delete $3;
1272     delete $5;
1273     delete $6;
1274 }
1275 ;
1276 
1277 TimeMs:
1278 '.' DATE_TIME_INTEGER
1279 {
1280     $$ = $2;
1281 }
1282 | %empty
1283 {
1284     $$ = new QByteArray;
1285 }
1286 ;
1287 
1288 TimePeriod:
1289 TIME_AM
1290 {
1291     $$ = KDbTime::Period::Am;
1292 }
1293 | TIME_PM
1294 {
1295     $$ = KDbTime::Period::Pm;
1296 }
1297 | %empty
1298 {
1299     $$ = KDbTime::Period::None;
1300 }
1301 ;
1302 
1303 DateTimeConst:
1304 '#' DateValue TABS_OR_SPACES TimeValue '#'
1305 {
1306     $$ = new KDbDateTime(*$2, *$4);
1307     sqlParserDebug() << "DateTimeConst:" << *$$;
1308     delete $2;
1309     delete $4;
1310 }
1311 ;
1312 
1313 aExpr10:
1314 '(' aExpr ')'
1315 {
1316     sqlParserDebug() << "(expr)";
1317     $$ = new KDbUnaryExpression('(', *$2);
1318     delete $2;
1319 }
1320 ;
1321 
1322 aExprList:
1323 '(' aExprList2 ')'
1324 {
1325     $$ = $2;
1326 }
1327 | '(' ')'
1328 {
1329     $$ = new KDbNArgExpression(KDb::ArgumentListExpression, ',');
1330 }
1331 ;
1332 
1333 aExprList2:
1334 aExpr ',' aExprList2
1335 {
1336     $$ = $3;
1337     $$->prepend( *$1 );
1338     delete $1;
1339 }
1340 | aExpr
1341 {
1342     $$ = new KDbNArgExpression(KDb::ArgumentListExpression, ',');
1343     $$->append( *$1 );
1344     delete $1;
1345 }
1346 ;
1347 
1348 Tables:
1349 FROM FlatTableList
1350 {
1351     $$ = $2;
1352 }
1353 /*
1354 | Tables LEFT JOIN IDENTIFIER SQL_ON ColExpression
1355 {
1356     sqlParserDebug() << "LEFT JOIN: '" << *$4 << "' ON " << $6;
1357     addTable($4->toQString());
1358     delete $4;
1359 }
1360 | Tables LEFT OUTER JOIN IDENTIFIER SQL_ON ColExpression
1361 {
1362     sqlParserDebug() << "LEFT OUTER JOIN: '" << $5 << "' ON " << $7;
1363     addTable($5);
1364 }
1365 | Tables INNER JOIN IDENTIFIER SQL_ON ColExpression
1366 {
1367     sqlParserDebug() << "INNER JOIN: '" << *$4 << "' ON " << $6;
1368     addTable($4->toQString());
1369     delete $4;
1370 }
1371 | Tables RIGHT JOIN IDENTIFIER SQL_ON ColExpression
1372 {
1373     sqlParserDebug() << "RIGHT JOIN: '" << *$4 << "' ON " << $6;
1374     addTable(*$4);
1375     delete $4;
1376 }
1377 | Tables RIGHT OUTER JOIN IDENTIFIER SQL_ON ColExpression
1378 {
1379     sqlParserDebug() << "RIGHT OUTER JOIN: '" << *$5 << "' ON " << $7;
1380     addTable($5->toQString());
1381     delete $5;
1382 }*/
1383 ;
1384 
1385 /*
1386 FlatTableList:
1387 aFlatTableList
1388 {
1389     $$
1390 }
1391 ;*/
1392 
1393 FlatTableList:
1394 FlatTableList ',' FlatTable
1395 {
1396     $$ = $1;
1397     $$->append(*$3);
1398     delete $3;
1399 }
1400 |FlatTable
1401 {
1402     $$ = new KDbNArgExpression(KDb::TableListExpression, KDbToken::IDENTIFIER); //ok?
1403     $$->append(*$1);
1404     delete $1;
1405 }
1406 ;
1407 
1408 FlatTable:
1409 IDENTIFIER
1410 {
1411     sqlParserDebug() << "FROM: '" << *$1 << "'";
1412     $$ = new KDbVariableExpression(*$1);
1413 
1414     //! @todo this isn't ok for more tables:
1415     /*
1416     KDbField::ListIterator it = globalParser->query()->fieldsIterator();
1417     for(KDbField *item; (item = it.current()); ++it)
1418     {
1419         if(item->table() == dummy)
1420         {
1421             item->setTable(schema);
1422         }
1423 
1424         if(item->table() && !item->isQueryAsterisk())
1425         {
1426             KDbField *f = item->table()->field(item->name());
1427             if(!f)
1428             {
1429                 KDbParserError err(KDbParser::tr("Field List Error"), KDbParser::tr("Unknown column '%1' in table '%2'",item->name(),schema->name()), ctoken, current);
1430                 globalParser->setError(err);
1431                 yyerror("fieldlisterror");
1432             }
1433         }
1434     }*/
1435     delete $1;
1436 }
1437 | IDENTIFIER IDENTIFIER
1438 {
1439     //table + alias
1440     $$ = new KDbBinaryExpression(
1441         KDbVariableExpression(*$1), KDbToken::AS_EMPTY,
1442         KDbVariableExpression(*$2)
1443     );
1444     delete $1;
1445     delete $2;
1446 }
1447 | IDENTIFIER AS IDENTIFIER
1448 {
1449     //table + alias
1450     $$ = new KDbBinaryExpression(
1451         KDbVariableExpression(*$1), KDbToken::AS,
1452         KDbVariableExpression(*$3)
1453     );
1454     delete $1;
1455     delete $3;
1456 }
1457 ;
1458 
1459 
1460 
1461 ColViews:
1462 ColViews ',' ColItem
1463 {
1464     $$ = $1;
1465     $$->append(*$3);
1466     delete $3;
1467     sqlParserDebug() << "ColViews: ColViews , ColItem";
1468 }
1469 |ColItem
1470 {
1471     $$ = new KDbNArgExpression(KDb::FieldListExpression, KDbToken());
1472     $$->append(*$1);
1473     delete $1;
1474     sqlParserDebug() << "ColViews: ColItem";
1475 }
1476 ;
1477 
1478 ColItem:
1479 ColExpression
1480 {
1481 //    $$ = new KDbField();
1482 //    dummy->addField($$);
1483 //    $$->setExpression( $1 );
1484 //    globalParser->query()->addField($$);
1485     $$ = $1;
1486     sqlParserDebug() << " added column expr:" << *$1;
1487 }
1488 | ColWildCard
1489 {
1490     $$ = $1;
1491     sqlParserDebug() << " added column wildcard:" << *$1;
1492 }
1493 | ColExpression AS IDENTIFIER
1494 {
1495     $$ = new KDbBinaryExpression(
1496         *$1, KDbToken::AS,
1497         KDbVariableExpression(*$3)
1498     );
1499     sqlParserDebug() << " added column expr:" << *$$;
1500     delete $1;
1501     delete $3;
1502 }
1503 | ColExpression IDENTIFIER
1504 {
1505     $$ = new KDbBinaryExpression(
1506         *$1, KDbToken::AS_EMPTY,
1507         KDbVariableExpression(*$2)
1508     );
1509     sqlParserDebug() << " added column expr:" << *$$;
1510     delete $1;
1511     delete $2;
1512 }
1513 ;
1514 
1515 ColExpression:
1516 aExpr
1517 {
1518     $$ = $1;
1519 }
1520 /* HANDLED BY 'IDENTIFIER aExprList'
1521 | IDENTIFIER '(' ColViews ')'
1522 {
1523     $$ = new KDbFunctionExpression( $1, $3 );
1524 }*/
1525 //! @todo
1526 /*
1527 | SUM '(' ColExpression ')'
1528 {
1529     KDbFunctionExpression(
1530 //    $$ = new AggregationExpression( SUM,  );
1531 //    $$->setName("SUM(" + $3->name() + ")");
1532 //wait    $$->containsGroupingAggregate(true);
1533 //wait    globalParser->query()->grouped(true);
1534 }*/
1535 //! @todo
1536 /*
1537 | SQL_MIN '(' ColExpression ')'
1538 {
1539     $$ = $3;
1540 //    $$->setName("MIN(" + $3->name() + ")");
1541 //wait    $$->containsGroupingAggregate(true);
1542 //wait    globalParser->query()->grouped(true);
1543 }*/
1544 //! @todo
1545 /*
1546 | SQL_MAX '(' ColExpression ')'
1547 {
1548     $$ = $3;
1549 //    $$->setName("MAX(" + $3->name() + ")");
1550 //wait    $$->containsGroupingAggregate(true);
1551 //wait    globalParser->query()->grouped(true);
1552 }*/
1553 //! @todo
1554 /*
1555 | AVG '(' ColExpression ')'
1556 {
1557     $$ = $3;
1558 //    $$->setName("AVG(" + $3->name() + ")");
1559 //wait    $$->containsGroupingAggregate(true);
1560 //wait    globalParser->query()->grouped(true);
1561 }*/
1562 | DISTINCT '(' ColExpression ')'
1563 {
1564     $$ = $3;
1565 //! @todo DISTINCT '(' ColExpression ')'
1566 //    $$->setName("DISTINCT(" + $3->name() + ")");
1567 }
1568 ;
1569 
1570 ColWildCard:
1571 '*'
1572 {
1573     $$ = new KDbVariableExpression(QLatin1String("*"));
1574     sqlParserDebug() << "all columns";
1575 
1576 //    KDbQueryAsterisk *ast = new KDbQueryAsterisk(globalParser->query(), dummy);
1577 //    globalParser->query()->addAsterisk(ast);
1578 //    requiresTable = true;
1579 }
1580 | IDENTIFIER '.' '*'
1581 {
1582     QString s( *$1 );
1583     s += QLatin1String(".*");
1584     $$ = new KDbVariableExpression(s);
1585     sqlParserDebug() << "  + all columns from " << s;
1586     delete $1;
1587 }
1588 /*| ERROR_DIGIT_BEFORE_IDENTIFIER
1589 {
1590     $$ = new KDbVariableExpression($1);
1591     sqlParserDebug() << "  Invalid identifier! " << $1;
1592     setError(KDbParser::tr("Invalid identifier \"%1\"",$1));
1593 }*/
1594 ;
1595 
1596 %%
1597 
1598