LCOV - code coverage report
Current view: directory - ogr - swq_parser.y (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 392 340 86.7 %
Date: 2012-04-28 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             170 : static void swqerror( swq_parse_context *context, const char *msg )
      46                 : {
      47                 :     CPLError( CE_Failure, CPLE_AppDefined, 
      48             170 :               "SQL Expression Parsing Error: %s", msg );
      49             170 : }
      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              52 : 
      90             138 : %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             982 : %destructor { delete $$; } logical_expr value_expr_list field_value value_expr type_def string_or_identifier table_def
      98                 : 
      99             982 : %%
     100                 : 
     101                 : input:  
     102               0 :   SWQT_LOGICAL_START logical_expr
     103                 :     {
     104               0 :       context->poRoot = $2;
     105                 :     }
     106                 : 
     107             720 :   | SWQT_VALUE_START value_expr
     108                 :     {
     109             720 :       context->poRoot = $2;
     110                 :     }
     111                 : 
     112                 :   | SWQT_SELECT_START select_statement
     113             476 :     {
     114             476 :       context->poRoot = $2;
     115             476 :     }
     116             476 : 
     117                 : logical_expr:
     118             476 :   logical_expr SWQT_AND logical_expr 
     119                 :          {
     120                 :       $$ = new swq_expr_node( SWQ_AND );
     121              12 :       $$->field_type = SWQ_BOOLEAN;
     122              12 :       $$->PushSubExpression( $1 );
     123              12 :       $$->PushSubExpression( $3 );
     124              12 :          }
     125                 : 
     126              12 :   | logical_expr SWQT_OR logical_expr
     127                 :          {
     128                 :       $$ = new swq_expr_node( SWQ_OR );
     129              16 :       $$->field_type = SWQ_BOOLEAN;
     130              16 :       $$->PushSubExpression( $1 );
     131              16 :       $$->PushSubExpression( $3 );
     132                 :          }
     133              16 : 
     134                 :   | SWQT_NOT logical_expr
     135                 :          {
     136             452 :       $$ = new swq_expr_node( SWQ_NOT );
     137                 :       $$->field_type = SWQ_BOOLEAN;
     138             452 :       $$->PushSubExpression( $2 );
     139                 :          }
     140                 : 
     141            1074 :   | '(' logical_expr ')'
     142            1074 :                {
     143            1074 :       $$ = $2;
     144            1074 :          }
     145                 : 
     146            1074 :   | value_expr '=' value_expr
     147                 :                {
     148                 :       $$ = new swq_expr_node( SWQ_EQ );
     149             184 :       $$->field_type = SWQ_BOOLEAN;
     150             184 :       $$->PushSubExpression( $1 );
     151             184 :       $$->PushSubExpression( $3 );
     152             184 :          }
     153                 : 
     154             184 :   | value_expr '<' '>' value_expr
     155                 :                {
     156                 :       $$ = new swq_expr_node( SWQ_NE );
     157               8 :       $$->field_type = SWQ_BOOLEAN;
     158               8 :       $$->PushSubExpression( $1 );
     159               8 :       $$->PushSubExpression( $4 );
     160               8 :          }
     161                 : 
     162               8 :   | value_expr '!' '=' value_expr
     163                 :                {
     164                 :       $$ = new swq_expr_node( SWQ_NE );
     165             122 :       $$->field_type = SWQ_BOOLEAN;
     166             122 :       $$->PushSubExpression( $1 );
     167             122 :       $$->PushSubExpression( $4 );
     168             122 :          }
     169                 : 
     170             122 :   | value_expr '<' value_expr
     171                 :                {
     172                 :       $$ = new swq_expr_node( SWQ_LT );
     173             132 :       $$->field_type = SWQ_BOOLEAN;
     174             132 :       $$->PushSubExpression( $1 );
     175             132 :       $$->PushSubExpression( $3 );
     176             132 :          }
     177                 : 
     178             132 :   | value_expr '>' value_expr
     179                 :                {
     180                 :       $$ = new swq_expr_node( SWQ_GT );
     181              64 :       $$->field_type = SWQ_BOOLEAN;
     182              64 :       $$->PushSubExpression( $1 );
     183              64 :       $$->PushSubExpression( $3 );
     184              64 :          }
     185                 : 
     186              64 :   | 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              64 :       $$->field_type = SWQ_BOOLEAN;
     206              64 :       $$->PushSubExpression( $1 );
     207              64 :       $$->PushSubExpression( $4 );
     208              64 :          }
     209                 : 
     210              64 :   | value_expr '>' '=' value_expr
     211                 :                {
     212                 :       $$ = new swq_expr_node( SWQ_GE );
     213              16 :       $$->field_type = SWQ_BOOLEAN;
     214              16 :       $$->PushSubExpression( $1 );
     215              16 :       $$->PushSubExpression( $4 );
     216              16 :          }
     217                 : 
     218              16 :   | value_expr SWQT_LIKE value_expr
     219                 :                {
     220                 :       $$ = new swq_expr_node( SWQ_LIKE );
     221                 :       $$->field_type = SWQ_BOOLEAN;
     222               2 :       $$->PushSubExpression( $1 );
     223               2 :       $$->PushSubExpression( $3 );
     224               2 :          }
     225               2 : 
     226                 :   | value_expr SWQT_NOT SWQT_LIKE value_expr
     227               4 :                {
     228               2 :             swq_expr_node *like;
     229               2 :       like = new swq_expr_node( SWQ_LIKE );
     230                 :       like->field_type = SWQ_BOOLEAN;
     231               2 :       like->PushSubExpression( $1 );
     232                 :       like->PushSubExpression( $4 );
     233                 : 
     234               4 :       $$ = new swq_expr_node( SWQ_NOT );
     235               4 :       $$->field_type = SWQ_BOOLEAN;
     236               4 :       $$->PushSubExpression( like );
     237               4 :          }
     238               4 : 
     239                 :     | value_expr SWQT_LIKE value_expr SWQT_ESCAPE value_expr
     240               4 :       {
     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              82 :             $$ = new swq_expr_node( SWQ_NOT );
     258              82 :             $$->field_type = SWQ_BOOLEAN;
     259              82 :             $$->PushSubExpression( like );
     260              82 :       }
     261              82 : 
     262                 :   | value_expr SWQT_IN '(' value_expr_list ')'
     263              82 :                {
     264                 :       $$ = $4;
     265                 :       $$->field_type = SWQ_BOOLEAN;
     266                 :       $$->nOperation = SWQ_IN;
     267                 :       $$->PushSubExpression( $1 );
     268               2 :       $$->ReverseSubExpressions();
     269               2 :          }
     270               2 : 
     271               2 :   | value_expr SWQT_NOT SWQT_IN '(' value_expr_list ')'
     272               2 :                {
     273                 :             swq_expr_node *in;
     274               2 : 
     275               2 :       in = $5;
     276               2 :       in->field_type = SWQ_BOOLEAN;
     277                 :       in->nOperation = SWQ_IN;
     278               2 :       in->PushSubExpression( $1 );
     279                 :       in->ReverseSubExpressions();
     280                 :       
     281              66 :       $$ = new swq_expr_node( SWQ_NOT );
     282              66 :       $$->field_type = SWQ_BOOLEAN;
     283              66 :       $$->PushSubExpression( in );
     284              66 :          }
     285              66 : 
     286                 :     | value_expr SWQT_BETWEEN value_expr SWQT_AND value_expr
     287              66 :                  {
     288                 :             $$ = new swq_expr_node( SWQ_BETWEEN );
     289                 :             $$->field_type = SWQ_BOOLEAN;
     290                 :             $$->PushSubExpression( $1 );
     291               2 :             $$->PushSubExpression( $3 );
     292               2 :             $$->PushSubExpression( $5 );
     293               2 :              }
     294               2 : 
     295               2 :     | value_expr SWQT_NOT SWQT_BETWEEN value_expr SWQT_AND value_expr
     296                 :                  {
     297               4 :             swq_expr_node *between;
     298               2 :             between = new swq_expr_node( SWQ_BETWEEN );
     299               2 :             between->field_type = SWQ_BOOLEAN;
     300                 :             between->PushSubExpression( $1 );
     301               2 :             between->PushSubExpression( $4 );
     302                 :             between->PushSubExpression( $6 );
     303                 : 
     304              14 :             $$ = new swq_expr_node( SWQ_NOT );
     305              14 :             $$->field_type = SWQ_BOOLEAN;
     306              14 :             $$->PushSubExpression( between );
     307                 :              }
     308              14 : 
     309                 :   | value_expr SWQT_IS SWQT_NULL
     310                 :                {
     311                 :       $$ = new swq_expr_node( SWQ_ISNULL );
     312                 :       $$->field_type = SWQ_BOOLEAN;
     313               4 :       $$->PushSubExpression( $1 );
     314               4 :          }
     315               4 : 
     316                 :   | value_expr SWQT_IS SWQT_NOT SWQT_NULL
     317               8 :                {
     318               4 :             swq_expr_node *isnull;
     319               4 : 
     320                 :       isnull = new swq_expr_node( SWQ_ISNULL );
     321               4 :       isnull->field_type = SWQ_BOOLEAN;
     322                 :       isnull->PushSubExpression( $1 );
     323                 : 
     324                 :       $$ = new swq_expr_node( SWQ_NOT );
     325              80 :       $$->field_type = SWQ_BOOLEAN;
     326              80 :       $$->PushSubExpression( isnull );
     327                 :          }
     328              80 : 
     329                 : value_expr_list:
     330                 :   value_expr ',' value_expr_list
     331             154 :     {
     332             154 :       $$ = $3;
     333                 :       $3->PushSubExpression( $1 );
     334             154 :     }
     335                 : 
     336                 :   | value_expr
     337                 :           {
     338            3796 :       $$ = new swq_expr_node( SWQ_UNKNOWN ); /* list */
     339            3796 :       $$->PushSubExpression( $1 );
     340            3796 :     }
     341                 : 
     342            3796 : field_value:
     343                 :   SWQT_IDENTIFIER
     344                 :     {
     345             114 :             $$ = $1;  // validation deferred.
     346             114 :       $$->eNodeType = SNT_COLUMN;
     347             114 :       $$->field_index = $$->table_index = -1;
     348                 :     }
     349                 : 
     350                 :   | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
     351             114 :     {
     352             114 :             $$ = $1;  // validation deferred.
     353             114 :       $$->eNodeType = SNT_COLUMN;
     354             114 :       $$->field_index = $$->table_index = -1;
     355             114 :       $$->string_value = (char *) 
     356                 :                             CPLRealloc( $$->string_value, 
     357             114 :                                         strlen($$->string_value) 
     358                 :                                         + strlen($3->string_value) + 2 );
     359                 :       strcat( $$->string_value, "." );
     360                 :       strcat( $$->string_value, $3->string_value );
     361            1886 :       delete $3;
     362                 :       $3 = NULL;
     363            1886 :     }
     364                 : 
     365                 : value_expr:
     366             664 :   SWQT_NUMBER 
     367                 :           {
     368             664 :       $$ = $1;
     369                 :     }
     370            3708 : 
     371                 :   | SWQT_STRING
     372            3708 :     {
     373                 :       $$ = $1;
     374                 :     }
     375             126 :   | field_value
     376                 :     {
     377             126 :       $$ = $1;
     378                 :     }
     379                 : 
     380              10 :   | '(' value_expr ')'
     381                 :     {
     382              10 :       $$ = $2;
     383                 :     }
     384                 : 
     385              10 :     | SWQT_NULL
     386                 :         {
     387               8 :             $$ = new swq_expr_node((const char*)NULL);
     388               8 :         }
     389               8 : 
     390                 :     | '-' value_expr %prec SWQT_UMINUS
     391                 :         {
     392                 :             if ($2->eNodeType == SNT_CONSTANT)
     393               2 :             {
     394               4 :                 $$ = $2;
     395               2 :                 $$->int_value *= -1;
     396                 :                 $$->float_value *= -1;
     397                 :             }
     398              10 :             else
     399                 :             {
     400                 :                 $$ = new swq_expr_node( SWQ_MULTIPLY );
     401              22 :                 $$->PushSubExpression( new swq_expr_node(-1) );
     402              22 :                 $$->PushSubExpression( $2 );
     403              22 :             }
     404                 :         }
     405              22 : 
     406                 :   | value_expr '+' value_expr
     407                 :     {
     408              14 :       $$ = new swq_expr_node( SWQ_ADD );
     409              14 :       $$->PushSubExpression( $1 );
     410              14 :       $$->PushSubExpression( $3 );
     411                 :     }
     412              14 : 
     413                 :   | value_expr '-' value_expr
     414                 :     {
     415              14 :       $$ = new swq_expr_node( SWQ_SUBTRACT );
     416              14 :       $$->PushSubExpression( $1 );
     417              14 :       $$->PushSubExpression( $3 );
     418                 :     }
     419              14 : 
     420                 :   | value_expr '*' value_expr
     421                 :     {
     422              16 :       $$ = new swq_expr_node( SWQ_MULTIPLY );
     423              16 :       $$->PushSubExpression( $1 );
     424              16 :       $$->PushSubExpression( $3 );
     425                 :     }
     426              16 : 
     427                 :   | value_expr '/' value_expr
     428                 :     {
     429              12 :       $$ = new swq_expr_node( SWQ_DIVIDE );
     430              12 :       $$->PushSubExpression( $1 );
     431              12 :       $$->PushSubExpression( $3 );
     432                 :     }
     433              12 : 
     434                 :   | value_expr '%' value_expr
     435                 :     {
     436                 :       $$ = new swq_expr_node( SWQ_MODULUS );
     437              64 :       $$->PushSubExpression( $1 );
     438                 :       $$->PushSubExpression( $3 );
     439              64 :     }
     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              64 :                                   $1->string_value );
     451              64 :                 delete $1;
     452              64 :                 delete $3;
     453              64 :             YYERROR;
     454              64 :         }
     455                 :         else
     456                 :         {
     457              64 :       $$ = $3;
     458                 :                         $$->eNodeType = SNT_OPERATION;
     459                 :                         $$->nOperation = poOp->eOperation;
     460              66 :       $$->ReverseSubExpressions();
     461              66 :       delete $1;
     462              66 :         }
     463                 :     }
     464              66 : 
     465                 :   | SWQT_CAST '(' value_expr SWQT_AS type_def ')'
     466                 :           {
     467                 :         $$ = $5;
     468              58 :         $$->PushSubExpression( $3 );
     469              58 :         $$->ReverseSubExpressions();
     470                 :     }
     471              58 :     
     472                 : type_def:
     473                 :   SWQT_IDENTIFIER
     474              12 :   {
     475              12 :       $$ = new swq_expr_node( SWQ_CAST );
     476              12 :       $$->PushSubExpression( $1 );
     477                 :   }
     478              12 : 
     479                 :   | SWQT_IDENTIFIER '(' SWQT_NUMBER ')' 
     480                 :   {
     481               2 :       $$ = new swq_expr_node( SWQ_CAST );
     482               2 :       $$->PushSubExpression( $3 );
     483               2 :       $$->PushSubExpression( $1 );
     484               2 :   }
     485                 : 
     486               2 :   | SWQT_IDENTIFIER '(' SWQT_NUMBER ',' SWQT_NUMBER ')' 
     487                 :   {
     488                 :       $$ = new swq_expr_node( SWQ_CAST );
     489                 :       $$->PushSubExpression( $5 );
     490             720 :       $$->PushSubExpression( $3 );
     491                 :       $$->PushSubExpression( $1 );
     492             720 :   }
     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              36 : select_field_list:
     501                 :   column_spec
     502               0 :   | column_spec ',' select_field_list
     503               0 : 
     504                 : column_spec: 
     505                 :    SWQT_DISTINCT field_value
     506              36 :       {
     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            2292 :             delete $2;
     519                 :             YYERROR;
     520              10 :         }
     521              10 :         }
     522                 : 
     523                 :     | value_expr
     524            2282 :       {
     525                 :     if( !context->poSelect->PushField( $1 ) )
     526                 :         {
     527               4 :             delete $1;
     528                 :         YYERROR;
     529               0 :         }
     530               0 :       }
     531               0 : 
     532                 :   | SWQT_DISTINCT field_value SWQT_AS string_or_identifier
     533                 :       {
     534               4 :     if( !context->poSelect->PushField( $2, $4->string_value, TRUE ))
     535                 :         {
     536               4 :             delete $2;
     537                 :             delete $4;
     538                 :         YYERROR;
     539              10 :         }
     540                 : 
     541               0 :     delete $4;
     542               0 :       }
     543               0 : 
     544                 :   | value_expr SWQT_AS string_or_identifier
     545              10 :       {
     546                 :     if( !context->poSelect->PushField( $1, $3->string_value ) )
     547              10 :         {
     548                 :             delete $1;
     549                 :             delete $3;
     550             392 :         YYERROR;
     551             392 :         }
     552             392 :     delete $3;
     553             392 :       }
     554                 : 
     555             392 :         | '*'
     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             392 : 
     562                 :     if( !context->poSelect->PushField( poNode ) )
     563                 :         {
     564              20 :             delete poNode;
     565                 :         YYERROR;
     566              20 :         }
     567              20 :       }
     568                 :     
     569              20 :         | SWQT_IDENTIFIER '.' '*'
     570              20 :       {
     571                 :                 CPLString osQualifiedField;
     572              20 : 
     573              20 :                 osQualifiedField = $1->string_value;
     574              40 :                 osQualifiedField += ".*";
     575              20 : 
     576                 :                 delete $1;
     577              20 :                 $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              20 : 
     584                 :     if( !context->poSelect->PushField( poNode ) )
     585                 :         {
     586                 :             delete poNode;
     587             196 :         YYERROR;
     588                 :         }
     589                 :       }
     590                 :     
     591               2 :         | SWQT_IDENTIFIER '(' '*' ')'
     592               2 :       {
     593               2 :           // special case for COUNT(*), confirm it.
     594                 :     if( !EQUAL($1->string_value,"COUNT") )
     595                 :     {
     596             194 :         CPLError( CE_Failure, CPLE_AppDefined,
     597             194 :                 "Syntax Error with %s(*).", 
     598                 :             $1->string_value );
     599             194 :             delete $1;
     600             194 :               YYERROR;
     601             194 :     }
     602             194 : 
     603                 :         delete $1;
     604             388 :         $1 = NULL;
     605             194 :                 
     606                 :     swq_expr_node *poNode = new swq_expr_node();
     607             194 :     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             194 : 
     614                 :     if( !context->poSelect->PushField( count ) )
     615                 :         {
     616                 :             delete count;
     617               4 :         YYERROR;
     618                 :         }
     619                 :       }
     620                 : 
     621               2 :         | SWQT_IDENTIFIER '(' '*' ')' SWQT_AS string_or_identifier
     622               2 :       {
     623               2 :           // special case for COUNT(*), confirm it.
     624               2 :     if( !EQUAL($1->string_value,"COUNT") )
     625                 :     {
     626                 :         CPLError( CE_Failure, CPLE_AppDefined,
     627               2 :                 "Syntax Error with %s(*).", 
     628               2 :             $1->string_value );
     629                 :             delete $1;
     630               2 :             delete $6;
     631               2 :               YYERROR;
     632               2 :     }
     633               2 : 
     634                 :         delete $1;
     635               4 :         $1 = NULL;
     636               2 : 
     637                 :     swq_expr_node *poNode = new swq_expr_node();
     638               2 :     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               2 :     if( !context->poSelect->PushField( count, $6->string_value ) )
     646                 :         {
     647               2 :             delete count;
     648                 :             delete $6;
     649                 :         YYERROR;
     650                 :         }
     651              12 : 
     652                 :                 delete $6;
     653                 :       }
     654               2 : 
     655               2 :   | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')'
     656               2 :       {
     657               2 :           // special case for COUNT(DISTINCT x), confirm it.
     658                 :     if( !EQUAL($1->string_value,"COUNT") )
     659                 :     {
     660              10 :         CPLError( CE_Failure, CPLE_AppDefined,
     661                 :                 "DISTINCT keyword can only be used in COUNT() operator." );
     662              10 :             delete $1;
     663              10 :             delete $4;
     664                 :               YYERROR;
     665              10 :     }
     666                 : 
     667               0 :                 delete $1;
     668               0 :                 
     669                 :                 swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
     670                 :                 count->PushSubExpression( $4 );
     671              10 :                 
     672                 :     if( !context->poSelect->PushField( count, NULL, TRUE ) )
     673                 :         {
     674                 :             delete count;
     675               4 :         YYERROR;
     676                 :         }
     677                 :       }
     678               2 : 
     679               2 :   | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' SWQT_AS string_or_identifier
     680               2 :       {
     681               2 :           // special case for COUNT(DISTINCT x), confirm it.
     682               2 :     if( !EQUAL($1->string_value,"COUNT") )
     683                 :     {
     684                 :         CPLError( CE_Failure, CPLE_AppDefined,
     685               2 :                 "DISTINCT keyword can only be used in COUNT() operator." );
     686               2 :             delete $1;
     687                 :             delete $4;
     688               2 :             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               2 :         {
     697               2 :             delete $1;
     698                 :             delete count;
     699               2 :             delete $7;
     700                 :         YYERROR;
     701                 :         }
     702                 : 
     703             366 :                 delete $1;
     704                 :                 delete $7;
     705             366 :       }
     706                 : 
     707                 : opt_where:  
     708                 :   | SWQT_WHERE logical_expr
     709               4 :       {      
     710               4 :          context->poSelect->where_expr = $2;
     711              12 :       }
     712               4 : 
     713               4 : opt_joins:
     714               4 :         | SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
     715                 :       {
     716               4 :           context->poSelect->PushJoin( $2->int_value, 
     717                 :                $4->string_value, 
     718              42 :                $6->string_value );
     719              42 :                 delete $2;
     720             126 :           delete $4;
     721              42 :           delete $6;
     722              42 :       }
     723              42 :         | SWQT_LEFT SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
     724                 :       {
     725              42 :           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              10 : sort_spec_list:
     737              10 :   sort_spec ',' sort_spec_list
     738              10 :   | sort_spec 
     739                 : 
     740              10 : sort_spec:
     741                 :   field_value
     742              22 :             {
     743              22 :                 context->poSelect->PushOrderBy( $1->string_value, TRUE );
     744              22 :                 delete $1;
     745                 :                 $1 = NULL;
     746              22 :             }
     747                 :   | field_value SWQT_ASC
     748              18 :             {
     749              18 :                 context->poSelect->PushOrderBy( $1->string_value, TRUE );
     750              18 :                 delete $1;
     751                 :                 $1 = NULL;
     752              18 :             }
     753                 :   | field_value SWQT_DESC
     754                 :             {
     755                 :                 context->poSelect->PushOrderBy( $1->string_value, FALSE );
     756             790 :                 delete $1;
     757                 :                 $1 = NULL;
     758             790 :             }
     759                 : 
     760              48 : string_or_identifier:
     761                 :         SWQT_IDENTIFIER
     762              48 :         {
     763                 :             $$ = $1;
     764                 :         }
     765                 :         | SWQT_STRING
     766                 :         {
     767             782 :             $$ = $1;
     768             782 :         }
     769             782 : 
     770                 : table_def:
     771             782 :   string_or_identifier
     772                 :   {
     773             782 :       int iTable;
     774                 :       iTable =context->poSelect->PushTableDef( NULL, $1->string_value, 
     775                 :                            NULL );
     776                 :       delete $1;
     777              24 : 
     778              48 :       $$ = new swq_expr_node( iTable );
     779              24 :   }
     780              24 : 
     781                 :   | string_or_identifier SWQT_IDENTIFIER
     782              24 :   {
     783                 :       int iTable;
     784              24 :       iTable = context->poSelect->PushTableDef( NULL, $1->string_value, 
     785                 :                       $2->string_value );
     786                 :       delete $1;
     787                 :       delete $2;
     788               2 : 
     789               4 :       $$ = new swq_expr_node( iTable );
     790               2 :   }
     791               2 : 
     792                 :   | SWQT_STRING '.' string_or_identifier
     793               2 :   {
     794                 :       int iTable;
     795               2 :       iTable = context->poSelect->PushTableDef( $1->string_value, 
     796                 :                       $3->string_value, NULL );
     797                 :       delete $1;
     798                 :       delete $3;
     799               8 : 
     800               8 :       $$ = new swq_expr_node( iTable );
     801              24 :   }
     802               8 : 
     803               8 :   | SWQT_STRING '.' string_or_identifier SWQT_IDENTIFIER
     804               8 :   {
     805                 :       int iTable;
     806               8 :       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