Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgssqlexpressionparser.yy
3 : : --------------------
4 : : begin : April 2016
5 : : copyright : (C) 2011 by Martin Dobias
6 : : copyright : (C) 2016 by Even Rouault
7 : : copyright : (C) 2010 by Frank Warmerdam (partly derived from GDAL ogr/swq_parser.y)
8 : : email : even.rouault at spatialys.com
9 : : ***************************************************************************
10 : : * *
11 : : * This program is free software; you can redistribute it and/or modify *
12 : : * it under the terms of the GNU General Public License as published by *
13 : : * the Free Software Foundation; either version 2 of the License, or *
14 : : * (at your option) any later version. *
15 : : * *
16 : : ***************************************************************************/
17 : :
18 : : %{
19 : : #include <qglobal.h>
20 : : #include <QList>
21 : : #include <cstdlib>
22 : : #include "qgssqlstatement.h"
23 : :
24 : : #ifdef _MSC_VER
25 : : # pragma warning( disable: 4065 ) // switch statement contains 'default' but no 'case' labels
26 : : # pragma warning( disable: 4702 ) // unreachable code
27 : : #endif
28 : :
29 : : // don't redeclare malloc/free
30 : : #define YYINCLUDED_STDLIB_H 1
31 : :
32 : : struct sqlstatement_parser_context;
33 : : #include "qgssqlstatementparser.hpp"
34 : :
35 : : //! from lexer
36 : : typedef void* yyscan_t;
37 : : typedef struct yy_buffer_state* YY_BUFFER_STATE;
38 : : extern int sqlstatement_lex_init(yyscan_t* scanner);
39 : : extern int sqlstatement_lex_destroy(yyscan_t scanner);
40 : : extern int sqlstatement_lex(YYSTYPE* yylval_param, yyscan_t yyscanner);
41 : : extern YY_BUFFER_STATE sqlstatement__scan_string(const char* buffer, yyscan_t scanner);
42 : :
43 : : /** returns parsed tree, otherwise returns nullptr and sets parserErrorMsg
44 : : (interface function to be called from QgsSQLStatement)
45 : : */
46 : : QgsSQLStatement::Node* parse(const QString& str, QString& parserErrorMsg);
47 : :
48 : : /** error handler for bison */
49 : : void sqlstatement_error(sqlstatement_parser_context* parser_ctx, const QString& errorMsg);
50 : :
51 : 0 : struct sqlstatement_parser_context
52 : : {
53 : : // lexer context
54 : : yyscan_t flex_scanner;
55 : :
56 : : // variable where the parser error will be stored
57 : : QString errorMsg;
58 : : // root node of the sqlstatement
59 : : QgsSQLStatement::NodeSelect* rootNode;
60 : :
61 : : QgsSQLStatement::Node* whereExp;
62 : :
63 : : QgsSQLStatement::Node* expression;
64 : :
65 : : QList<QgsSQLStatement::NodeJoin*> joinList;
66 : :
67 : : QList<QgsSQLStatement::NodeColumnSorted*> orderByList;
68 : :
69 : 0 : sqlstatement_parser_context() : rootNode( nullptr ), whereExp( nullptr ), expression( nullptr ) {}
70 : :
71 : 0 : void setWhere( QgsSQLStatement::Node* whereExp ) { this->whereExp = whereExp; }
72 : :
73 : 0 : void setJoins( const QList<QgsSQLStatement::NodeJoin*>& joinList ) { this->joinList = joinList; }
74 : :
75 : 0 : void setOrderBy( const QList<QgsSQLStatement::NodeColumnSorted*>& orderByList ) { this->orderByList = orderByList; }
76 : : };
77 : :
78 : : #define scanner parser_ctx->flex_scanner
79 : :
80 : : // we want verbose error messages
81 : : #define YYERROR_VERBOSE 1
82 : :
83 : : #define BINOP(x, y, z) new QgsSQLStatement::NodeBinaryOperator(x, y, z)
84 : :
85 : : %}
86 : :
87 : : // make the parser reentrant
88 : : %define api.pure
89 : : %lex-param {void * scanner}
90 : : %parse-param {sqlstatement_parser_context* parser_ctx}
91 : :
92 : : %union
93 : : {
94 : : QgsSQLStatement::Node* node;
95 : : QgsSQLStatement::NodeColumnRef* nodecolumnref;
96 : : QgsSQLStatement::NodeSelectedColumn* nodeselectedcolumn;
97 : : QgsSQLStatement::NodeSelect* nodeselect;
98 : : QgsSQLStatement::NodeList* nodelist;
99 : : QgsSQLStatement::NodeJoin* nodejoin;
100 : : QgsSQLStatement::NodeTableDef* nodetabledef;
101 : : QgsSQLStatement::NodeColumnSorted* nodecolumnsorted;
102 : : QList<QgsSQLStatement::NodeColumnSorted*>* columnsortedlist;
103 : : QList<QgsSQLStatement::NodeJoin*>* joinlist;
104 : : QList<QgsSQLStatement::NodeTableDef*>* tablelist;
105 : : QList<QgsSQLStatement::NodeSelectedColumn*>* selectedcolumnlist;
106 : : double numberFloat;
107 : : int numberInt;
108 : : qlonglong numberInt64;
109 : : bool boolVal;
110 : : QString* text;
111 : : QgsSQLStatement::BinaryOperator b_op;
112 : : QgsSQLStatement::UnaryOperator u_op;
113 : : QgsSQLStatement::JoinType jointype;
114 : : QList<QString>* usinglist;
115 : : }
116 : :
117 : : %start root
118 : :
119 : :
120 : : //
121 : : // token definitions
122 : : //
123 : :
124 : : // operator tokens
125 : : %token <b_op> OR AND EQ NE LE GE LT GT LIKE IS PLUS MINUS MUL_OR_STAR DIV INTDIV MOD CONCAT POW
126 : : %token <u_op> NOT
127 : : %token IN BETWEEN
128 : :
129 : : %token SELECT ALL DISTINCT CAST AS JOIN FROM ON USING WHERE ORDER BY ASC DESC LEFT RIGHT INNER OUTER CROSS FULL NATURAL UNION
130 : :
131 : : // literals
132 : : %token <numberFloat> NUMBER_FLOAT
133 : : %token <numberInt> NUMBER_INT
134 : : %token <numberInt64> NUMBER_INT64
135 : : %token <boolVal> BOOLEAN
136 : : %token NULLVALUE
137 : :
138 : : %token <text> STRING IDENTIFIER
139 : :
140 : : %token COMMA
141 : :
142 : : %token Unknown_CHARACTER
143 : :
144 : : //
145 : : // definition of non-terminal types
146 : : //
147 : :
148 : : %type <node> expr
149 : : %type <node> expr_non_logical
150 : : %type <nodecolumnref> column_name
151 : : %type <nodecolumnsorted> sort_spec
152 : : %type <nodeselectedcolumn> selected_column
153 : : %type <nodeselect> select_statement
154 : : %type <nodejoin> join
155 : : %type <nodetabledef> table_def
156 : : %type <nodelist> expr_list
157 : : %type <selectedcolumnlist> selected_column_list
158 : : %type <joinlist> join_list
159 : : %type <tablelist> table_list
160 : : %type <columnsortedlist> sort_spec_list
161 : : %type <usinglist> using_list;
162 : : %type <text> as_clause
163 : : %type <jointype> join_qualifier
164 : : %type <boolVal> select_type;
165 : :
166 : : // debugging
167 : : %define parse.error verbose
168 : :
169 : : //
170 : : // operator precedence
171 : : //
172 : :
173 : : // left associativity means that 1+2+3 translates to (1+2)+3
174 : : // the order of operators here determines their precedence
175 : :
176 : : %left OR
177 : : %left AND
178 : : %right NOT
179 : : %left BETWEEN
180 : : %left EQ NE LE GE LT GT LIKE IS IN
181 : : %left PLUS MINUS
182 : : %left MUL_OR_STAR DIV INTDIV MOD
183 : : %right POW
184 : : %left CONCAT
185 : :
186 : : %right UMINUS // fictitious symbol (for unary minus)
187 : :
188 : : %left COMMA
189 : :
190 : : %destructor { delete $$; } <node>
191 : : %destructor { delete $$; } <nodelist>
192 : : %destructor { delete $$; } <nodecolumnref>
193 : : %destructor { delete $$; } <text>
194 : : %destructor { delete $$; } <nodetabledef>
195 : : %destructor { delete $$; } <nodeselect>
196 : : %destructor { delete $$; } <nodeselectedcolumn>
197 : : %destructor { delete $$; } <nodecolumnsorted>
198 : : %destructor { delete $$; } <nodejoin>
199 : : %destructor { delete $$; } <usinglist>
200 : : %destructor { qDeleteAll(*$$); delete $$; } <selectedcolumnlist>
201 : : %destructor { qDeleteAll(*$$); delete $$; } <columnsortedlist>
202 : : %destructor { qDeleteAll(*$$); delete $$; } <joinlist>
203 : : %destructor { qDeleteAll(*$$); delete $$; } <tablelist>
204 : :
205 : : %%
206 : :
207 : : root: select_statement { parser_ctx->rootNode = $1; }
208 : : | expr { parser_ctx->expression = $1; }
209 : : ;
210 : :
211 : : /* We have to separate expr from expr_non_logical to avoid */
212 : : /* grammar ambiguities with the AND of the "BETWEEN x AND y" and the */
213 : : /* logical binary AND */
214 : : expr:
215 : : expr_non_logical
216 : : {
217 : : $$ = $1;
218 : : }
219 : :
220 : : | expr AND expr { $$ = BINOP($2, $1, $3); }
221 : : | expr OR expr { $$ = BINOP($2, $1, $3); }
222 : : | expr EQ expr { $$ = BINOP($2, $1, $3); }
223 : : | expr NE expr { $$ = BINOP($2, $1, $3); }
224 : : | expr LE expr { $$ = BINOP($2, $1, $3); }
225 : : | expr GE expr { $$ = BINOP($2, $1, $3); }
226 : : | expr LT expr { $$ = BINOP($2, $1, $3); }
227 : : | expr GT expr { $$ = BINOP($2, $1, $3); }
228 : : | expr LIKE expr { $$ = BINOP($2, $1, $3); }
229 : : | expr IS expr { $$ = BINOP($2, $1, $3); }
230 : : | NOT expr { $$ = new QgsSQLStatement::NodeUnaryOperator($1, $2); }
231 : :
232 : : | expr IN '(' expr_list ')' { $$ = new QgsSQLStatement::NodeInOperator($1, $4, false); }
233 : : | expr NOT IN '(' expr_list ')' { $$ = new QgsSQLStatement::NodeInOperator($1, $5, true); }
234 : :
235 : : | expr BETWEEN expr_non_logical AND expr_non_logical { $$ = new QgsSQLStatement::NodeBetweenOperator($1, $3, $5, false); }
236 : : | expr NOT BETWEEN expr_non_logical AND expr_non_logical { $$ = new QgsSQLStatement::NodeBetweenOperator($1, $4, $6, true); }
237 : :
238 : : ;
239 : :
240 : : column_name:
241 : : IDENTIFIER
242 : : {
243 : : $$ = new QgsSQLStatement::NodeColumnRef( *$1, false );
244 : : delete $1;
245 : : }
246 : :
247 : : | IDENTIFIER '.' IDENTIFIER
248 : : {
249 : : $$ = new QgsSQLStatement::NodeColumnRef( *$1, *$3, false );
250 : : delete $1;
251 : : delete $3;
252 : : }
253 : : ;
254 : :
255 : : expr_list:
256 : : expr_list COMMA expr
257 : : {
258 : : $$ = $1; $1->append($3);
259 : : }
260 : : | expr { $$ = new QgsSQLStatement::NodeList(); $$->append($1); }
261 : : ;
262 : :
263 : : expr_non_logical:
264 : :
265 : : // literals
266 : : NUMBER_FLOAT { $$ = new QgsSQLStatement::NodeLiteral( QVariant($1) ); }
267 : : | NUMBER_INT { $$ = new QgsSQLStatement::NodeLiteral( QVariant($1) ); }
268 : : | NUMBER_INT64 { $$ = new QgsSQLStatement::NodeLiteral( QVariant($1) ); }
269 : : | BOOLEAN { $$ = new QgsSQLStatement::NodeLiteral( QVariant($1) ); }
270 : : | STRING { $$ = new QgsSQLStatement::NodeLiteral( QVariant(*$1) ); delete $1; }
271 : : | NULLVALUE { $$ = new QgsSQLStatement::NodeLiteral( QVariant() ); }
272 : :
273 : : | column_name
274 : : {
275 : : $$ = $1;
276 : : }
277 : :
278 : : | '(' expr ')' { $$ = $2; }
279 : :
280 : : | IDENTIFIER '(' expr_list ')'
281 : : {
282 : : $$ = new QgsSQLStatement::NodeFunction(*$1, $3);
283 : : delete $1;
284 : : }
285 : :
286 : : | IDENTIFIER '(' ')'
287 : : {
288 : : $$ = new QgsSQLStatement::NodeFunction(*$1, new QgsSQLStatement::NodeList());
289 : : delete $1;
290 : : }
291 : :
292 : : | expr_non_logical PLUS expr_non_logical { $$ = BINOP($2, $1, $3); }
293 : : | expr_non_logical MINUS expr_non_logical { $$ = BINOP($2, $1, $3); }
294 : : | expr_non_logical MUL_OR_STAR expr_non_logical { $$ = BINOP($2, $1, $3); }
295 : : | expr_non_logical INTDIV expr_non_logical { $$ = BINOP($2, $1, $3); }
296 : : | expr_non_logical DIV expr_non_logical { $$ = BINOP($2, $1, $3); }
297 : : | expr_non_logical MOD expr_non_logical { $$ = BINOP($2, $1, $3); }
298 : : | expr_non_logical POW expr_non_logical { $$ = BINOP($2, $1, $3); }
299 : : | expr_non_logical CONCAT expr_non_logical { $$ = BINOP($2, $1, $3); }
300 : : | PLUS expr_non_logical %prec UMINUS { $$ = $2; }
301 : : | MINUS expr_non_logical %prec UMINUS { $$ = new QgsSQLStatement::NodeUnaryOperator( QgsSQLStatement::uoMinus, $2); }
302 : :
303 : : | CAST '(' expr AS IDENTIFIER ')'
304 : : {
305 : : $$ = new QgsSQLStatement::NodeCast($3, *$5);
306 : : delete $5;
307 : : }
308 : :
309 : : ;
310 : :
311 : : select_type:
312 : : SELECT
313 : : {
314 : : $$ = false;
315 : : }
316 : : | SELECT ALL
317 : : {
318 : : $$ = false;
319 : : }
320 : : | SELECT DISTINCT
321 : : {
322 : : $$ = true;
323 : : }
324 : : ;
325 : :
326 : : select_statement:
327 : : select_type selected_column_list FROM table_list opt_joins opt_where opt_order_by
328 : : {
329 : : $$ = new QgsSQLStatement::NodeSelect(*$4, *$2, $1);
330 : : delete $2;
331 : : delete $4;
332 : : }
333 : : ;
334 : :
335 : : selected_column_list:
336 : : selected_column_list COMMA selected_column
337 : : {
338 : : $$ = $1; $1->append($3);
339 : : }
340 : : | selected_column
341 : : { $$ = new QList<QgsSQLStatement::NodeSelectedColumn*>(); $$->append($1); }
342 : : ;
343 : :
344 : : selected_column:
345 : : expr
346 : : {
347 : : $$ = new QgsSQLStatement::NodeSelectedColumn($1);
348 : : }
349 : :
350 : : | expr as_clause
351 : : {
352 : : $$ = new QgsSQLStatement::NodeSelectedColumn($1);
353 : : $$->setAlias(*$2);
354 : : delete $2;
355 : : }
356 : :
357 : : | MUL_OR_STAR
358 : : {
359 : : $$ = new QgsSQLStatement::NodeSelectedColumn( new QgsSQLStatement::NodeColumnRef("*", true) );
360 : : }
361 : :
362 : : | IDENTIFIER '.' MUL_OR_STAR
363 : : {
364 : : $$ = new QgsSQLStatement::NodeSelectedColumn( new QgsSQLStatement::NodeColumnRef(*$1, "*", true) );
365 : : delete $1;
366 : : }
367 : :
368 : : | IDENTIFIER '(' MUL_OR_STAR ')'
369 : : {
370 : : // special case for COUNT(*), confirm it.
371 : : if( $1->compare("COUNT", Qt::CaseInsensitive) != 0 )
372 : : {
373 : : sqlstatement_error(parser_ctx, QString( QObject::tr("Syntax Error with %1(*).") ).arg(*$1));
374 : : delete $1;
375 : : YYERROR;
376 : : }
377 : : delete $1;
378 : : QgsSQLStatement::NodeList* nodeList = new QgsSQLStatement::NodeList();
379 : : nodeList->append( new QgsSQLStatement::NodeColumnRef("*", true) );
380 : : $$ = new QgsSQLStatement::NodeSelectedColumn(
381 : : new QgsSQLStatement::NodeFunction( "COUNT", nodeList) );
382 : : }
383 : :
384 : : | IDENTIFIER '(' MUL_OR_STAR ')' as_clause
385 : : {
386 : : // special case for COUNT(*), confirm it.
387 : : if( $1->compare("COUNT", Qt::CaseInsensitive) != 0 )
388 : : {
389 : : sqlstatement_error(parser_ctx, QString( QObject::tr("Syntax Error with %1(*).") ).arg(*$1));
390 : : delete $1;
391 : : delete $5;
392 : : YYERROR;
393 : : }
394 : : delete $1;
395 : : QgsSQLStatement::NodeList* nodeList = new QgsSQLStatement::NodeList();
396 : : nodeList->append( new QgsSQLStatement::NodeColumnRef("*", true) );
397 : : $$ = new QgsSQLStatement::NodeSelectedColumn(
398 : : new QgsSQLStatement::NodeFunction( "COUNT", nodeList) );
399 : : $$->setAlias(*$5);
400 : : delete $5;
401 : : }
402 : :
403 : : | IDENTIFIER '(' DISTINCT column_name ')'
404 : : {
405 : : // special case for COUNT(DISTINCT x), confirm it.
406 : : if( $1->compare("COUNT", Qt::CaseInsensitive) != 0 )
407 : : {
408 : : sqlstatement_error(parser_ctx, QObject::tr(
409 : : "DISTINCT keyword can only be used in COUNT() operator.") );
410 : : delete $1;
411 : : delete $4;
412 : : YYERROR;
413 : : }
414 : : delete $1;
415 : : QgsSQLStatement::NodeList* nodeList = new QgsSQLStatement::NodeList();
416 : : $4->setDistinct();
417 : : nodeList->append( $4 );
418 : : $$ = new QgsSQLStatement::NodeSelectedColumn(
419 : : new QgsSQLStatement::NodeFunction( "COUNT", nodeList) );
420 : : }
421 : :
422 : : | IDENTIFIER '(' DISTINCT column_name ')' as_clause
423 : : {
424 : : // special case for COUNT(DISTINCT x), confirm it.
425 : : if( $1->compare("COUNT", Qt::CaseInsensitive) != 0 )
426 : : {
427 : : sqlstatement_error(parser_ctx, QObject::tr(
428 : : "DISTINCT keyword can only be used in COUNT() operator.") );
429 : : delete $1;
430 : : delete $4;
431 : : delete $6;
432 : : YYERROR;
433 : : }
434 : : delete $1;
435 : : QgsSQLStatement::NodeList* nodeList = new QgsSQLStatement::NodeList();
436 : : $4->setDistinct();
437 : : nodeList->append( $4 );
438 : : $$ = new QgsSQLStatement::NodeSelectedColumn(
439 : : new QgsSQLStatement::NodeFunction( "COUNT", nodeList) );
440 : : $$->setAlias(*$6);
441 : : delete $6;
442 : : }
443 : : ;
444 : :
445 : : as_clause:
446 : : AS IDENTIFIER
447 : : {
448 : : $$ = $2;
449 : : }
450 : :
451 : : | IDENTIFIER
452 : : ;
453 : :
454 : : opt_where:
455 : : | WHERE expr
456 : : {
457 : : parser_ctx->setWhere($2);
458 : : }
459 : : ;
460 : :
461 : : join_qualifier:
462 : : JOIN
463 : : {
464 : : $$ = QgsSQLStatement::jtDefault;
465 : : }
466 : : | LEFT JOIN
467 : : {
468 : : $$ = QgsSQLStatement::jtLeft;
469 : : }
470 : : | LEFT OUTER JOIN
471 : : {
472 : : $$ = QgsSQLStatement::jtLeftOuter;
473 : : }
474 : : | RIGHT JOIN
475 : : {
476 : : $$ = QgsSQLStatement::jtRight;
477 : : }
478 : : | RIGHT OUTER JOIN
479 : : {
480 : : $$ = QgsSQLStatement::jtRightOuter;
481 : : }
482 : : | FULL JOIN
483 : : {
484 : : $$ = QgsSQLStatement::jtFull;
485 : : }
486 : : | CROSS JOIN
487 : : {
488 : : $$ = QgsSQLStatement::jtCross;
489 : : }
490 : : | INNER JOIN
491 : : {
492 : : $$ = QgsSQLStatement::jtInner;
493 : : }
494 : : ;
495 : :
496 : : join:
497 : : join_qualifier table_def ON expr
498 : : {
499 : : $$ = new QgsSQLStatement::NodeJoin($2, $4, $1);
500 : : }
501 : : | join_qualifier table_def USING '(' using_list ')'
502 : : {
503 : : $$ = new QgsSQLStatement::NodeJoin($2, *$5, $1);
504 : : delete $5;
505 : : }
506 : : ;
507 : :
508 : : using_list:
509 : : IDENTIFIER
510 : : {
511 : : $$ = new QList<QString>(); $$->push_back(*$1);
512 : : delete $1;
513 : : }
514 : : | using_list COMMA IDENTIFIER
515 : : {
516 : : $$ = $1; $1->push_back(*$3);
517 : : delete $3;
518 : : }
519 : : ;
520 : :
521 : : join_list:
522 : : join
523 : : {
524 : : $$ = new QList<QgsSQLStatement::NodeJoin*>(); $$->push_back($1);
525 : : }
526 : : | join_list join
527 : : {
528 : : $$ = $1; $1->push_back($2);
529 : : }
530 : : ;
531 : :
532 : : opt_joins:
533 : : | join_list
534 : : {
535 : : parser_ctx->setJoins( *$1 );
536 : : delete $1;
537 : : }
538 : : ;
539 : :
540 : : opt_order_by:
541 : : | ORDER BY sort_spec_list
542 : : {
543 : : parser_ctx->setOrderBy(*$3);
544 : : delete $3;
545 : : }
546 : : ;
547 : :
548 : : sort_spec_list:
549 : : sort_spec_list COMMA sort_spec
550 : : {
551 : : $$ = $1; $1->push_back($3);
552 : : }
553 : : | sort_spec
554 : : { $$ = new QList<QgsSQLStatement::NodeColumnSorted*>(); $$->push_back($1); }
555 : : ;
556 : :
557 : : sort_spec:
558 : : column_name
559 : : {
560 : : $$ = new QgsSQLStatement::NodeColumnSorted( $1, true );
561 : : }
562 : : | column_name ASC
563 : : {
564 : : $$ = new QgsSQLStatement::NodeColumnSorted( $1, true );
565 : : }
566 : : | column_name DESC
567 : : {
568 : : $$ = new QgsSQLStatement::NodeColumnSorted( $1, false );
569 : : }
570 : : ;
571 : :
572 : : table_def:
573 : : IDENTIFIER
574 : : {
575 : : $$ = new QgsSQLStatement::NodeTableDef(*$1);
576 : : delete $1;
577 : : }
578 : :
579 : : | IDENTIFIER as_clause
580 : : {
581 : : $$ = new QgsSQLStatement::NodeTableDef(*$1, *$2);
582 : : delete $1;
583 : : delete $2;
584 : : }
585 : : ;
586 : :
587 : : table_list:
588 : : table_list COMMA table_def
589 : : {
590 : : $$ = $1; $1->push_back($3);
591 : : }
592 : : | table_def
593 : : { $$ = new QList<QgsSQLStatement::NodeTableDef*>(); $$->push_back($1); }
594 : : ;
595 : :
596 : : %%
597 : :
598 : :
599 : : // returns parsed tree, otherwise returns nullptr and sets parserErrorMsg
600 : 0 : QgsSQLStatement::Node* parse(const QString& str, QString& parserErrorMsg, bool allowFragments )
601 : : {
602 : 0 : sqlstatement_parser_context ctx;
603 : 0 : ctx.rootNode = 0;
604 : :
605 : 0 : sqlstatement_lex_init(&ctx.flex_scanner);
606 : 0 : sqlstatement__scan_string(str.toUtf8().constData(), ctx.flex_scanner);
607 : 0 : int res = sqlstatement_parse(&ctx);
608 : 0 : sqlstatement_lex_destroy(ctx.flex_scanner);
609 : :
610 : : // list should be empty when parsing was OK
611 : 0 : if ( res == 0 && ( ctx.rootNode || ( allowFragments && ctx.expression ) ) ) // success?
612 : : {
613 : 0 : if ( ctx.rootNode )
614 : : {
615 : 0 : ctx.rootNode->setWhere(ctx.whereExp);
616 : 0 : ctx.rootNode->setJoins(ctx.joinList);
617 : 0 : ctx.rootNode->setOrderBy(ctx.orderByList);
618 : 0 : return ctx.rootNode;
619 : : }
620 : : else
621 : : {
622 : : //fragment
623 : 0 : return ctx.expression;
624 : : }
625 : : }
626 : : else // error?
627 : : {
628 : 0 : parserErrorMsg = !allowFragments && !ctx.rootNode ? QStringLiteral("Expression must begin with SELECT") : ctx.errorMsg;
629 : 0 : delete ctx.rootNode;
630 : 0 : delete ctx.whereExp;
631 : 0 : qDeleteAll(ctx.joinList);
632 : 0 : qDeleteAll(ctx.orderByList);
633 : 0 : return nullptr;
634 : : }
635 : 0 : }
636 : :
637 : :
638 : 0 : void sqlstatement_error(sqlstatement_parser_context* parser_ctx, const QString& errorMsg)
639 : : {
640 : 0 : parser_ctx->errorMsg = errorMsg;
641 : 0 : }
642 : :
|