LCOV - code coverage report
Current view: directory - ogr - swq_parser.y (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 392 333 84.9 %
Date: 2011-12-18 Functions: 1 1 100.0 %

       1                 : %{
       2                 : /******************************************************************************
       3                 :  *
       4                 :  * Component: OGR SQL Engine
       5                 :  * Purpose: expression and select parser grammar.
       6                 :  *          Requires Bison 2.4.0 or newer to process.  Use "make parser" target.
       7                 :  * Author: Frank Warmerdam <warmerdam@pobox.com>
       8                 :  * 
       9                 :  ******************************************************************************
      10                 :  * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : 
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : #include "swq.h"
      35                 : 
      36                 : #define YYSTYPE  swq_expr_node*
      37                 : 
      38                 : /* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */ 
      39                 : /* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */ 
      40                 : /* increase YYINITDEPTH instead, but this will consume memory. */ 
      41                 : /* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */ 
      42                 : /* it appears to be a non documented feature of Bison */ 
      43                 : #define YYSTYPE_IS_TRIVIAL 1
      44                 : 
      45              81 : static void swqerror( swq_parse_context *context, const char *msg )
      46                 : {
      47                 :     CPLError( CE_Failure, CPLE_AppDefined, 
      48              81 :               "SQL Expression Parsing Error: %s", msg );
      49              81 : }
      50                 : 
      51                 : %}
      52                 : 
      53                 : %define api.pure
      54                 : %require "2.4.0"
      55                 : 
      56                 : %parse-param {swq_parse_context *context}
      57                 : %lex-param {swq_parse_context *context}
      58                 : 
      59                 : %token SWQT_NUMBER
      60                 : %token SWQT_STRING
      61                 : %token SWQT_IDENTIFIER
      62                 : %token SWQT_IN
      63                 : %token SWQT_LIKE
      64                 : %token SWQT_ESCAPE
      65                 : %token SWQT_BETWEEN
      66                 : %token SWQT_NULL
      67                 : %token SWQT_IS
      68                 : %token SWQT_SELECT
      69                 : %token SWQT_LEFT
      70                 : %token SWQT_JOIN
      71                 : %token SWQT_WHERE
      72                 : %token SWQT_ON
      73                 : %token SWQT_ORDER
      74                 : %token SWQT_BY
      75                 : %token SWQT_FROM
      76                 : %token SWQT_AS
      77                 : %token SWQT_ASC
      78                 : %token SWQT_DESC
      79                 : %token SWQT_DISTINCT
      80                 : %token SWQT_CAST
      81                 : 
      82                 : %token SWQT_LOGICAL_START
      83                 : %token SWQT_VALUE_START
      84                 : %token SWQT_SELECT_START
      85                 : 
      86                 : %left SWQT_NOT
      87                 : %left SWQT_OR
      88                 : %left SWQT_AND
      89              22 : 
      90              69 : %left '+' '-'
      91                 : %left '*' '/' '%'
      92                 : %left SWQT_UMINUS
      93                 : 
      94                 : /* Any grammar rule that does $$ =  must be listed afterwards */
      95                 : /* as well as SWQT_NUMBER SWQT_STRING SWQT_IDENTIFIER that are allocated by swqlex() */
      96                 : %destructor { delete $$; } SWQT_NUMBER SWQT_STRING SWQT_IDENTIFIER
      97             338 : %destructor { delete $$; } logical_expr value_expr_list field_value value_expr type_def string_or_identifier table_def
      98                 : 
      99             338 : %%
     100                 : 
     101                 : input:  
     102               0 :   SWQT_LOGICAL_START logical_expr
     103                 :     {
     104               0 :       context->poRoot = $2;
     105                 :     }
     106                 : 
     107             216 :   | SWQT_VALUE_START value_expr
     108                 :     {
     109             216 :       context->poRoot = $2;
     110                 :     }
     111                 : 
     112                 :   | SWQT_SELECT_START select_statement
     113              37 :     {
     114              37 :       context->poRoot = $2;
     115              37 :     }
     116              37 : 
     117                 : logical_expr:
     118              37 :   logical_expr SWQT_AND logical_expr 
     119                 :          {
     120                 :       $$ = new swq_expr_node( SWQ_AND );
     121               6 :       $$->field_type = SWQ_BOOLEAN;
     122               6 :       $$->PushSubExpression( $1 );
     123               6 :       $$->PushSubExpression( $3 );
     124               6 :          }
     125                 : 
     126               6 :   | logical_expr SWQT_OR logical_expr
     127                 :          {
     128                 :       $$ = new swq_expr_node( SWQ_OR );
     129               8 :       $$->field_type = SWQ_BOOLEAN;
     130               8 :       $$->PushSubExpression( $1 );
     131               8 :       $$->PushSubExpression( $3 );
     132                 :          }
     133               8 : 
     134                 :   | SWQT_NOT logical_expr
     135                 :          {
     136              24 :       $$ = new swq_expr_node( SWQ_NOT );
     137                 :       $$->field_type = SWQ_BOOLEAN;
     138              24 :       $$->PushSubExpression( $2 );
     139                 :          }
     140                 : 
     141             253 :   | '(' logical_expr ')'
     142             253 :                {
     143             253 :       $$ = $2;
     144             253 :          }
     145                 : 
     146             253 :   | value_expr '=' value_expr
     147                 :                {
     148                 :       $$ = new swq_expr_node( SWQ_EQ );
     149              52 :       $$->field_type = SWQ_BOOLEAN;
     150              52 :       $$->PushSubExpression( $1 );
     151              52 :       $$->PushSubExpression( $3 );
     152              52 :          }
     153                 : 
     154              52 :   | value_expr '<' '>' value_expr
     155                 :                {
     156                 :       $$ = new swq_expr_node( SWQ_NE );
     157               4 :       $$->field_type = SWQ_BOOLEAN;
     158               4 :       $$->PushSubExpression( $1 );
     159               4 :       $$->PushSubExpression( $4 );
     160               4 :          }
     161                 : 
     162               4 :   | value_expr '!' '=' value_expr
     163                 :                {
     164                 :       $$ = new swq_expr_node( SWQ_NE );
     165              34 :       $$->field_type = SWQ_BOOLEAN;
     166              34 :       $$->PushSubExpression( $1 );
     167              34 :       $$->PushSubExpression( $4 );
     168              34 :          }
     169                 : 
     170              34 :   | value_expr '<' value_expr
     171                 :                {
     172                 :       $$ = new swq_expr_node( SWQ_LT );
     173              35 :       $$->field_type = SWQ_BOOLEAN;
     174              35 :       $$->PushSubExpression( $1 );
     175              35 :       $$->PushSubExpression( $3 );
     176              35 :          }
     177                 : 
     178              35 :   | value_expr '>' value_expr
     179                 :                {
     180                 :       $$ = new swq_expr_node( SWQ_GT );
     181               6 :       $$->field_type = SWQ_BOOLEAN;
     182               6 :       $$->PushSubExpression( $1 );
     183               6 :       $$->PushSubExpression( $3 );
     184               6 :          }
     185                 : 
     186               6 :   | value_expr '<' '=' value_expr
     187                 :                {
     188                 :       $$ = new swq_expr_node( SWQ_LE );
     189               0 :       $$->field_type = SWQ_BOOLEAN;
     190               0 :       $$->PushSubExpression( $1 );
     191               0 :       $$->PushSubExpression( $4 );
     192               0 :          }
     193                 : 
     194               0 :   | value_expr '=' '<' value_expr
     195                 :                {
     196                 :       $$ = new swq_expr_node( SWQ_LE );
     197               0 :       $$->field_type = SWQ_BOOLEAN;
     198               0 :       $$->PushSubExpression( $1 );
     199               0 :       $$->PushSubExpression( $4 );
     200               0 :          }
     201                 : 
     202               0 :   | value_expr '=' '>' value_expr
     203                 :                {
     204                 :       $$ = new swq_expr_node( SWQ_LE );
     205               7 :       $$->field_type = SWQ_BOOLEAN;
     206               7 :       $$->PushSubExpression( $1 );
     207               7 :       $$->PushSubExpression( $4 );
     208               7 :          }
     209                 : 
     210               7 :   | value_expr '>' '=' value_expr
     211                 :                {
     212                 :       $$ = new swq_expr_node( SWQ_GE );
     213               9 :       $$->field_type = SWQ_BOOLEAN;
     214               9 :       $$->PushSubExpression( $1 );
     215               9 :       $$->PushSubExpression( $4 );
     216               9 :          }
     217                 : 
     218               9 :   | value_expr SWQT_LIKE value_expr
     219                 :                {
     220                 :       $$ = new swq_expr_node( SWQ_LIKE );
     221                 :       $$->field_type = SWQ_BOOLEAN;
     222               1 :       $$->PushSubExpression( $1 );
     223               1 :       $$->PushSubExpression( $3 );
     224               1 :          }
     225               1 : 
     226                 :   | value_expr SWQT_NOT SWQT_LIKE value_expr
     227               2 :                {
     228               1 :             swq_expr_node *like;
     229               1 :       like = new swq_expr_node( SWQ_LIKE );
     230                 :       like->field_type = SWQ_BOOLEAN;
     231               1 :       like->PushSubExpression( $1 );
     232                 :       like->PushSubExpression( $4 );
     233                 : 
     234               2 :       $$ = new swq_expr_node( SWQ_NOT );
     235               2 :       $$->field_type = SWQ_BOOLEAN;
     236               2 :       $$->PushSubExpression( like );
     237               2 :          }
     238               2 : 
     239                 :     | value_expr SWQT_LIKE value_expr SWQT_ESCAPE value_expr
     240               2 :       {
     241                 :             $$ = new swq_expr_node( SWQ_LIKE );
     242                 :             $$->field_type = SWQ_BOOLEAN;
     243                 :             $$->PushSubExpression( $1 );
     244               0 :             $$->PushSubExpression( $3 );
     245               0 :             $$->PushSubExpression( $5 );
     246               0 :        }
     247               0 : 
     248               0 :     | value_expr SWQT_NOT SWQT_LIKE value_expr SWQT_ESCAPE value_expr
     249                 :       {
     250               0 :                 swq_expr_node *like;
     251               0 :             like = new swq_expr_node( SWQ_LIKE );
     252               0 :             like->field_type = SWQ_BOOLEAN;
     253                 :             like->PushSubExpression( $1 );
     254               0 :             like->PushSubExpression( $4 );
     255                 :             like->PushSubExpression( $6 );
     256                 : 
     257              29 :             $$ = new swq_expr_node( SWQ_NOT );
     258              29 :             $$->field_type = SWQ_BOOLEAN;
     259              29 :             $$->PushSubExpression( like );
     260              29 :       }
     261              29 : 
     262                 :   | value_expr SWQT_IN '(' value_expr_list ')'
     263              29 :                {
     264                 :       $$ = $4;
     265                 :       $$->field_type = SWQ_BOOLEAN;
     266                 :       $$->nOperation = SWQ_IN;
     267                 :       $$->PushSubExpression( $1 );
     268               1 :       $$->ReverseSubExpressions();
     269               1 :          }
     270               1 : 
     271               1 :   | value_expr SWQT_NOT SWQT_IN '(' value_expr_list ')'
     272               1 :                {
     273                 :             swq_expr_node *in;
     274               1 : 
     275               1 :       in = $5;
     276               1 :       in->field_type = SWQ_BOOLEAN;
     277                 :       in->nOperation = SWQ_IN;
     278               1 :       in->PushSubExpression( $1 );
     279                 :       in->ReverseSubExpressions();
     280                 :       
     281               3 :       $$ = new swq_expr_node( SWQ_NOT );
     282               3 :       $$->field_type = SWQ_BOOLEAN;
     283               3 :       $$->PushSubExpression( in );
     284               3 :          }
     285               3 : 
     286                 :     | value_expr SWQT_BETWEEN value_expr SWQT_AND value_expr
     287               3 :                  {
     288                 :             $$ = new swq_expr_node( SWQ_BETWEEN );
     289                 :             $$->field_type = SWQ_BOOLEAN;
     290                 :             $$->PushSubExpression( $1 );
     291               1 :             $$->PushSubExpression( $3 );
     292               1 :             $$->PushSubExpression( $5 );
     293               1 :              }
     294               1 : 
     295               1 :     | value_expr SWQT_NOT SWQT_BETWEEN value_expr SWQT_AND value_expr
     296                 :                  {
     297               2 :             swq_expr_node *between;
     298               1 :             between = new swq_expr_node( SWQ_BETWEEN );
     299               1 :             between->field_type = SWQ_BOOLEAN;
     300                 :             between->PushSubExpression( $1 );
     301               1 :             between->PushSubExpression( $4 );
     302                 :             between->PushSubExpression( $6 );
     303                 : 
     304               7 :             $$ = new swq_expr_node( SWQ_NOT );
     305               7 :             $$->field_type = SWQ_BOOLEAN;
     306               7 :             $$->PushSubExpression( between );
     307                 :              }
     308               7 : 
     309                 :   | value_expr SWQT_IS SWQT_NULL
     310                 :                {
     311                 :       $$ = new swq_expr_node( SWQ_ISNULL );
     312                 :       $$->field_type = SWQ_BOOLEAN;
     313               3 :       $$->PushSubExpression( $1 );
     314               3 :          }
     315               3 : 
     316                 :   | value_expr SWQT_IS SWQT_NOT SWQT_NULL
     317               6 :                {
     318               3 :             swq_expr_node *isnull;
     319               3 : 
     320                 :       isnull = new swq_expr_node( SWQ_ISNULL );
     321               3 :       isnull->field_type = SWQ_BOOLEAN;
     322                 :       isnull->PushSubExpression( $1 );
     323                 : 
     324                 :       $$ = new swq_expr_node( SWQ_NOT );
     325              27 :       $$->field_type = SWQ_BOOLEAN;
     326              27 :       $$->PushSubExpression( isnull );
     327                 :          }
     328              27 : 
     329                 : value_expr_list:
     330                 :   value_expr ',' value_expr_list
     331              63 :     {
     332              63 :       $$ = $3;
     333                 :       $3->PushSubExpression( $1 );
     334              63 :     }
     335                 : 
     336                 :   | value_expr
     337                 :           {
     338            1619 :       $$ = new swq_expr_node( SWQ_UNKNOWN ); /* list */
     339            1619 :       $$->PushSubExpression( $1 );
     340            1619 :     }
     341                 : 
     342            1619 : field_value:
     343                 :   SWQT_IDENTIFIER
     344                 :     {
     345              53 :             $$ = $1;  // validation deferred.
     346              53 :       $$->eNodeType = SNT_COLUMN;
     347              53 :       $$->field_index = $$->table_index = -1;
     348                 :     }
     349                 : 
     350                 :   | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
     351              53 :     {
     352              53 :             $$ = $1;  // validation deferred.
     353              53 :       $$->eNodeType = SNT_COLUMN;
     354              53 :       $$->field_index = $$->table_index = -1;
     355              53 :       $$->string_value = (char *) 
     356                 :                             CPLRealloc( $$->string_value, 
     357              53 :                                         strlen($$->string_value) 
     358                 :                                         + strlen($3->string_value) + 2 );
     359                 :       strcat( $$->string_value, "." );
     360                 :       strcat( $$->string_value, $3->string_value );
     361             329 :       delete $3;
     362                 :       $3 = NULL;
     363             329 :     }
     364                 : 
     365                 : value_expr:
     366             189 :   SWQT_NUMBER 
     367                 :           {
     368             189 :       $$ = $1;
     369                 :     }
     370            1579 : 
     371                 :   | SWQT_STRING
     372            1579 :     {
     373                 :       $$ = $1;
     374                 :     }
     375              21 :   | field_value
     376                 :     {
     377              21 :       $$ = $1;
     378                 :     }
     379                 : 
     380               5 :   | '(' value_expr ')'
     381                 :     {
     382               5 :       $$ = $2;
     383                 :     }
     384                 : 
     385               5 :     | SWQT_NULL
     386                 :         {
     387               4 :             $$ = new swq_expr_node((const char*)NULL);
     388               4 :         }
     389               4 : 
     390                 :     | '-' value_expr %prec SWQT_UMINUS
     391                 :         {
     392                 :             if ($2->eNodeType == SNT_CONSTANT)
     393               1 :             {
     394               2 :                 $$ = $2;
     395               1 :                 $$->int_value *= -1;
     396                 :                 $$->float_value *= -1;
     397                 :             }
     398               5 :             else
     399                 :             {
     400                 :                 $$ = new swq_expr_node( SWQ_MULTIPLY );
     401               7 :                 $$->PushSubExpression( new swq_expr_node(-1) );
     402               7 :                 $$->PushSubExpression( $2 );
     403               7 :             }
     404                 :         }
     405               7 : 
     406                 :   | value_expr '+' value_expr
     407                 :     {
     408               3 :       $$ = new swq_expr_node( SWQ_ADD );
     409               3 :       $$->PushSubExpression( $1 );
     410               3 :       $$->PushSubExpression( $3 );
     411                 :     }
     412               3 : 
     413                 :   | value_expr '-' value_expr
     414                 :     {
     415               3 :       $$ = new swq_expr_node( SWQ_SUBTRACT );
     416               3 :       $$->PushSubExpression( $1 );
     417               3 :       $$->PushSubExpression( $3 );
     418                 :     }
     419               3 : 
     420                 :   | value_expr '*' value_expr
     421                 :     {
     422               4 :       $$ = new swq_expr_node( SWQ_MULTIPLY );
     423               4 :       $$->PushSubExpression( $1 );
     424               4 :       $$->PushSubExpression( $3 );
     425                 :     }
     426               4 : 
     427                 :   | value_expr '/' value_expr
     428                 :     {
     429               2 :       $$ = new swq_expr_node( SWQ_DIVIDE );
     430               2 :       $$->PushSubExpression( $1 );
     431               2 :       $$->PushSubExpression( $3 );
     432                 :     }
     433               2 : 
     434                 :   | value_expr '%' value_expr
     435                 :     {
     436                 :       $$ = new swq_expr_node( SWQ_MODULUS );
     437              30 :       $$->PushSubExpression( $1 );
     438                 :       $$->PushSubExpression( $3 );
     439              30 :     }
     440                 : 
     441                 :   | SWQT_IDENTIFIER '(' value_expr_list ')'
     442                 :     {
     443               0 :         const swq_operation *poOp = 
     444               0 :                       swq_op_registrar::GetOperator( $1->string_value );
     445               0 : 
     446               0 :         if( poOp == NULL )
     447                 :         {
     448                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     449                 :                                   "Undefined function '%s' used.",
     450              30 :                                   $1->string_value );
     451              30 :                 delete $1;
     452              30 :                 delete $3;
     453              30 :             YYERROR;
     454              30 :         }
     455                 :         else
     456                 :         {
     457              30 :       $$ = $3;
     458                 :                         $$->eNodeType = SNT_OPERATION;
     459                 :                         $$->nOperation = poOp->eOperation;
     460              33 :       $$->ReverseSubExpressions();
     461              33 :       delete $1;
     462              33 :         }
     463                 :     }
     464              33 : 
     465                 :   | SWQT_CAST '(' value_expr SWQT_AS type_def ')'
     466                 :           {
     467                 :         $$ = $5;
     468              29 :         $$->PushSubExpression( $3 );
     469              29 :         $$->ReverseSubExpressions();
     470                 :     }
     471              29 :     
     472                 : type_def:
     473                 :   SWQT_IDENTIFIER
     474               6 :   {
     475               6 :       $$ = new swq_expr_node( SWQ_CAST );
     476               6 :       $$->PushSubExpression( $1 );
     477                 :   }
     478               6 : 
     479                 :   | SWQT_IDENTIFIER '(' SWQT_NUMBER ')' 
     480                 :   {
     481               1 :       $$ = new swq_expr_node( SWQ_CAST );
     482               1 :       $$->PushSubExpression( $3 );
     483               1 :       $$->PushSubExpression( $1 );
     484               1 :   }
     485                 : 
     486               1 :   | SWQT_IDENTIFIER '(' SWQT_NUMBER ',' SWQT_NUMBER ')' 
     487                 :   {
     488                 :       $$ = new swq_expr_node( SWQ_CAST );
     489                 :       $$->PushSubExpression( $5 );
     490             216 :       $$->PushSubExpression( $3 );
     491                 :       $$->PushSubExpression( $1 );
     492             216 :   }
     493                 : 
     494                 : select_statement: 
     495                 :   SWQT_SELECT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by
     496                 :   {
     497                 :       delete $4;
     498                 :   }
     499                 : 
     500              16 : select_field_list:
     501                 :   column_spec
     502               0 :   | column_spec ',' select_field_list
     503               0 : 
     504                 : column_spec: 
     505                 :    SWQT_DISTINCT field_value
     506              16 :       {
     507                 :     if( !context->poSelect->PushField( $2, NULL, TRUE ) )
     508                 :         {
     509               0 :             delete $2;
     510                 :         YYERROR;
     511               0 :         }
     512               0 :       }
     513                 : 
     514                 :     | SWQT_DISTINCT SWQT_STRING
     515               0 :         {
     516                 :         if( !context->poSelect->PushField( $2, NULL, TRUE ) )
     517                 :         {
     518            1124 :             delete $2;
     519                 :             YYERROR;
     520               5 :         }
     521               5 :         }
     522                 : 
     523                 :     | value_expr
     524            1119 :       {
     525                 :     if( !context->poSelect->PushField( $1 ) )
     526                 :         {
     527               2 :             delete $1;
     528                 :         YYERROR;
     529               0 :         }
     530               0 :       }
     531               0 : 
     532                 :   | SWQT_DISTINCT field_value SWQT_AS string_or_identifier
     533                 :       {
     534               2 :     if( !context->poSelect->PushField( $2, $4->string_value, TRUE ))
     535                 :         {
     536               2 :             delete $2;
     537                 :             delete $4;
     538                 :         YYERROR;
     539               5 :         }
     540                 : 
     541               0 :     delete $4;
     542               0 :       }
     543               0 : 
     544                 :   | value_expr SWQT_AS string_or_identifier
     545               5 :       {
     546                 :     if( !context->poSelect->PushField( $1, $3->string_value ) )
     547               5 :         {
     548                 :             delete $1;
     549                 :             delete $3;
     550              94 :         YYERROR;
     551              94 :         }
     552              94 :     delete $3;
     553              94 :       }
     554                 : 
     555              94 :         | '*'
     556                 :       {
     557               0 :           swq_expr_node *poNode = new swq_expr_node();
     558               0 :     poNode->eNodeType = SNT_COLUMN;
     559                 :     poNode->string_value = CPLStrdup( "*" );
     560                 :     poNode->table_index = poNode->field_index = -1;
     561              94 : 
     562                 :     if( !context->poSelect->PushField( poNode ) )
     563                 :         {
     564              10 :             delete poNode;
     565                 :         YYERROR;
     566              10 :         }
     567              10 :       }
     568                 :     
     569              10 :         | SWQT_IDENTIFIER '.' '*'
     570              10 :       {
     571                 :                 CPLString osQualifiedField;
     572              10 : 
     573              10 :                 osQualifiedField = $1->string_value;
     574              20 :                 osQualifiedField += ".*";
     575              10 : 
     576                 :                 delete $1;
     577              10 :                 $1 = NULL;
     578                 : 
     579               0 :           swq_expr_node *poNode = new swq_expr_node();
     580                 :     poNode->eNodeType = SNT_COLUMN;
     581                 :     poNode->string_value = CPLStrdup( osQualifiedField );
     582               0 :     poNode->table_index = poNode->field_index = -1;
     583              10 : 
     584                 :     if( !context->poSelect->PushField( poNode ) )
     585                 :         {
     586                 :             delete poNode;
     587              79 :         YYERROR;
     588                 :         }
     589                 :       }
     590                 :     
     591               1 :         | SWQT_IDENTIFIER '(' '*' ')'
     592               1 :       {
     593               1 :           // special case for COUNT(*), confirm it.
     594                 :     if( !EQUAL($1->string_value,"COUNT") )
     595                 :     {
     596              78 :         CPLError( CE_Failure, CPLE_AppDefined,
     597              78 :                 "Syntax Error with %s(*).", 
     598                 :             $1->string_value );
     599              78 :             delete $1;
     600              78 :               YYERROR;
     601              78 :     }
     602              78 : 
     603                 :         delete $1;
     604             156 :         $1 = NULL;
     605              78 :                 
     606                 :     swq_expr_node *poNode = new swq_expr_node();
     607              78 :     poNode->eNodeType = SNT_COLUMN;
     608                 :     poNode->string_value = CPLStrdup( "*" );
     609               0 :     poNode->table_index = poNode->field_index = -1;
     610               0 : 
     611                 :     swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
     612                 :     count->PushSubExpression( poNode );
     613              78 : 
     614                 :     if( !context->poSelect->PushField( count ) )
     615                 :         {
     616                 :             delete count;
     617               2 :         YYERROR;
     618                 :         }
     619                 :       }
     620                 : 
     621               1 :         | SWQT_IDENTIFIER '(' '*' ')' SWQT_AS string_or_identifier
     622               1 :       {
     623               1 :           // special case for COUNT(*), confirm it.
     624               1 :     if( !EQUAL($1->string_value,"COUNT") )
     625                 :     {
     626                 :         CPLError( CE_Failure, CPLE_AppDefined,
     627               1 :                 "Syntax Error with %s(*).", 
     628               1 :             $1->string_value );
     629                 :             delete $1;
     630               1 :             delete $6;
     631               1 :               YYERROR;
     632               1 :     }
     633               1 : 
     634                 :         delete $1;
     635               2 :         $1 = NULL;
     636               1 : 
     637                 :     swq_expr_node *poNode = new swq_expr_node();
     638               1 :     poNode->eNodeType = SNT_COLUMN;
     639                 :     poNode->string_value = CPLStrdup( "*" );
     640               0 :     poNode->table_index = poNode->field_index = -1;
     641               0 : 
     642               0 :     swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
     643                 :     count->PushSubExpression( poNode );
     644                 : 
     645               1 :     if( !context->poSelect->PushField( count, $6->string_value ) )
     646                 :         {
     647               1 :             delete count;
     648                 :             delete $6;
     649                 :         YYERROR;
     650                 :         }
     651               6 : 
     652                 :                 delete $6;
     653                 :       }
     654               1 : 
     655               1 :   | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')'
     656               1 :       {
     657               1 :           // special case for COUNT(DISTINCT x), confirm it.
     658                 :     if( !EQUAL($1->string_value,"COUNT") )
     659                 :     {
     660               5 :         CPLError( CE_Failure, CPLE_AppDefined,
     661                 :                 "DISTINCT keyword can only be used in COUNT() operator." );
     662               5 :             delete $1;
     663               5 :             delete $4;
     664                 :               YYERROR;
     665               5 :     }
     666                 : 
     667               0 :                 delete $1;
     668               0 :                 
     669                 :                 swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
     670                 :                 count->PushSubExpression( $4 );
     671               5 :                 
     672                 :     if( !context->poSelect->PushField( count, NULL, TRUE ) )
     673                 :         {
     674                 :             delete count;
     675               2 :         YYERROR;
     676                 :         }
     677                 :       }
     678               1 : 
     679               1 :   | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' SWQT_AS string_or_identifier
     680               1 :       {
     681               1 :           // special case for COUNT(DISTINCT x), confirm it.
     682               1 :     if( !EQUAL($1->string_value,"COUNT") )
     683                 :     {
     684                 :         CPLError( CE_Failure, CPLE_AppDefined,
     685               1 :                 "DISTINCT keyword can only be used in COUNT() operator." );
     686               1 :             delete $1;
     687                 :             delete $4;
     688               1 :             delete $7;
     689                 :               YYERROR;
     690               0 :     }
     691               0 : 
     692               0 :                 swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
     693               0 :                 count->PushSubExpression( $4 );
     694                 :                 
     695                 :     if( !context->poSelect->PushField( count, $7->string_value, TRUE ) )
     696               1 :         {
     697               1 :             delete $1;
     698                 :             delete count;
     699               1 :             delete $7;
     700                 :         YYERROR;
     701                 :         }
     702                 : 
     703              64 :                 delete $1;
     704                 :                 delete $7;
     705              64 :       }
     706                 : 
     707                 : opt_where:  
     708                 :   | SWQT_WHERE logical_expr
     709               0 :       {      
     710               0 :          context->poSelect->where_expr = $2;
     711               0 :       }
     712               0 : 
     713               0 : opt_joins:
     714               0 :         | SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
     715                 :       {
     716               0 :           context->poSelect->PushJoin( $2->int_value, 
     717                 :                $4->string_value, 
     718              21 :                $6->string_value );
     719              21 :                 delete $2;
     720              63 :           delete $4;
     721              21 :           delete $6;
     722              21 :       }
     723              21 :         | SWQT_LEFT SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
     724                 :       {
     725              21 :           context->poSelect->PushJoin( $3->int_value, 
     726                 :                $5->string_value, 
     727                 :                $7->string_value );
     728                 :                 delete $3;
     729                 :           delete $5;
     730                 :           delete $7;
     731                 :       }
     732                 : 
     733                 : opt_order_by:
     734                 :   | SWQT_ORDER SWQT_BY sort_spec_list
     735                 : 
     736               5 : sort_spec_list:
     737               5 :   sort_spec ',' sort_spec_list
     738               5 :   | sort_spec 
     739                 : 
     740               5 : sort_spec:
     741                 :   field_value
     742              11 :             {
     743              11 :                 context->poSelect->PushOrderBy( $1->string_value, TRUE );
     744              11 :                 delete $1;
     745                 :                 $1 = NULL;
     746              11 :             }
     747                 :   | field_value SWQT_ASC
     748               7 :             {
     749               7 :                 context->poSelect->PushOrderBy( $1->string_value, TRUE );
     750               7 :                 delete $1;
     751                 :                 $1 = NULL;
     752               7 :             }
     753                 :   | field_value SWQT_DESC
     754                 :             {
     755                 :                 context->poSelect->PushOrderBy( $1->string_value, FALSE );
     756             251 :                 delete $1;
     757                 :                 $1 = NULL;
     758             251 :             }
     759                 : 
     760              22 : string_or_identifier:
     761                 :         SWQT_IDENTIFIER
     762              22 :         {
     763                 :             $$ = $1;
     764                 :         }
     765                 :         | SWQT_STRING
     766                 :         {
     767             245 :             $$ = $1;
     768             245 :         }
     769             245 : 
     770                 : table_def:
     771             245 :   string_or_identifier
     772                 :   {
     773             245 :       int iTable;
     774                 :       iTable =context->poSelect->PushTableDef( NULL, $1->string_value, 
     775                 :                            NULL );
     776                 :       delete $1;
     777              12 : 
     778              24 :       $$ = new swq_expr_node( iTable );
     779              12 :   }
     780              12 : 
     781                 :   | string_or_identifier SWQT_IDENTIFIER
     782              12 :   {
     783                 :       int iTable;
     784              12 :       iTable = context->poSelect->PushTableDef( NULL, $1->string_value, 
     785                 :                       $2->string_value );
     786                 :       delete $1;
     787                 :       delete $2;
     788               1 : 
     789               2 :       $$ = new swq_expr_node( iTable );
     790               1 :   }
     791               1 : 
     792                 :   | SWQT_STRING '.' string_or_identifier
     793               1 :   {
     794                 :       int iTable;
     795               1 :       iTable = context->poSelect->PushTableDef( $1->string_value, 
     796                 :                       $3->string_value, NULL );
     797                 :       delete $1;
     798                 :       delete $3;
     799               4 : 
     800               4 :       $$ = new swq_expr_node( iTable );
     801              12 :   }
     802               4 : 
     803               4 :   | SWQT_STRING '.' string_or_identifier SWQT_IDENTIFIER
     804               4 :   {
     805                 :       int iTable;
     806               4 :       iTable = context->poSelect->PushTableDef( $1->string_value, 
     807                 :                           $3->string_value, 
     808                 :                       $4->string_value );
     809                 :       delete $1;
     810                 :       delete $3;
     811                 :       delete $4;
     812                 : 
     813                 :       $$ = new swq_expr_node( iTable );
     814                 :   }

Generated by: LCOV version 1.7