LCOV - code coverage report
Current view: directory - ogr - swq_parser.y (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 396 344 86.9 %
Date: 2012-12-26 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             112 : static void swqerror( swq_parse_context *context, const char *msg )
      46                 : {
      47                 :     CPLError( CE_Failure, CPLE_AppDefined, 
      48             112 :               "SQL Expression Parsing Error: %s", msg );
      49             112 : }
      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                 : %token SWQT_UNION
      82                 : %token SWQT_ALL
      83                 : 
      84                 : %token SWQT_LOGICAL_START
      85                 : %token SWQT_VALUE_START
      86                 : %token SWQT_SELECT_START
      87                 : 
      88                 : %left SWQT_NOT
      89                 : %left SWQT_OR
      90                 : %left SWQT_AND
      91                 : 
      92                 : %left '+' '-'
      93                 : %left '*' '/' '%'
      94                 : %left SWQT_UMINUS
      95                 : 
      96                 : /* Any grammar rule that does $$ =  must be listed afterwards */
      97                 : /* as well as SWQT_NUMBER SWQT_STRING SWQT_IDENTIFIER that are allocated by swqlex() */
      98              47 : %destructor { delete $$; } SWQT_NUMBER SWQT_STRING SWQT_IDENTIFIER
      99              71 : %destructor { delete $$; } logical_expr value_expr_list field_value value_expr type_def string_or_identifier table_def
     100                 : 
     101                 : %%
     102                 : 
     103                 : input:  
     104                 :   SWQT_LOGICAL_START logical_expr
     105                 :     {
     106             849 :       context->poRoot = $2;
     107                 :     }
     108             849 : 
     109                 :   | SWQT_VALUE_START value_expr
     110                 :     {
     111               0 :       context->poRoot = $2;
     112                 :     }
     113               0 : 
     114                 :   | SWQT_SELECT_START select_statement
     115                 :     {
     116             496 :       context->poRoot = $2;
     117                 :     }
     118             496 : 
     119                 : logical_expr:
     120                 :   logical_expr SWQT_AND logical_expr 
     121                 :          {
     122             265 :       $$ = new swq_expr_node( SWQ_AND );
     123             265 :       $$->field_type = SWQ_BOOLEAN;
     124             265 :       $$->PushSubExpression( $1 );
     125             265 :       $$->PushSubExpression( $3 );
     126                 :          }
     127             265 : 
     128                 :   | logical_expr SWQT_OR logical_expr
     129                 :          {
     130              23 :       $$ = new swq_expr_node( SWQ_OR );
     131              23 :       $$->field_type = SWQ_BOOLEAN;
     132              23 :       $$->PushSubExpression( $1 );
     133              23 :       $$->PushSubExpression( $3 );
     134                 :          }
     135              23 : 
     136                 :   | SWQT_NOT logical_expr
     137                 :          {
     138              11 :       $$ = new swq_expr_node( SWQ_NOT );
     139              11 :       $$->field_type = SWQ_BOOLEAN;
     140              11 :       $$->PushSubExpression( $2 );
     141                 :          }
     142              11 : 
     143                 :   | '(' logical_expr ')'
     144                 :                {
     145             241 :       $$ = $2;
     146                 :          }
     147             241 : 
     148                 :   | value_expr '=' value_expr
     149                 :                {
     150             920 :       $$ = new swq_expr_node( SWQ_EQ );
     151             920 :       $$->field_type = SWQ_BOOLEAN;
     152             920 :       $$->PushSubExpression( $1 );
     153             920 :       $$->PushSubExpression( $3 );
     154                 :          }
     155             920 : 
     156                 :   | value_expr '<' '>' value_expr
     157                 :                {
     158             104 :       $$ = new swq_expr_node( SWQ_NE );
     159             104 :       $$->field_type = SWQ_BOOLEAN;
     160             104 :       $$->PushSubExpression( $1 );
     161             104 :       $$->PushSubExpression( $4 );
     162                 :          }
     163             104 : 
     164                 :   | value_expr '!' '=' value_expr
     165                 :                {
     166               6 :       $$ = new swq_expr_node( SWQ_NE );
     167               6 :       $$->field_type = SWQ_BOOLEAN;
     168               6 :       $$->PushSubExpression( $1 );
     169               6 :       $$->PushSubExpression( $4 );
     170                 :          }
     171               6 : 
     172                 :   | value_expr '<' value_expr
     173                 :                {
     174              89 :       $$ = new swq_expr_node( SWQ_LT );
     175              89 :       $$->field_type = SWQ_BOOLEAN;
     176              89 :       $$->PushSubExpression( $1 );
     177              89 :       $$->PushSubExpression( $3 );
     178                 :          }
     179              89 : 
     180                 :   | value_expr '>' value_expr
     181                 :                {
     182              95 :       $$ = new swq_expr_node( SWQ_GT );
     183              95 :       $$->field_type = SWQ_BOOLEAN;
     184              95 :       $$->PushSubExpression( $1 );
     185              95 :       $$->PushSubExpression( $3 );
     186                 :          }
     187              95 : 
     188                 :   | value_expr '<' '=' value_expr
     189                 :                {
     190              58 :       $$ = new swq_expr_node( SWQ_LE );
     191              58 :       $$->field_type = SWQ_BOOLEAN;
     192              58 :       $$->PushSubExpression( $1 );
     193              58 :       $$->PushSubExpression( $4 );
     194                 :          }
     195              58 : 
     196                 :   | value_expr '=' '<' value_expr
     197                 :                {
     198               0 :       $$ = new swq_expr_node( SWQ_LE );
     199               0 :       $$->field_type = SWQ_BOOLEAN;
     200               0 :       $$->PushSubExpression( $1 );
     201               0 :       $$->PushSubExpression( $4 );
     202                 :          }
     203               0 : 
     204                 :   | value_expr '=' '>' value_expr
     205                 :                {
     206               0 :       $$ = new swq_expr_node( SWQ_LE );
     207               0 :       $$->field_type = SWQ_BOOLEAN;
     208               0 :       $$->PushSubExpression( $1 );
     209               0 :       $$->PushSubExpression( $4 );
     210                 :          }
     211               0 : 
     212                 :   | value_expr '>' '=' value_expr
     213                 :                {
     214              59 :       $$ = new swq_expr_node( SWQ_GE );
     215              59 :       $$->field_type = SWQ_BOOLEAN;
     216              59 :       $$->PushSubExpression( $1 );
     217              59 :       $$->PushSubExpression( $4 );
     218                 :          }
     219              59 : 
     220                 :   | value_expr SWQT_LIKE value_expr
     221                 :                {
     222               9 :       $$ = new swq_expr_node( SWQ_LIKE );
     223               9 :       $$->field_type = SWQ_BOOLEAN;
     224               9 :       $$->PushSubExpression( $1 );
     225               9 :       $$->PushSubExpression( $3 );
     226                 :          }
     227               9 : 
     228                 :   | value_expr SWQT_NOT SWQT_LIKE value_expr
     229                 :                {
     230                 :             swq_expr_node *like;
     231               1 :       like = new swq_expr_node( SWQ_LIKE );
     232               1 :       like->field_type = SWQ_BOOLEAN;
     233               1 :       like->PushSubExpression( $1 );
     234               1 :       like->PushSubExpression( $4 );
     235                 : 
     236               2 :       $$ = new swq_expr_node( SWQ_NOT );
     237               1 :       $$->field_type = SWQ_BOOLEAN;
     238               1 :       $$->PushSubExpression( like );
     239                 :          }
     240               1 : 
     241                 :     | value_expr SWQT_LIKE value_expr SWQT_ESCAPE value_expr
     242                 :       {
     243               2 :             $$ = new swq_expr_node( SWQ_LIKE );
     244               2 :             $$->field_type = SWQ_BOOLEAN;
     245               2 :             $$->PushSubExpression( $1 );
     246               2 :             $$->PushSubExpression( $3 );
     247               2 :             $$->PushSubExpression( $5 );
     248                 :        }
     249               2 : 
     250                 :     | value_expr SWQT_NOT SWQT_LIKE value_expr SWQT_ESCAPE value_expr
     251                 :       {
     252                 :                 swq_expr_node *like;
     253               0 :             like = new swq_expr_node( SWQ_LIKE );
     254               0 :             like->field_type = SWQ_BOOLEAN;
     255               0 :             like->PushSubExpression( $1 );
     256               0 :             like->PushSubExpression( $4 );
     257               0 :             like->PushSubExpression( $6 );
     258                 : 
     259               0 :             $$ = new swq_expr_node( SWQ_NOT );
     260               0 :             $$->field_type = SWQ_BOOLEAN;
     261               0 :             $$->PushSubExpression( like );
     262                 :       }
     263               0 : 
     264                 :   | value_expr SWQT_IN '(' value_expr_list ')'
     265                 :                {
     266              41 :       $$ = $4;
     267              41 :       $$->field_type = SWQ_BOOLEAN;
     268              41 :       $$->nOperation = SWQ_IN;
     269              41 :       $$->PushSubExpression( $1 );
     270              41 :       $$->ReverseSubExpressions();
     271                 :          }
     272              41 : 
     273                 :   | value_expr SWQT_NOT SWQT_IN '(' value_expr_list ')'
     274                 :                {
     275                 :             swq_expr_node *in;
     276                 : 
     277               1 :       in = $5;
     278               1 :       in->field_type = SWQ_BOOLEAN;
     279               1 :       in->nOperation = SWQ_IN;
     280               1 :       in->PushSubExpression( $1 );
     281               1 :       in->ReverseSubExpressions();
     282                 :       
     283               1 :       $$ = new swq_expr_node( SWQ_NOT );
     284               1 :       $$->field_type = SWQ_BOOLEAN;
     285               1 :       $$->PushSubExpression( in );
     286                 :          }
     287               1 : 
     288                 :     | value_expr SWQT_BETWEEN value_expr SWQT_AND value_expr
     289                 :                  {
     290              33 :             $$ = new swq_expr_node( SWQ_BETWEEN );
     291              33 :             $$->field_type = SWQ_BOOLEAN;
     292              33 :             $$->PushSubExpression( $1 );
     293              33 :             $$->PushSubExpression( $3 );
     294              33 :             $$->PushSubExpression( $5 );
     295                 :              }
     296              33 : 
     297                 :     | value_expr SWQT_NOT SWQT_BETWEEN value_expr SWQT_AND value_expr
     298                 :                  {
     299                 :             swq_expr_node *between;
     300               1 :             between = new swq_expr_node( SWQ_BETWEEN );
     301               1 :             between->field_type = SWQ_BOOLEAN;
     302               1 :             between->PushSubExpression( $1 );
     303               1 :             between->PushSubExpression( $4 );
     304               1 :             between->PushSubExpression( $6 );
     305                 : 
     306               2 :             $$ = new swq_expr_node( SWQ_NOT );
     307               1 :             $$->field_type = SWQ_BOOLEAN;
     308               1 :             $$->PushSubExpression( between );
     309                 :              }
     310               1 : 
     311                 :   | value_expr SWQT_IS SWQT_NULL
     312                 :                {
     313              14 :       $$ = new swq_expr_node( SWQ_ISNULL );
     314              14 :       $$->field_type = SWQ_BOOLEAN;
     315              14 :       $$->PushSubExpression( $1 );
     316                 :          }
     317              14 : 
     318                 :   | value_expr SWQT_IS SWQT_NOT SWQT_NULL
     319                 :                {
     320                 :             swq_expr_node *isnull;
     321                 : 
     322               6 :       isnull = new swq_expr_node( SWQ_ISNULL );
     323               6 :       isnull->field_type = SWQ_BOOLEAN;
     324               6 :       isnull->PushSubExpression( $1 );
     325                 : 
     326              12 :       $$ = new swq_expr_node( SWQ_NOT );
     327               6 :       $$->field_type = SWQ_BOOLEAN;
     328               6 :       $$->PushSubExpression( isnull );
     329                 :          }
     330               6 : 
     331                 : value_expr_list:
     332                 :   value_expr ',' value_expr_list
     333                 :     {
     334              42 :       $$ = $3;
     335              42 :       $3->PushSubExpression( $1 );
     336                 :     }
     337              42 : 
     338                 :   | value_expr
     339                 :           {
     340              79 :       $$ = new swq_expr_node( SWQ_UNKNOWN ); /* list */
     341              79 :       $$->PushSubExpression( $1 );
     342                 :     }
     343              79 : 
     344                 : field_value:
     345                 :   SWQT_IDENTIFIER
     346                 :     {
     347            2233 :             $$ = $1;  // validation deferred.
     348            2233 :       $$->eNodeType = SNT_COLUMN;
     349            2233 :       $$->field_index = $$->table_index = -1;
     350                 :     }
     351            2233 : 
     352                 :   | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
     353                 :     {
     354              57 :             $$ = $1;  // validation deferred.
     355              57 :       $$->eNodeType = SNT_COLUMN;
     356              57 :       $$->field_index = $$->table_index = -1;
     357                 :       $$->string_value = (char *) 
     358                 :                             CPLRealloc( $$->string_value, 
     359                 :                                         strlen($$->string_value) 
     360              57 :                                         + strlen($3->string_value) + 2 );
     361              57 :       strcat( $$->string_value, "." );
     362              57 :       strcat( $$->string_value, $3->string_value );
     363              57 :       delete $3;
     364              57 :       $3 = NULL;
     365                 :     }
     366              57 : 
     367                 : value_expr:
     368                 :   SWQT_NUMBER 
     369                 :           {
     370            1537 :       $$ = $1;
     371                 :     }
     372            1537 : 
     373                 :   | SWQT_STRING
     374                 :     {
     375             433 :       $$ = $1;
     376                 :     }
     377             433 :   | field_value
     378                 :     {
     379            2188 :       $$ = $1;
     380                 :     }
     381            2188 : 
     382                 :   | '(' value_expr ')'
     383                 :     {
     384              73 :       $$ = $2;
     385                 :     }
     386              73 : 
     387                 :     | SWQT_NULL
     388                 :         {
     389              15 :             $$ = new swq_expr_node((const char*)NULL);
     390                 :         }
     391              15 : 
     392                 :     | '-' value_expr %prec SWQT_UMINUS
     393                 :         {
     394               5 :             if ($2->eNodeType == SNT_CONSTANT)
     395                 :             {
     396               4 :                 $$ = $2;
     397               4 :                 $$->int_value *= -1;
     398               4 :                 $$->float_value *= -1;
     399                 :             }
     400                 :             else
     401                 :             {
     402               1 :                 $$ = new swq_expr_node( SWQ_MULTIPLY );
     403               2 :                 $$->PushSubExpression( new swq_expr_node(-1) );
     404               1 :                 $$->PushSubExpression( $2 );
     405                 :             }
     406                 :         }
     407               5 : 
     408                 :   | value_expr '+' value_expr
     409                 :     {
     410              19 :       $$ = new swq_expr_node( SWQ_ADD );
     411              19 :       $$->PushSubExpression( $1 );
     412              19 :       $$->PushSubExpression( $3 );
     413                 :     }
     414              19 : 
     415                 :   | value_expr '-' value_expr
     416                 :     {
     417               7 :       $$ = new swq_expr_node( SWQ_SUBTRACT );
     418               7 :       $$->PushSubExpression( $1 );
     419               7 :       $$->PushSubExpression( $3 );
     420                 :     }
     421               7 : 
     422                 :   | value_expr '*' value_expr
     423                 :     {
     424               7 :       $$ = new swq_expr_node( SWQ_MULTIPLY );
     425               7 :       $$->PushSubExpression( $1 );
     426               7 :       $$->PushSubExpression( $3 );
     427                 :     }
     428               7 : 
     429                 :   | value_expr '/' value_expr
     430                 :     {
     431               8 :       $$ = new swq_expr_node( SWQ_DIVIDE );
     432               8 :       $$->PushSubExpression( $1 );
     433               8 :       $$->PushSubExpression( $3 );
     434                 :     }
     435               8 : 
     436                 :   | value_expr '%' value_expr
     437                 :     {
     438               6 :       $$ = new swq_expr_node( SWQ_MODULUS );
     439               6 :       $$->PushSubExpression( $1 );
     440               6 :       $$->PushSubExpression( $3 );
     441                 :     }
     442               6 : 
     443                 :   | SWQT_IDENTIFIER '(' value_expr_list ')'
     444                 :     {
     445                 :         const swq_operation *poOp = 
     446              34 :                       swq_op_registrar::GetOperator( $1->string_value );
     447                 : 
     448              34 :         if( poOp == NULL )
     449                 :         {
     450                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     451                 :                                   "Undefined function '%s' used.",
     452               0 :                                   $1->string_value );
     453               0 :                 delete $1;
     454               0 :                 delete $3;
     455               0 :             YYERROR;
     456                 :         }
     457                 :         else
     458                 :         {
     459              34 :       $$ = $3;
     460              34 :                         $$->eNodeType = SNT_OPERATION;
     461              34 :                         $$->nOperation = poOp->eOperation;
     462              34 :       $$->ReverseSubExpressions();
     463              34 :       delete $1;
     464                 :         }
     465                 :     }
     466              34 : 
     467                 :   | SWQT_CAST '(' value_expr SWQT_AS type_def ')'
     468                 :           {
     469              43 :         $$ = $5;
     470              43 :         $$->PushSubExpression( $3 );
     471              43 :         $$->ReverseSubExpressions();
     472                 :     }
     473              43 :     
     474                 : type_def:
     475                 :   SWQT_IDENTIFIER
     476                 :   {
     477              37 :       $$ = new swq_expr_node( SWQ_CAST );
     478              37 :       $$->PushSubExpression( $1 );
     479                 :   }
     480              37 : 
     481                 :   | SWQT_IDENTIFIER '(' SWQT_NUMBER ')' 
     482                 :   {
     483               8 :       $$ = new swq_expr_node( SWQ_CAST );
     484               8 :       $$->PushSubExpression( $3 );
     485               8 :       $$->PushSubExpression( $1 );
     486                 :   }
     487               8 : 
     488                 :   | SWQT_IDENTIFIER '(' SWQT_NUMBER ',' SWQT_NUMBER ')' 
     489                 :   {
     490               1 :       $$ = new swq_expr_node( SWQ_CAST );
     491               1 :       $$->PushSubExpression( $5 );
     492               1 :       $$->PushSubExpression( $3 );
     493               1 :       $$->PushSubExpression( $1 );
     494                 :   }
     495               1 : 
     496                 : select_statement: 
     497                 :   select_core opt_union_all
     498                 :     | '(' select_core ')' opt_union_all
     499                 : 
     500                 : select_core:
     501                 :     SWQT_SELECT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by
     502                 :     {
     503             503 :         delete $4;
     504                 :     }
     505             503 : 
     506                 : opt_union_all:
     507                 :     | union_all select_statement
     508                 : 
     509                 : union_all: SWQT_UNION SWQT_ALL
     510                 :     {
     511               6 :         swq_select* poNewSelect = new swq_select();
     512               6 :         context->poCurSelect->PushUnionAll(poNewSelect);
     513               6 :         context->poCurSelect = poNewSelect;
     514                 :     }
     515               6 : 
     516                 : select_field_list:
     517                 :   column_spec
     518                 :   | column_spec ',' select_field_list
     519                 : 
     520                 : column_spec: 
     521                 :    SWQT_DISTINCT field_value
     522                 :       {
     523              18 :     if( !context->poCurSelect->PushField( $2, NULL, TRUE ) )
     524                 :         {
     525               0 :             delete $2;
     526               0 :         YYERROR;
     527                 :         }
     528                 :       }
     529              18 : 
     530                 :     | SWQT_DISTINCT SWQT_STRING
     531                 :         {
     532               0 :         if( !context->poCurSelect->PushField( $2, NULL, TRUE ) )
     533                 :         {
     534               0 :             delete $2;
     535               0 :             YYERROR;
     536                 :         }
     537                 :         }
     538               0 : 
     539                 :     | value_expr
     540                 :       {
     541            1147 :     if( !context->poCurSelect->PushField( $1 ) )
     542                 :         {
     543               5 :             delete $1;
     544               5 :         YYERROR;
     545                 :         }
     546                 :       }
     547            1142 : 
     548                 :   | SWQT_DISTINCT field_value SWQT_AS string_or_identifier
     549                 :       {
     550               2 :     if( !context->poCurSelect->PushField( $2, $4->string_value, TRUE ))
     551                 :         {
     552               0 :             delete $2;
     553               0 :             delete $4;
     554               0 :         YYERROR;
     555                 :         }
     556                 : 
     557               2 :     delete $4;
     558                 :       }
     559               2 : 
     560                 :   | value_expr SWQT_AS string_or_identifier
     561                 :       {
     562               5 :     if( !context->poCurSelect->PushField( $1, $3->string_value ) )
     563                 :         {
     564               0 :             delete $1;
     565               0 :             delete $3;
     566               0 :         YYERROR;
     567                 :         }
     568               5 :     delete $3;
     569                 :       }
     570               5 : 
     571                 :         | '*'
     572                 :       {
     573             332 :           swq_expr_node *poNode = new swq_expr_node();
     574             332 :     poNode->eNodeType = SNT_COLUMN;
     575             332 :     poNode->string_value = CPLStrdup( "*" );
     576             332 :     poNode->table_index = poNode->field_index = -1;
     577                 : 
     578             332 :     if( !context->poCurSelect->PushField( poNode ) )
     579                 :         {
     580               0 :             delete poNode;
     581               0 :         YYERROR;
     582                 :         }
     583                 :       }
     584             332 :     
     585                 :         | SWQT_IDENTIFIER '.' '*'
     586                 :       {
     587              10 :                 CPLString osQualifiedField;
     588                 : 
     589              10 :                 osQualifiedField = $1->string_value;
     590              10 :                 osQualifiedField += ".*";
     591                 : 
     592              10 :                 delete $1;
     593              10 :                 $1 = NULL;
     594                 : 
     595              10 :           swq_expr_node *poNode = new swq_expr_node();
     596              10 :     poNode->eNodeType = SNT_COLUMN;
     597              20 :     poNode->string_value = CPLStrdup( osQualifiedField );
     598              10 :     poNode->table_index = poNode->field_index = -1;
     599                 : 
     600              10 :     if( !context->poCurSelect->PushField( poNode ) )
     601                 :         {
     602               0 :             delete poNode;
     603                 :         YYERROR;
     604                 :         }
     605               0 :       }
     606              10 :     
     607                 :         | SWQT_IDENTIFIER '(' '*' ')'
     608                 :       {
     609                 :           // special case for COUNT(*), confirm it.
     610             106 :     if( !EQUAL($1->string_value,"COUNT") )
     611                 :     {
     612                 :         CPLError( CE_Failure, CPLE_AppDefined,
     613                 :                 "Syntax Error with %s(*).", 
     614               1 :             $1->string_value );
     615               1 :             delete $1;
     616               1 :               YYERROR;
     617                 :     }
     618                 : 
     619             105 :         delete $1;
     620             105 :         $1 = NULL;
     621                 :                 
     622             105 :     swq_expr_node *poNode = new swq_expr_node();
     623             105 :     poNode->eNodeType = SNT_COLUMN;
     624             105 :     poNode->string_value = CPLStrdup( "*" );
     625             105 :     poNode->table_index = poNode->field_index = -1;
     626                 : 
     627             210 :     swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
     628             105 :     count->PushSubExpression( poNode );
     629                 : 
     630             105 :     if( !context->poCurSelect->PushField( count ) )
     631                 :         {
     632               0 :             delete count;
     633               0 :         YYERROR;
     634                 :         }
     635                 :       }
     636             105 : 
     637                 :         | SWQT_IDENTIFIER '(' '*' ')' SWQT_AS string_or_identifier
     638                 :       {
     639                 :           // special case for COUNT(*), confirm it.
     640               2 :     if( !EQUAL($1->string_value,"COUNT") )
     641                 :     {
     642                 :         CPLError( CE_Failure, CPLE_AppDefined,
     643                 :                 "Syntax Error with %s(*).", 
     644               1 :             $1->string_value );
     645               1 :             delete $1;
     646               1 :             delete $6;
     647               1 :               YYERROR;
     648                 :     }
     649                 : 
     650               1 :         delete $1;
     651               1 :         $1 = NULL;
     652                 : 
     653               1 :     swq_expr_node *poNode = new swq_expr_node();
     654               1 :     poNode->eNodeType = SNT_COLUMN;
     655               1 :     poNode->string_value = CPLStrdup( "*" );
     656               1 :     poNode->table_index = poNode->field_index = -1;
     657                 : 
     658               2 :     swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
     659               1 :     count->PushSubExpression( poNode );
     660                 : 
     661               1 :     if( !context->poCurSelect->PushField( count, $6->string_value ) )
     662                 :         {
     663               0 :             delete count;
     664               0 :             delete $6;
     665               0 :         YYERROR;
     666                 :         }
     667                 : 
     668               1 :                 delete $6;
     669                 :       }
     670               1 : 
     671                 :   | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')'
     672                 :       {
     673                 :           // special case for COUNT(DISTINCT x), confirm it.
     674               6 :     if( !EQUAL($1->string_value,"COUNT") )
     675                 :     {
     676                 :         CPLError( CE_Failure, CPLE_AppDefined,
     677               1 :                 "DISTINCT keyword can only be used in COUNT() operator." );
     678               1 :             delete $1;
     679               1 :             delete $4;
     680               1 :               YYERROR;
     681                 :     }
     682                 : 
     683               5 :                 delete $1;
     684                 :                 
     685               5 :                 swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
     686               5 :                 count->PushSubExpression( $4 );
     687                 :                 
     688               5 :     if( !context->poCurSelect->PushField( count, NULL, TRUE ) )
     689                 :         {
     690               0 :             delete count;
     691               0 :         YYERROR;
     692                 :         }
     693                 :       }
     694               5 : 
     695                 :   | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' SWQT_AS string_or_identifier
     696                 :       {
     697                 :           // special case for COUNT(DISTINCT x), confirm it.
     698               2 :     if( !EQUAL($1->string_value,"COUNT") )
     699                 :     {
     700                 :         CPLError( CE_Failure, CPLE_AppDefined,
     701               1 :                 "DISTINCT keyword can only be used in COUNT() operator." );
     702               1 :             delete $1;
     703               1 :             delete $4;
     704               1 :             delete $7;
     705               1 :               YYERROR;
     706                 :     }
     707                 : 
     708               1 :                 swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
     709               1 :                 count->PushSubExpression( $4 );
     710                 :                 
     711               1 :     if( !context->poCurSelect->PushField( count, $7->string_value, TRUE ) )
     712                 :         {
     713               0 :             delete $1;
     714               0 :             delete count;
     715               0 :             delete $7;
     716               0 :         YYERROR;
     717                 :         }
     718                 : 
     719               1 :                 delete $1;
     720               1 :                 delete $7;
     721                 :       }
     722               1 : 
     723                 : opt_where:  
     724                 :   | SWQT_WHERE logical_expr
     725                 :       {      
     726             300 :          context->poCurSelect->where_expr = $2;
     727                 :       }
     728             300 : 
     729                 : opt_joins:
     730                 :         | SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
     731                 :       {
     732               2 :           context->poCurSelect->PushJoin( $2->int_value,
     733               2 :                $4->string_value, 
     734               6 :                $6->string_value );
     735               2 :                 delete $2;
     736               2 :           delete $4;
     737               2 :           delete $6;
     738                 :       }
     739               2 :         | SWQT_LEFT SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
     740                 :       {
     741              21 :           context->poCurSelect->PushJoin( $3->int_value,
     742              21 :                $5->string_value, 
     743              63 :                $7->string_value );
     744              21 :                 delete $3;
     745              21 :           delete $5;
     746              21 :           delete $7;
     747                 :       }
     748              21 : 
     749                 : opt_order_by:
     750                 :   | SWQT_ORDER SWQT_BY sort_spec_list
     751                 : 
     752                 : sort_spec_list:
     753                 :   sort_spec ',' sort_spec_list
     754                 :   | sort_spec 
     755                 : 
     756                 : sort_spec:
     757                 :   field_value
     758                 :             {
     759               6 :                 context->poCurSelect->PushOrderBy( $1->string_value, TRUE );
     760               6 :                 delete $1;
     761               6 :                 $1 = NULL;
     762                 :             }
     763               6 :   | field_value SWQT_ASC
     764                 :             {
     765              11 :                 context->poCurSelect->PushOrderBy( $1->string_value, TRUE );
     766              11 :                 delete $1;
     767              11 :                 $1 = NULL;
     768                 :             }
     769              11 :   | field_value SWQT_DESC
     770                 :             {
     771               9 :                 context->poCurSelect->PushOrderBy( $1->string_value, FALSE );
     772               9 :                 delete $1;
     773               9 :                 $1 = NULL;
     774                 :             }
     775               9 : 
     776                 : string_or_identifier:
     777                 :         SWQT_IDENTIFIER
     778                 :         {
     779             507 :             $$ = $1;
     780                 :         }
     781             507 :         | SWQT_STRING
     782                 :         {
     783              56 :             $$ = $1;
     784                 :         }
     785              56 : 
     786                 : table_def:
     787                 :   string_or_identifier
     788                 :   {
     789                 :       int iTable;
     790             535 :       iTable =context->poCurSelect->PushTableDef( NULL, $1->string_value,
     791             535 :                            NULL );
     792             535 :       delete $1;
     793                 : 
     794             535 :       $$ = new swq_expr_node( iTable );
     795                 :   }
     796             535 : 
     797                 :   | string_or_identifier SWQT_IDENTIFIER
     798                 :   {
     799                 :       int iTable;
     800              12 :       iTable = context->poCurSelect->PushTableDef( NULL, $1->string_value,
     801              24 :                       $2->string_value );
     802              12 :       delete $1;
     803              12 :       delete $2;
     804                 : 
     805              12 :       $$ = new swq_expr_node( iTable );
     806                 :   }
     807              12 : 
     808                 :   | SWQT_STRING '.' string_or_identifier
     809                 :   {
     810                 :       int iTable;
     811               1 :       iTable = context->poCurSelect->PushTableDef( $1->string_value,
     812               2 :                       $3->string_value, NULL );
     813               1 :       delete $1;
     814               1 :       delete $3;
     815                 : 
     816               1 :       $$ = new swq_expr_node( iTable );
     817                 :   }
     818               1 : 
     819                 :   | SWQT_STRING '.' string_or_identifier SWQT_IDENTIFIER
     820                 :   {
     821                 :       int iTable;
     822               4 :       iTable = context->poCurSelect->PushTableDef( $1->string_value,
     823               4 :                           $3->string_value, 
     824              12 :                       $4->string_value );
     825               4 :       delete $1;
     826               4 :       delete $3;
     827               4 :       delete $4;
     828                 : 
     829               4 :       $$ = new swq_expr_node( iTable );
     830                 :   }

Generated by: LCOV version 1.7