1
/* This file is part of the KDE project
2
Copyright (C) 2004 Lucijan Busch <lucijan@kde.org>
3
Copyright (C) 2004, 2006 Jarosław Staniek <staniek@kde.org>
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.
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.
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.
59
%token BITWISE_SHIFT_LEFT
60
%token BITWISE_SHIFT_RIGHT
72
%token CHARACTER_STRING_LITERAL
83
%token CONCATENATION /* || */
99
%token CURRENT_TIMESTAMP
105
%token DATE_REMAINDER
130
%token DOUBLE_QUOTED_STRING
164
%token GREATER_OR_EQUAL
165
//%token GREATER_THAN
166
//conflict %token GROUP
215
%token MINUTES_BETWEEN
220
%token MONTHS_BETWEEN
229
%token NOT_EQUAL //<>
230
%token NOT_EQUAL2 //!=
234
%token SQL_IS_NULL /*helper */
235
%token SQL_IS_NOT_NULL /*helper */
286
%token SECONDS_BETWEEN
294
%token SIMILAR_TO /* helper */
295
%token NOT_SIMILAR_TO /* helper */
299
%token DATETIME_CONST
318
%token SYSDATE_FORMAT
328
%token TIMEZONE_MINUTE
343
//%token UNSIGNED_INTEGER
349
%token IDENTIFIER_DOT_ASTERISK
350
%token QUERY_PARAMETER
351
//%token ERROR_DIGIT_BEFORE_IDENTIFIER
364
%token WHERE_CURRENT_OF
374
%token __LAST_TOKEN /* sentinel */
391
%type <stringValue> IDENTIFIER
392
%type <stringValue> IDENTIFIER_DOT_ASTERISK
393
%type <stringValue> QUERY_PARAMETER
394
%type <stringValue> CHARACTER_STRING_LITERAL
395
%type <stringValue> DOUBLE_QUOTED_STRING
398
%type <field> ColExpression
399
%type <field> ColView
401
%type <expr> ColExpression
402
%type <expr> ColWildCard
403
//%type <expr> ColView
405
%type <exprList> ColViews
416
%type <exprList> aExprList
417
%type <exprList> aExprList2
418
%type <expr> WhereClause
419
%type <orderByColumns> OrderByClause
420
%type <booleanValue> OrderByOption
421
%type <variantValue> OrderByColumnId
422
%type <selectOptions> SelectOptions
423
%type <expr> FlatTable
424
%type <exprList> Tables
425
%type <exprList> FlatTableList
426
%type <querySchema> SelectStatement
427
%type <querySchema> Select
429
%type <querySchema> StatementList
430
/*todo: not onlu select*/
431
%type <querySchema> Statement
433
%type <colType> SQL_TYPE
434
%type <integerValue> INTEGER_CONST
435
%type <realValue> REAL_CONST
436
/*%type <integerValue> SIGNED_INTEGER */
439
#ifndef YYDEBUG /* compat. */
450
//workaround for bug on msvc
454
# define LLONG_MAX 0x7fffffffffffffffLL
457
# define LLONG_MIN 0x8000000000000000LL
460
# define ULLONG_MAX 0xffffffffffffffffLL
474
#include <kexidb/connection.h>
475
#include <kexidb/queryschema.h>
476
#include <kexidb/field.h>
477
#include <kexidb/tableschema.h>
480
#include "parser_p.h"
481
#include "sqltypes.h"
485
// using namespace std;
486
using namespace KexiDB;
489
#define YYSTACK_USE_ALLOCA 1
490
#define YYMAXDEPTH 255
503
QString parserUserName;
505
KexiDBField::ColumnType coltype;
512
QString* stringValue;
515
struct realType realValue;
516
KexiDB::Field::Type colType;
517
KexiDB::Field *field;
518
KexiDB::BaseExpr *expr;
519
KexiDB::NArgExpr *exprList;
520
KexiDB::ConstExpr *constExpr;
521
KexiDB::QuerySchema *querySchema;
522
SelectOptionsInternal *selectOptions;
523
OrderByColumnInternal::List *orderByColumns;
524
QVariant *variantValue;
527
//%left '=' NOT_EQUAL '>' GREATER_OR_EQUAL '<' LESS_OR_EQUAL LIKE '%' NOT
529
//%left ASTERISK SLASH
531
/* precedence: lowest to highest */
539
//%nonassoc '=' '<' '>' "<=" ">=" "<>" ":=" LIKE ILIKE SIMILAR
540
//%nonassoc '=' LESS_THAN GREATER_THAN LESS_OR_EQUAL GREATER_OR_EQUAL NOT_EQUAL
541
%nonassoc '=' '<' '>'
542
//LESS_THAN GREATER_THAN
543
%nonassoc LESS_OR_EQUAL GREATER_OR_EQUAL
544
%nonassoc NOT_EQUAL NOT_EQUAL2
545
%nonassoc SQL_IN LIKE ILIKE SIMILAR_TO NOT_SIMILAR_TO
546
//%nonassoc LIKE ILIKE SIMILAR
551
//%left POSTFIXOP // dummy for postfix Op rules
552
//%left Op OPERATOR // multi-character ops and user-defined operators
555
//%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN // sets precedence for IS NULL, etc
561
//%left AT ZONE // sets precedence for AT TIME ZONE
569
* These might seem to be low-precedence, but actually they are not part
570
* of the arithmetic hierarchy at all in their use as JOIN operators.
571
* We make them high-precedence to support their use as function names.
572
* They wouldn't be given a precedence at all, were it not that we need
573
* left-associativity among the JOIN rules themselves.
575
/*%left JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
582
//todo: multiple statements
583
//todo: not only "select" statements
584
parser->setOperation(Parser::OP_Select);
585
parser->setQuerySchema($1);
590
Statement ';' StatementList
592
//todo: multiple statements
601
/* Statement CreateTableStatement { YYACCEPT; }
602
| Statement SelectStatement { }
615
CreateTableStatement :
616
CREATE TABLE IDENTIFIER
618
parser->setOperation(Parser::OP_CreateTable);
619
parser->createTable($3->toLatin1());
626
ColDefs ',' ColDef|ColDef
634
KexiDBDbg << "adding field " << *$1;
635
field->setName($1->toLatin1());
636
parser->table()->addField(field);
640
| IDENTIFIER ColType ColKeys
642
KexiDBDbg << "adding field " << *$1;
645
parser->table()->addField(field);
647
// if(field->isPrimaryKey())
648
// parser->table()->addPrimaryKey(field->name());
656
ColKeys ColKey|ColKey
664
field->setPrimaryKey(true);
665
KexiDBDbg << "primary";
669
field->setNotNull(true);
670
KexiDBDbg << "not_null";
674
field->setAutoIncrement(true);
685
| SQL_TYPE '(' INTEGER_CONST ')'
687
KexiDBDbg << "sql + length";
689
field->setPrecision($3);
692
| VARCHAR '(' INTEGER_CONST ')'
695
field->setPrecision($3);
696
field->setType(Field::Text);
700
// SQLITE compatibillity
702
field->setType(Field::InvalidType);
709
KexiDBDbg << "Select ColViews=" << $2->debugString();
711
if (!($$ = buildSelectQuery( $1, $2 )))
714
| Select ColViews Tables
716
if (!($$ = buildSelectQuery( $1, $2, $3 )))
721
KexiDBDbg << "Select ColViews Tables";
722
if (!($$ = buildSelectQuery( $1, 0, $2 )))
725
| Select ColViews SelectOptions
727
KexiDBDbg << "Select ColViews Conditions";
728
if (!($$ = buildSelectQuery( $1, $2, 0, $3 )))
731
| Select ColViews Tables SelectOptions
733
KexiDBDbg << "Select ColViews Tables SelectOptions";
734
if (!($$ = buildSelectQuery( $1, $2, $3, $4 )))
742
KexiDBDbg << "SELECT";
743
// parser->createSelect();
744
// parser->setOperation(Parser::OP_Select);
745
$$ = new QuerySchema();
749
SelectOptions: /* todo: more options (having, group by, limit...) */
752
KexiDBDbg << "WhereClause";
753
$$ = new SelectOptionsInternal;
756
| ORDER BY OrderByClause
758
KexiDBDbg << "OrderByClause";
759
$$ = new SelectOptionsInternal;
760
$$->orderByColumns = $3;
762
| WhereClause ORDER BY OrderByClause
764
KexiDBDbg << "WhereClause ORDER BY OrderByClause";
765
$$ = new SelectOptionsInternal;
767
$$->orderByColumns = $4;
769
| ORDER BY OrderByClause WhereClause
771
KexiDBDbg << "OrderByClause WhereClause";
772
$$ = new SelectOptionsInternal;
774
$$->orderByColumns = $3;
785
/* todo: support "ORDER BY NULL" as described here http://dev.mysql.com/doc/refman/5.1/en/select.html */
786
/* todo: accept expr and position as well */
790
KexiDBDbg << "ORDER BY IDENTIFIER";
791
$$ = new OrderByColumnInternal::List;
792
OrderByColumnInternal orderByColumn;
793
orderByColumn.setColumnByNameOrNumber( *$1 );
794
$$->append( orderByColumn );
797
| OrderByColumnId OrderByOption
799
KexiDBDbg << "ORDER BY IDENTIFIER OrderByOption";
800
$$ = new OrderByColumnInternal::List;
801
OrderByColumnInternal orderByColumn;
802
orderByColumn.setColumnByNameOrNumber( *$1 );
803
orderByColumn.ascending = $2;
804
$$->append( orderByColumn );
807
| OrderByColumnId ',' OrderByClause
810
OrderByColumnInternal orderByColumn;
811
orderByColumn.setColumnByNameOrNumber( *$1 );
812
$$->append( orderByColumn );
815
| OrderByColumnId OrderByOption ',' OrderByClause
818
OrderByColumnInternal orderByColumn;
819
orderByColumn.setColumnByNameOrNumber( *$1 );
820
orderByColumn.ascending = $2;
821
$$->append( orderByColumn );
829
$$ = new QVariant( *$1 );
830
KexiDBDbg << "OrderByColumnId: " << *$$;
833
| IDENTIFIER '.' IDENTIFIER
835
$$ = new QVariant( *$1 + "." + *$3 );
836
KexiDBDbg << "OrderByColumnId: " << *$$;
842
$$ = new QVariant($1);
843
KexiDBDbg << "OrderByColumnId: " << *$$;
861
/* --- binary logical --- */
865
// KexiDBDbg << "AND " << $3.debugString();
866
$$ = new BinaryExpr( KexiDBExpr_Logical, $1, AND, $3 );
870
$$ = new BinaryExpr( KexiDBExpr_Logical, $1, OR, $3 );
874
$$ = new BinaryExpr( KexiDBExpr_Arithm, $1, XOR, $3 );
880
/* relational op precedence */
882
aExpr4 '>' %prec GREATER_OR_EQUAL aExpr3
884
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, '>', $3);
886
| aExpr4 GREATER_OR_EQUAL aExpr3
888
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, GREATER_OR_EQUAL, $3);
890
| aExpr4 '<' %prec LESS_OR_EQUAL aExpr3
892
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, '<', $3);
894
| aExpr4 LESS_OR_EQUAL aExpr3
896
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, LESS_OR_EQUAL, $3);
900
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, '=', $3);
906
/* relational (equality) op precedence */
908
aExpr5 NOT_EQUAL aExpr4
910
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_EQUAL, $3);
913
aExpr5 NOT_EQUAL2 aExpr4
915
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_EQUAL2, $3);
919
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, LIKE, $3);
921
| aExpr5 SQL_IN aExpr4
923
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, SQL_IN, $3);
925
| aExpr5 SIMILAR_TO aExpr4
927
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, SIMILAR_TO, $3);
929
| aExpr5 NOT_SIMILAR_TO aExpr4
931
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_SIMILAR_TO, $3);
937
/* --- unary logical right --- */
941
$$ = new UnaryExpr( SQL_IS_NULL, $1 );
943
| aExpr5 SQL_IS_NOT_NULL
945
$$ = new UnaryExpr( SQL_IS_NOT_NULL, $1 );
951
/* arithm. lowest precedence */
953
aExpr7 BITWISE_SHIFT_LEFT aExpr6
955
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, BITWISE_SHIFT_LEFT, $3);
957
| aExpr7 BITWISE_SHIFT_RIGHT aExpr6
959
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, BITWISE_SHIFT_RIGHT, $3);
965
/* arithm. lower precedence */
969
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '+', $3);
972
| aExpr8 '-' %prec UMINUS aExpr7
974
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '-', $3);
978
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '&', $3);
982
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '|', $3);
988
/* arithm. higher precedence */
992
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '/', $3);
996
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '*', $3);
1000
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '%', $3);
1006
/* parenthesis, unary operators, and terminals precedence */
1008
/* --- unary logical left --- */
1011
$$ = new UnaryExpr( '-', $2 );
1015
$$ = new UnaryExpr( '+', $2 );
1019
$$ = new UnaryExpr( '~', $2 );
1023
$$ = new UnaryExpr( NOT, $2 );
1027
$$ = new VariableExpr( *$1 );
1029
//TODO: simplify this later if that's 'only one field name' expression
1030
KexiDBDbg << " + identifier: " << *$1;
1035
$$ = new QueryParameterExpr( *$1 );
1036
KexiDBDbg << " + query parameter: " << $$->debugString();
1039
| IDENTIFIER aExprList
1041
KexiDBDbg << " + function: " << *$1 << "(" << $2->debugString() << ")";
1042
$$ = new FunctionExpr(*$1, $2);
1045
/*TODO: shall we also support db name? */
1046
| IDENTIFIER '.' IDENTIFIER
1048
$$ = new VariableExpr( *$1 + "." + *$3 );
1049
KexiDBDbg << " + identifier.identifier: " << *$1 << "." << *$3;
1055
$$ = new ConstExpr( SQL_NULL, QVariant() );
1056
KexiDBDbg << " + NULL";
1057
// $$ = new Field();
1058
//$$->setName(QString::null);
1060
| CHARACTER_STRING_LITERAL
1062
$$ = new ConstExpr( CHARACTER_STRING_LITERAL, *$1 );
1063
KexiDBDbg << " + constant " << $1;
1069
if ($1 <= INT_MAX && $1 >= INT_MIN)
1071
else if ($1 <= UINT_MAX && $1 >= 0)
1073
else if ($1 <= LLONG_MAX && $1 >= LLONG_MIN)
1076
// if ($1 < ULLONG_MAX)
1077
// val = (quint64)$1;
1080
$$ = new ConstExpr( INTEGER_CONST, val );
1081
KexiDBDbg << " + int constant: " << val.toString();
1085
$$ = new ConstExpr( REAL_CONST, QPoint( $1.integer, $1.fractional ) );
1086
KexiDBDbg << " + real constant: " << $1.integer << "." << $1.fractional;
1096
KexiDBDbg << "(expr)";
1097
$$ = new UnaryExpr('(', $2);
1104
// $$ = new NArgExpr(0, 0);
1112
aExpr ',' aExprList2
1119
$$ = new NArgExpr(0, 0);
1131
| Tables LEFT JOIN IDENTIFIER SQL_ON ColExpression
1133
KexiDBDbg << "LEFT JOIN: '" << *$4 << "' ON " << $6;
1134
addTable($4->toQString());
1137
| Tables LEFT OUTER JOIN IDENTIFIER SQL_ON ColExpression
1139
KexiDBDbg << "LEFT OUTER JOIN: '" << $5 << "' ON " << $7;
1142
| Tables INNER JOIN IDENTIFIER SQL_ON ColExpression
1144
KexiDBDbg << "INNER JOIN: '" << *$4 << "' ON " << $6;
1145
addTable($4->toQString());
1148
| Tables RIGHT JOIN IDENTIFIER SQL_ON ColExpression
1150
KexiDBDbg << "RIGHT JOIN: '" << *$4 << "' ON " << $6;
1154
| Tables RIGHT OUTER JOIN IDENTIFIER SQL_ON ColExpression
1156
KexiDBDbg << "RIGHT OUTER JOIN: '" << *$5 << "' ON " << $7;
1157
addTable($5->toQString());
1171
FlatTableList ',' FlatTable
1178
$$ = new NArgExpr(KexiDBExpr_TableList, IDENTIFIER); //ok?
1186
KexiDBDbg << "FROM: '" << *$1 << "'";
1187
$$ = new VariableExpr(*$1);
1190
//TODO: this isn't ok for more tables:
1191
Field::ListIterator it = parser->select()->fieldsIterator();
1192
for(Field *item; (item = it.current()); ++it)
1194
if(item->table() == dummy)
1196
item->setTable(schema);
1199
if(item->table() && !item->isQueryAsterisk())
1201
Field *f = item->table()->field(item->name());
1204
ParserError err(i18n("Field List Error"), i18n("Unknown column '%1' in table '%2'",item->name(),schema->name()), ctoken, current);
1205
parser->setError(err);
1206
yyerror("fieldlisterror");
1212
| IDENTIFIER IDENTIFIER
1215
$$ = new BinaryExpr(
1216
KexiDBExpr_SpecialBinary,
1217
new VariableExpr(*$1), 0,
1218
new VariableExpr(*$2)
1223
| IDENTIFIER AS IDENTIFIER
1226
$$ = new BinaryExpr(
1227
KexiDBExpr_SpecialBinary,
1228
new VariableExpr(*$1), AS,
1229
new VariableExpr(*$3)
1239
ColViews ',' ColItem
1243
KexiDBDbg << "ColViews: ColViews , ColItem";
1247
$$ = new NArgExpr(0,0);
1249
KexiDBDbg << "ColViews: ColItem";
1256
// $$ = new Field();
1257
// dummy->addField($$);
1258
// $$->setExpression( $1 );
1259
// parser->select()->addField($$);
1261
KexiDBDbg << " added column expr: '" << $1->debugString() << "'";
1266
KexiDBDbg << " added column wildcard: '" << $1->debugString() << "'";
1268
| ColExpression AS IDENTIFIER
1270
$$ = new BinaryExpr(
1271
KexiDBExpr_SpecialBinary, $1, AS,
1272
new VariableExpr(*$3)
1274
KexiDBDbg << " added column expr: " << $$->debugString();
1277
| ColExpression IDENTIFIER
1279
$$ = new BinaryExpr(
1280
KexiDBExpr_SpecialBinary, $1, 0,
1281
new VariableExpr(*$2)
1283
KexiDBDbg << " added column expr: " << $$->debugString();
1293
/* HANDLED BY 'IDENTIFIER aExprList'
1294
| IDENTIFIER '(' ColViews ')'
1296
$$ = new FunctionExpr( $1, $3 );
1299
| SUM '(' ColExpression ')'
1302
// $$ = new AggregationExpr( SUM, );
1304
// $$->setName("SUM(" + $3->name() + ")");
1305
//wait $$->containsGroupingAggregate(true);
1306
//wait parser->select()->grouped(true);
1308
| SQL_MIN '(' ColExpression ')'
1312
// $$->setName("MIN(" + $3->name() + ")");
1313
//wait $$->containsGroupingAggregate(true);
1314
//wait parser->select()->grouped(true);
1316
| SQL_MAX '(' ColExpression ')'
1320
// $$->setName("MAX(" + $3->name() + ")");
1321
//wait $$->containsGroupingAggregate(true);
1322
//wait parser->select()->grouped(true);
1324
| AVG '(' ColExpression ')'
1328
// $$->setName("AVG(" + $3->name() + ")");
1329
//wait $$->containsGroupingAggregate(true);
1330
//wait parser->select()->grouped(true);
1333
| DISTINCT '(' ColExpression ')'
1337
// $$->setName("DISTINCT(" + $3->name() + ")");
1344
$$ = new VariableExpr("*");
1345
KexiDBDbg << "all columns";
1347
// QueryAsterisk *ast = new QueryAsterisk(parser->select(), dummy);
1348
// parser->select()->addAsterisk(ast);
1349
// requiresTable = true;
1351
| IDENTIFIER '.' '*'
1355
$$ = new VariableExpr(s);
1356
KexiDBDbg << " + all columns from " << s;
1359
/*| ERROR_DIGIT_BEFORE_IDENTIFIER
1361
$$ = new VariableExpr($1);
1362
KexiDBDbg << " Invalid identifier! " << $1;
1363
setError(i18n("Invalid identifier \"%1\"",$1));