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 #include "cpl_port.h" 32 #include "ogr_swq.h" 33 34 #include <cstdlib> 35 #include <cstring> 36 #include <limits> 37 38 #include "cpl_conv.h" 39 #include "cpl_error.h" 40 #include "cpl_string.h" 41 #include "ogr_core.h" 42 #include "ogr_geometry.h" 43 44 CPL_CVSID("$Id$") 45 46 #define YYSTYPE swq_expr_node * 47 48 /* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */ 49 /* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */ 50 /* increase YYINITDEPTH instead, but this will consume memory. */ 51 /* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */ 52 /* it appears to be a non documented feature of Bison */ 53 #define YYSTYPE_IS_TRIVIAL 1 54 %} 55 56 %define api.pure 57 /* if the next %define is commented out, Bison 2.4 should be sufficient */ 58 /* but will produce less prettier error messages */ 59 %define parse.error verbose 60 %require "3.0" 61 62 %parse-param {swq_parse_context *context} 63 %lex-param {swq_parse_context *context} 64 65 %token SWQT_INTEGER_NUMBER "integer number" 66 %token SWQT_FLOAT_NUMBER "floating point number" 67 %token SWQT_STRING "string" 68 %token SWQT_IDENTIFIER "identifier" 69 %token SWQT_IN "IN" 70 %token SWQT_LIKE "LIKE" 71 %token SWQT_ILIKE "ILIKE" 72 %token SWQT_ESCAPE "ESCAPE" 73 %token SWQT_BETWEEN "BETWEEN" 74 %token SWQT_NULL "NULL" 75 %token SWQT_IS "IS" 76 %token SWQT_SELECT "SELECT" 77 %token SWQT_LEFT "LEFT" 78 %token SWQT_JOIN "JOIN" 79 %token SWQT_WHERE "WHERE" 80 %token SWQT_ON "ON" 81 %token SWQT_ORDER "ORDER" 82 %token SWQT_BY "BY" 83 %token SWQT_FROM "FROM" 84 %token SWQT_AS "AS" 85 %token SWQT_ASC "ASC" 86 %token SWQT_DESC "DESC" 87 %token SWQT_DISTINCT "DISTINCT" 88 %token SWQT_CAST "CAST" 89 %token SWQT_UNION "UNION" 90 %token SWQT_ALL "ALL" 91 %token SWQT_LIMIT "LIMIT" 92 %token SWQT_OFFSET "OFFSET" 93 94 %token SWQT_VALUE_START 95 %token SWQT_SELECT_START 96 97 %token END 0 "end of string" 98 99 %token SWQT_NOT "NOT" 100 %token SWQT_OR "OR" 101 %token SWQT_AND "AND" 102 103 %left SWQT_OR 104 %left SWQT_AND 105 %left SWQT_NOT 106 107 %left '=' '<' '>' '!' SWQT_BETWEEN SWQT_IN SWQT_LIKE SWQT_ILIKE SWQT_IS 108 %left SWQT_ESCAPE 109 110 %left '+' '-' 111 %left '*' '/' '%' 112 %left SWQT_UMINUS 113 114 %token SWQT_RESERVED_KEYWORD "reserved keyword" 115 116 /* Any grammar rule that does $$ = must be listed afterwards */ 117 /* as well as SWQT_INTEGER_NUMBER SWQT_FLOAT_NUMBER SWQT_STRING SWQT_IDENTIFIER that are allocated by swqlex() */ 118 %destructor { delete $$; } SWQT_INTEGER_NUMBER SWQT_FLOAT_NUMBER SWQT_STRING SWQT_IDENTIFIER 119 %destructor { delete $$; } value_expr_list field_value value_expr value_expr_non_logical type_def table_def 120 121 %% 122 123 input: 124 | SWQT_VALUE_START value_expr 125 { 126 context->poRoot = $2; 127 swq_fixup(context); 128 } 129 130 | SWQT_SELECT_START select_statement 131 { 132 context->poRoot = $2; 133 swq_fixup(context); 134 } 135 136 value_expr: 137 value_expr_non_logical 138 { 139 $$ = $1; 140 } 141 142 | value_expr SWQT_AND value_expr 143 { 144 $$ = swq_create_and_or_or( SWQ_AND, $1, $3 ); 145 } 146 147 | value_expr SWQT_OR value_expr 148 { 149 $$ = swq_create_and_or_or( SWQ_OR, $1, $3 ); 150 } 151 152 | SWQT_NOT value_expr 153 { 154 $$ = new swq_expr_node( SWQ_NOT ); 155 $$->field_type = SWQ_BOOLEAN; 156 $$->PushSubExpression( $2 ); 157 } 158 159 | value_expr '=' value_expr 160 { 161 $$ = new swq_expr_node( SWQ_EQ ); 162 $$->field_type = SWQ_BOOLEAN; 163 $$->PushSubExpression( $1 ); 164 $$->PushSubExpression( $3 ); 165 } 166 167 | value_expr '<' '>' value_expr 168 { 169 $$ = new swq_expr_node( SWQ_NE ); 170 $$->field_type = SWQ_BOOLEAN; 171 $$->PushSubExpression( $1 ); 172 $$->PushSubExpression( $4 ); 173 } 174 175 | value_expr '!' '=' value_expr 176 { 177 $$ = new swq_expr_node( SWQ_NE ); 178 $$->field_type = SWQ_BOOLEAN; 179 $$->PushSubExpression( $1 ); 180 $$->PushSubExpression( $4 ); 181 } 182 183 | value_expr '<' value_expr 184 { 185 $$ = new swq_expr_node( SWQ_LT ); 186 $$->field_type = SWQ_BOOLEAN; 187 $$->PushSubExpression( $1 ); 188 $$->PushSubExpression( $3 ); 189 } 190 191 | value_expr '>' value_expr 192 { 193 $$ = new swq_expr_node( SWQ_GT ); 194 $$->field_type = SWQ_BOOLEAN; 195 $$->PushSubExpression( $1 ); 196 $$->PushSubExpression( $3 ); 197 } 198 199 | value_expr '<' '=' value_expr 200 { 201 $$ = new swq_expr_node( SWQ_LE ); 202 $$->field_type = SWQ_BOOLEAN; 203 $$->PushSubExpression( $1 ); 204 $$->PushSubExpression( $4 ); 205 } 206 207 | value_expr '=' '<' value_expr 208 { 209 $$ = new swq_expr_node( SWQ_LE ); 210 $$->field_type = SWQ_BOOLEAN; 211 $$->PushSubExpression( $1 ); 212 $$->PushSubExpression( $4 ); 213 } 214 215 | value_expr '=' '>' value_expr 216 { 217 $$ = new swq_expr_node( SWQ_LE ); 218 $$->field_type = SWQ_BOOLEAN; 219 $$->PushSubExpression( $1 ); 220 $$->PushSubExpression( $4 ); 221 } 222 223 | value_expr '>' '=' value_expr 224 { 225 $$ = new swq_expr_node( SWQ_GE ); 226 $$->field_type = SWQ_BOOLEAN; 227 $$->PushSubExpression( $1 ); 228 $$->PushSubExpression( $4 ); 229 } 230 231 | value_expr SWQT_LIKE value_expr 232 { 233 $$ = new swq_expr_node( SWQ_LIKE ); 234 $$->field_type = SWQ_BOOLEAN; 235 $$->PushSubExpression( $1 ); 236 $$->PushSubExpression( $3 ); 237 } 238 239 | value_expr SWQT_NOT SWQT_LIKE value_expr 240 { 241 swq_expr_node *like = new swq_expr_node( SWQ_LIKE ); 242 like->field_type = SWQ_BOOLEAN; 243 like->PushSubExpression( $1 ); 244 like->PushSubExpression( $4 ); 245 246 $$ = new swq_expr_node( SWQ_NOT ); 247 $$->field_type = SWQ_BOOLEAN; 248 $$->PushSubExpression( like ); 249 } 250 251 | value_expr SWQT_LIKE value_expr SWQT_ESCAPE value_expr 252 { 253 $$ = new swq_expr_node( SWQ_LIKE ); 254 $$->field_type = SWQ_BOOLEAN; 255 $$->PushSubExpression( $1 ); 256 $$->PushSubExpression( $3 ); 257 $$->PushSubExpression( $5 ); 258 } 259 260 | value_expr SWQT_NOT SWQT_LIKE value_expr SWQT_ESCAPE value_expr 261 { 262 swq_expr_node *like = new swq_expr_node( SWQ_LIKE ); 263 like->field_type = SWQ_BOOLEAN; 264 like->PushSubExpression( $1 ); 265 like->PushSubExpression( $4 ); 266 like->PushSubExpression( $6 ); 267 268 $$ = new swq_expr_node( SWQ_NOT ); 269 $$->field_type = SWQ_BOOLEAN; 270 $$->PushSubExpression( like ); 271 } 272 273 | value_expr SWQT_ILIKE value_expr 274 { 275 $$ = new swq_expr_node( SWQ_ILIKE ); 276 $$->field_type = SWQ_BOOLEAN; 277 $$->PushSubExpression( $1 ); 278 $$->PushSubExpression( $3 ); 279 } 280 281 | value_expr SWQT_NOT SWQT_ILIKE value_expr 282 { 283 swq_expr_node *like = new swq_expr_node( SWQ_ILIKE ); 284 like->field_type = SWQ_BOOLEAN; 285 like->PushSubExpression( $1 ); 286 like->PushSubExpression( $4 ); 287 288 $$ = new swq_expr_node( SWQ_NOT ); 289 $$->field_type = SWQ_BOOLEAN; 290 $$->PushSubExpression( like ); 291 } 292 293 | value_expr SWQT_ILIKE value_expr SWQT_ESCAPE value_expr 294 { 295 $$ = new swq_expr_node( SWQ_ILIKE ); 296 $$->field_type = SWQ_BOOLEAN; 297 $$->PushSubExpression( $1 ); 298 $$->PushSubExpression( $3 ); 299 $$->PushSubExpression( $5 ); 300 } 301 302 | value_expr SWQT_NOT SWQT_ILIKE value_expr SWQT_ESCAPE value_expr 303 { 304 swq_expr_node *like = new swq_expr_node( SWQ_ILIKE ); 305 like->field_type = SWQ_BOOLEAN; 306 like->PushSubExpression( $1 ); 307 like->PushSubExpression( $4 ); 308 like->PushSubExpression( $6 ); 309 310 $$ = new swq_expr_node( SWQ_NOT ); 311 $$->field_type = SWQ_BOOLEAN; 312 $$->PushSubExpression( like ); 313 } 314 315 | value_expr SWQT_IN '(' value_expr_list ')' 316 { 317 $$ = $4; 318 $$->field_type = SWQ_BOOLEAN; 319 $$->nOperation = SWQ_IN; 320 $$->PushSubExpression( $1 ); 321 $$->ReverseSubExpressions(); 322 } 323 324 | value_expr SWQT_NOT SWQT_IN '(' value_expr_list ')' 325 { 326 swq_expr_node *in = $5; 327 in->field_type = SWQ_BOOLEAN; 328 in->nOperation = SWQ_IN; 329 in->PushSubExpression( $1 ); 330 in->ReverseSubExpressions(); 331 332 $$ = new swq_expr_node( SWQ_NOT ); 333 $$->field_type = SWQ_BOOLEAN; 334 $$->PushSubExpression( in ); 335 } 336 337 | value_expr SWQT_BETWEEN value_expr_non_logical SWQT_AND value_expr_non_logical 338 { 339 $$ = new swq_expr_node( SWQ_BETWEEN ); 340 $$->field_type = SWQ_BOOLEAN; 341 $$->PushSubExpression( $1 ); 342 $$->PushSubExpression( $3 ); 343 $$->PushSubExpression( $5 ); 344 } 345 346 | value_expr SWQT_NOT SWQT_BETWEEN value_expr_non_logical SWQT_AND value_expr_non_logical 347 { 348 swq_expr_node *between = new swq_expr_node( SWQ_BETWEEN ); 349 between->field_type = SWQ_BOOLEAN; 350 between->PushSubExpression( $1 ); 351 between->PushSubExpression( $4 ); 352 between->PushSubExpression( $6 ); 353 354 $$ = new swq_expr_node( SWQ_NOT ); 355 $$->field_type = SWQ_BOOLEAN; 356 $$->PushSubExpression( between ); 357 } 358 359 | value_expr SWQT_IS SWQT_NULL 360 { 361 $$ = new swq_expr_node( SWQ_ISNULL ); 362 $$->field_type = SWQ_BOOLEAN; 363 $$->PushSubExpression( $1 ); 364 } 365 366 | value_expr SWQT_IS SWQT_NOT SWQT_NULL 367 { 368 swq_expr_node *isnull = new swq_expr_node( SWQ_ISNULL ); 369 isnull->field_type = SWQ_BOOLEAN; 370 isnull->PushSubExpression( $1 ); 371 372 $$ = new swq_expr_node( SWQ_NOT ); 373 $$->field_type = SWQ_BOOLEAN; 374 $$->PushSubExpression( isnull ); 375 } 376 377 value_expr_list: 378 value_expr ',' value_expr_list 379 { 380 $$ = $3; 381 $3->PushSubExpression( $1 ); 382 } 383 384 | value_expr 385 { 386 $$ = new swq_expr_node( SWQ_ARGUMENT_LIST ); /* temporary value */ 387 $$->PushSubExpression( $1 ); 388 } 389 390 field_value: 391 SWQT_IDENTIFIER 392 { 393 $$ = $1; // validation deferred. 394 $$->eNodeType = SNT_COLUMN; 395 $$->field_index = -1; 396 $$->table_index = -1; 397 } 398 399 | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER 400 { 401 $$ = $1; // validation deferred. 402 $$->eNodeType = SNT_COLUMN; 403 $$->field_index = -1; 404 $$->table_index = -1; 405 $$->table_name = $$->string_value; 406 $$->string_value = CPLStrdup($3->string_value); 407 delete $3; 408 $3 = nullptr; 409 } 410 411 value_expr_non_logical: 412 SWQT_INTEGER_NUMBER 413 { 414 $$ = $1; 415 } 416 417 | SWQT_FLOAT_NUMBER 418 { 419 $$ = $1; 420 } 421 422 | SWQT_STRING 423 { 424 $$ = $1; 425 } 426 | field_value 427 { 428 $$ = $1; 429 } 430 431 | '(' value_expr ')' 432 { 433 $$ = $2; 434 } 435 436 | SWQT_NULL 437 { 438 $$ = new swq_expr_node(static_cast<const char*>(nullptr)); 439 } 440 441 | '-' value_expr_non_logical %prec SWQT_UMINUS 442 { 443 if ($2->eNodeType == SNT_CONSTANT) 444 { 445 if( $2->field_type == SWQ_FLOAT && 446 $2->string_value && 447 strcmp($2->string_value, "9223372036854775808") == 0 ) 448 { 449 $$ = $2; 450 $$->field_type = SWQ_INTEGER64; 451 $$->int_value = std::numeric_limits<GIntBig>::min(); 452 $$->float_value = static_cast<double>(std::numeric_limits<GIntBig>::min()); 453 } 454 // - (-9223372036854775808) cannot be represented on int64 455 // the classic overflow is that its negation is itself. 456 else if( $2->field_type == SWQ_INTEGER64 && 457 $2->int_value == std::numeric_limits<GIntBig>::min() ) 458 { 459 $$ = $2; 460 } 461 else 462 { 463 $$ = $2; 464 $$->int_value *= -1; 465 $$->float_value *= -1; 466 } 467 } 468 else 469 { 470 $$ = new swq_expr_node( SWQ_MULTIPLY ); 471 $$->PushSubExpression( new swq_expr_node(-1) ); 472 $$->PushSubExpression( $2 ); 473 } 474 } 475 476 | value_expr_non_logical '+' value_expr_non_logical 477 { 478 $$ = new swq_expr_node( SWQ_ADD ); 479 $$->PushSubExpression( $1 ); 480 $$->PushSubExpression( $3 ); 481 } 482 483 | value_expr_non_logical '-' value_expr_non_logical 484 { 485 $$ = new swq_expr_node( SWQ_SUBTRACT ); 486 $$->PushSubExpression( $1 ); 487 $$->PushSubExpression( $3 ); 488 } 489 490 | value_expr_non_logical '*' value_expr_non_logical 491 { 492 $$ = new swq_expr_node( SWQ_MULTIPLY ); 493 $$->PushSubExpression( $1 ); 494 $$->PushSubExpression( $3 ); 495 } 496 497 | value_expr_non_logical '/' value_expr_non_logical 498 { 499 $$ = new swq_expr_node( SWQ_DIVIDE ); 500 $$->PushSubExpression( $1 ); 501 $$->PushSubExpression( $3 ); 502 } 503 504 | value_expr_non_logical '%' value_expr_non_logical 505 { 506 $$ = new swq_expr_node( SWQ_MODULUS ); 507 $$->PushSubExpression( $1 ); 508 $$->PushSubExpression( $3 ); 509 } 510 511 | SWQT_IDENTIFIER '(' value_expr_list ')' 512 { 513 const swq_operation *poOp = 514 swq_op_registrar::GetOperator( $1->string_value ); 515 516 if( poOp == nullptr ) 517 { 518 if( context->bAcceptCustomFuncs ) 519 { 520 $$ = $3; 521 $$->eNodeType = SNT_OPERATION; 522 $$->nOperation = SWQ_CUSTOM_FUNC; 523 $$->string_value = CPLStrdup($1->string_value); 524 $$->ReverseSubExpressions(); 525 delete $1; 526 } 527 else 528 { 529 CPLError( CE_Failure, CPLE_AppDefined, 530 "Undefined function '%s' used.", 531 $1->string_value ); 532 delete $1; 533 delete $3; 534 YYERROR; 535 } 536 } 537 else 538 { 539 $$ = $3; 540 $$->eNodeType = SNT_OPERATION; 541 $$->nOperation = poOp->eOperation; 542 $$->ReverseSubExpressions(); 543 delete $1; 544 } 545 } 546 547 | SWQT_CAST '(' value_expr SWQT_AS type_def ')' 548 { 549 $$ = $5; 550 $$->PushSubExpression( $3 ); 551 $$->ReverseSubExpressions(); 552 } 553 554 type_def: 555 SWQT_IDENTIFIER 556 { 557 $$ = new swq_expr_node( SWQ_CAST ); 558 $$->PushSubExpression( $1 ); 559 } 560 561 | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ')' 562 { 563 $$ = new swq_expr_node( SWQ_CAST ); 564 $$->PushSubExpression( $3 ); 565 $$->PushSubExpression( $1 ); 566 } 567 568 | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ',' SWQT_INTEGER_NUMBER ')' 569 { 570 $$ = new swq_expr_node( SWQ_CAST ); 571 $$->PushSubExpression( $5 ); 572 $$->PushSubExpression( $3 ); 573 $$->PushSubExpression( $1 ); 574 } 575 576 /* e.g. GEOMETRY(POINT) */ 577 | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ')' 578 { 579 OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value); 580 if( !EQUAL($1->string_value, "GEOMETRY") || 581 (wkbFlatten(eType) == wkbUnknown && 582 !STARTS_WITH_CI($3->string_value, "GEOMETRY")) ) 583 { 584 yyerror (context, "syntax error"); 585 delete $1; 586 delete $3; 587 YYERROR; 588 } 589 $$ = new swq_expr_node( SWQ_CAST ); 590 $$->PushSubExpression( $3 ); 591 $$->PushSubExpression( $1 ); 592 } 593 594 /* e.g. GEOMETRY(POINT,4326) */ 595 | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ',' SWQT_INTEGER_NUMBER ')' 596 { 597 OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value); 598 if( !EQUAL($1->string_value, "GEOMETRY") || 599 (wkbFlatten(eType) == wkbUnknown && 600 !STARTS_WITH_CI($3->string_value, "GEOMETRY")) ) 601 { 602 yyerror (context, "syntax error"); 603 delete $1; 604 delete $3; 605 delete $5; 606 YYERROR; 607 } 608 $$ = new swq_expr_node( SWQ_CAST ); 609 $$->PushSubExpression( $5 ); 610 $$->PushSubExpression( $3 ); 611 $$->PushSubExpression( $1 ); 612 } 613 614 select_statement: 615 select_core opt_union_all 616 | '(' select_core ')' opt_union_all 617 618 select_core: 619 SWQT_SELECT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by opt_limit opt_offset 620 { 621 delete $4; 622 } 623 624 | SWQT_SELECT SWQT_DISTINCT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by opt_limit opt_offset 625 { 626 context->poCurSelect->query_mode = SWQM_DISTINCT_LIST; 627 delete $5; 628 } 629 630 opt_union_all: 631 | union_all select_statement 632 633 union_all: SWQT_UNION SWQT_ALL 634 { 635 swq_select* poNewSelect = new swq_select(); 636 context->poCurSelect->PushUnionAll(poNewSelect); 637 context->poCurSelect = poNewSelect; 638 } 639 640 select_field_list: 641 column_spec 642 | column_spec ',' select_field_list 643 644 column_spec: 645 value_expr 646 { 647 if( !context->poCurSelect->PushField( $1 ) ) 648 { 649 delete $1; 650 YYERROR; 651 } 652 } 653 654 | value_expr as_clause 655 { 656 if( !context->poCurSelect->PushField( $1, $2->string_value ) ) 657 { 658 delete $1; 659 delete $2; 660 YYERROR; 661 } 662 delete $2; 663 } 664 665 | '*' 666 { 667 swq_expr_node *poNode = new swq_expr_node(); 668 poNode->eNodeType = SNT_COLUMN; 669 poNode->string_value = CPLStrdup( "*" ); 670 poNode->table_index = -1; 671 poNode->field_index = -1; 672 673 if( !context->poCurSelect->PushField( poNode ) ) 674 { 675 delete poNode; 676 YYERROR; 677 } 678 } 679 680 | SWQT_IDENTIFIER '.' '*' 681 { 682 CPLString osTableName = $1->string_value; 683 684 delete $1; 685 $1 = nullptr; 686 687 swq_expr_node *poNode = new swq_expr_node(); 688 poNode->eNodeType = SNT_COLUMN; 689 poNode->table_name = CPLStrdup(osTableName ); 690 poNode->string_value = CPLStrdup( "*" ); 691 poNode->table_index = -1; 692 poNode->field_index = -1; 693 694 if( !context->poCurSelect->PushField( poNode ) ) 695 { 696 delete poNode; 697 YYERROR; 698 } 699 } 700 701 | SWQT_IDENTIFIER '(' '*' ')' 702 { 703 // special case for COUNT(*), confirm it. 704 if( !EQUAL($1->string_value, "COUNT") ) 705 { 706 CPLError( CE_Failure, CPLE_AppDefined, 707 "Syntax Error with %s(*).", 708 $1->string_value ); 709 delete $1; 710 YYERROR; 711 } 712 713 delete $1; 714 $1 = nullptr; 715 716 swq_expr_node *poNode = new swq_expr_node(); 717 poNode->eNodeType = SNT_COLUMN; 718 poNode->string_value = CPLStrdup( "*" ); 719 poNode->table_index = -1; 720 poNode->field_index = -1; 721 722 swq_expr_node *count = new swq_expr_node( SWQ_COUNT ); 723 count->PushSubExpression( poNode ); 724 725 if( !context->poCurSelect->PushField( count ) ) 726 { 727 delete count; 728 YYERROR; 729 } 730 } 731 732 | SWQT_IDENTIFIER '(' '*' ')' as_clause 733 { 734 // special case for COUNT(*), confirm it. 735 if( !EQUAL($1->string_value, "COUNT") ) 736 { 737 CPLError( CE_Failure, CPLE_AppDefined, 738 "Syntax Error with %s(*).", 739 $1->string_value ); 740 delete $1; 741 delete $5; 742 YYERROR; 743 } 744 745 delete $1; 746 $1 = nullptr; 747 748 swq_expr_node *poNode = new swq_expr_node(); 749 poNode->eNodeType = SNT_COLUMN; 750 poNode->string_value = CPLStrdup( "*" ); 751 poNode->table_index = -1; 752 poNode->field_index = -1; 753 754 swq_expr_node *count = new swq_expr_node( SWQ_COUNT ); 755 count->PushSubExpression( poNode ); 756 757 if( !context->poCurSelect->PushField( count, $5->string_value ) ) 758 { 759 delete count; 760 delete $5; 761 YYERROR; 762 } 763 764 delete $5; 765 } 766 767 | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' 768 { 769 // special case for COUNT(DISTINCT x), confirm it. 770 if( !EQUAL($1->string_value, "COUNT") ) 771 { 772 CPLError( 773 CE_Failure, CPLE_AppDefined, 774 "DISTINCT keyword can only be used in COUNT() operator." ); 775 delete $1; 776 delete $4; 777 YYERROR; 778 } 779 780 delete $1; 781 782 swq_expr_node *count = new swq_expr_node( SWQ_COUNT ); 783 count->PushSubExpression( $4 ); 784 785 if( !context->poCurSelect->PushField( count, nullptr, TRUE ) ) 786 { 787 delete count; 788 YYERROR; 789 } 790 } 791 792 | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' as_clause 793 { 794 // special case for COUNT(DISTINCT x), confirm it. 795 if( !EQUAL($1->string_value, "COUNT") ) 796 { 797 CPLError( CE_Failure, CPLE_AppDefined, 798 "DISTINCT keyword can only be used in COUNT() operator." ); 799 delete $1; 800 delete $4; 801 delete $6; 802 YYERROR; 803 } 804 805 swq_expr_node *count = new swq_expr_node( SWQ_COUNT ); 806 count->PushSubExpression( $4 ); 807 808 if( !context->poCurSelect->PushField( count, $6->string_value, TRUE ) ) 809 { 810 delete $1; 811 delete count; 812 delete $6; 813 YYERROR; 814 } 815 816 delete $1; 817 delete $6; 818 } 819 820 as_clause: 821 SWQT_AS SWQT_IDENTIFIER 822 { 823 delete $1; 824 $$ = $2; 825 } 826 827 | SWQT_IDENTIFIER 828 829 opt_where: 830 | SWQT_WHERE value_expr 831 { 832 context->poCurSelect->where_expr = $2; 833 } 834 835 opt_joins: 836 | SWQT_JOIN table_def SWQT_ON value_expr opt_joins 837 { 838 context->poCurSelect->PushJoin( static_cast<int>($2->int_value), 839 $4 ); 840 delete $2; 841 } 842 | SWQT_LEFT SWQT_JOIN table_def SWQT_ON value_expr opt_joins 843 { 844 context->poCurSelect->PushJoin( static_cast<int>($3->int_value), 845 $5 ); 846 delete $3; 847 } 848 849 opt_order_by: 850 | SWQT_ORDER SWQT_BY sort_spec_list 851 852 sort_spec_list: 853 sort_spec ',' sort_spec_list 854 | sort_spec 855 856 sort_spec: 857 field_value 858 { 859 context->poCurSelect->PushOrderBy( $1->table_name, $1->string_value, TRUE ); 860 delete $1; 861 $1 = nullptr; 862 } 863 | field_value SWQT_ASC 864 { 865 context->poCurSelect->PushOrderBy( $1->table_name, $1->string_value, TRUE ); 866 delete $1; 867 $1 = nullptr; 868 } 869 | field_value SWQT_DESC 870 { 871 context->poCurSelect->PushOrderBy( $1->table_name, $1->string_value, FALSE ); 872 delete $1; 873 $1 = nullptr; 874 } 875 876 opt_limit: 877 | SWQT_LIMIT SWQT_INTEGER_NUMBER 878 { 879 context->poCurSelect->SetLimit( $2->int_value ); 880 delete $2; 881 $2 = nullptr; 882 } 883 884 opt_offset: 885 | SWQT_OFFSET SWQT_INTEGER_NUMBER 886 { 887 context->poCurSelect->SetOffset( $2->int_value ); 888 delete $2; 889 $2 = nullptr; 890 } 891 892 table_def: 893 SWQT_IDENTIFIER 894 { 895 const int iTable = 896 context->poCurSelect->PushTableDef( nullptr, $1->string_value, 897 nullptr ); 898 delete $1; 899 900 $$ = new swq_expr_node( iTable ); 901 } 902 903 | SWQT_IDENTIFIER as_clause 904 { 905 const int iTable = 906 context->poCurSelect->PushTableDef( nullptr, $1->string_value, 907 $2->string_value ); 908 delete $1; 909 delete $2; 910 911 $$ = new swq_expr_node( iTable ); 912 } 913 914 | SWQT_STRING '.' SWQT_IDENTIFIER 915 { 916 const int iTable = 917 context->poCurSelect->PushTableDef( $1->string_value, 918 $3->string_value, nullptr ); 919 delete $1; 920 delete $3; 921 922 $$ = new swq_expr_node( iTable ); 923 } 924 925 | SWQT_STRING '.' SWQT_IDENTIFIER as_clause 926 { 927 const int iTable = 928 context->poCurSelect->PushTableDef( $1->string_value, 929 $3->string_value, 930 $4->string_value ); 931 delete $1; 932 delete $3; 933 delete $4; 934 935 $$ = new swq_expr_node( iTable ); 936 } 937 938 | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER 939 { 940 const int iTable = 941 context->poCurSelect->PushTableDef( $1->string_value, 942 $3->string_value, nullptr ); 943 delete $1; 944 delete $3; 945 946 $$ = new swq_expr_node( iTable ); 947 } 948 949 | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER as_clause 950 { 951 const int iTable = 952 context->poCurSelect->PushTableDef( $1->string_value, 953 $3->string_value, 954 $4->string_value ); 955 delete $1; 956 delete $3; 957 delete $4; 958 959 $$ = new swq_expr_node( iTable ); 960 } 961