LCOV - code coverage report
Current view: top level - core - qgssqlstatementparser.yy (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 29 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           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                 :            : 

Generated by: LCOV version 1.14