1 /****************************************************************************** 2 * 3 * Component: OGR SQL Engine 4 * Purpose: Implementation of the swq_expr_node class used to represent a 5 * node in an SQL expression. 6 * Author: Frank Warmerdam <warmerdam@pobox.com> 7 * 8 ****************************************************************************** 9 * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com> 10 * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.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 #ifndef DOXYGEN_SKIP 32 33 #include "cpl_port.h" 34 #include "ogr_swq.h" 35 36 #include <cctype> 37 #include <cstdio> 38 #include <cstring> 39 #include <string> 40 #include <vector> 41 42 #include "cpl_conv.h" 43 #include "cpl_error.h" 44 #include "cpl_multiproc.h" 45 #include "cpl_string.h" 46 #include "ogr_geometry.h" 47 48 CPL_CVSID("$Id: swq_expr_node.cpp 6659c4d5c910df313ac451cd5ca687862eef040b 2020-10-01 15:37:53 +0200 Even Rouault $") 49 50 /************************************************************************/ 51 /* swq_expr_node() */ 52 /************************************************************************/ 53 54 swq_expr_node::swq_expr_node() = default; 55 56 /************************************************************************/ 57 /* swq_expr_node(int) */ 58 /************************************************************************/ 59 60 swq_expr_node::swq_expr_node( int nValueIn ): 61 int_value(nValueIn) 62 { 63 } 64 65 /************************************************************************/ 66 /* swq_expr_node(GIntBig) */ 67 /************************************************************************/ 68 69 swq_expr_node::swq_expr_node( GIntBig nValueIn ): 70 field_type(SWQ_INTEGER64), 71 int_value(nValueIn) 72 { 73 } 74 75 /************************************************************************/ 76 /* swq_expr_node(double) */ 77 /************************************************************************/ 78 79 swq_expr_node::swq_expr_node( double dfValueIn ): 80 field_type(SWQ_FLOAT), 81 float_value(dfValueIn) 82 { 83 } 84 85 /************************************************************************/ 86 /* swq_expr_node(const char*) */ 87 /************************************************************************/ 88 89 swq_expr_node::swq_expr_node( const char *pszValueIn ): 90 field_type(SWQ_STRING), 91 is_null(pszValueIn == nullptr), 92 string_value(CPLStrdup( pszValueIn ? pszValueIn : "" )) 93 { 94 } 95 96 /************************************************************************/ 97 /* swq_expr_node(OGRGeometry *) */ 98 /************************************************************************/ 99 100 swq_expr_node::swq_expr_node( OGRGeometry *poGeomIn ): 101 field_type(SWQ_GEOMETRY), 102 is_null(poGeomIn == nullptr), 103 geometry_value(poGeomIn ? poGeomIn->clone() : nullptr) 104 { 105 } 106 107 /************************************************************************/ 108 /* swq_expr_node(swq_op) */ 109 /************************************************************************/ 110 111 swq_expr_node::swq_expr_node( swq_op eOp ): 112 eNodeType(SNT_OPERATION), 113 nOperation(eOp) 114 { 115 } 116 117 /************************************************************************/ 118 /* ~swq_expr_node() */ 119 /************************************************************************/ 120 121 swq_expr_node::~swq_expr_node() 122 123 { 124 CPLFree( table_name ); 125 CPLFree( string_value ); 126 127 for( int i = 0; i < nSubExprCount; i++ ) 128 delete papoSubExpr[i]; 129 CPLFree( papoSubExpr ); 130 delete geometry_value; 131 } 132 133 /************************************************************************/ 134 /* MarkAsTimestamp() */ 135 /************************************************************************/ 136 137 void swq_expr_node::MarkAsTimestamp() 138 139 { 140 CPLAssert( eNodeType == SNT_CONSTANT ); 141 CPLAssert( field_type == SWQ_STRING ); 142 field_type = SWQ_TIMESTAMP; 143 } 144 145 /************************************************************************/ 146 /* PushSubExpression() */ 147 /************************************************************************/ 148 149 void swq_expr_node::PushSubExpression( swq_expr_node *child ) 150 151 { 152 nSubExprCount++; 153 papoSubExpr = static_cast<swq_expr_node **>( 154 CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount )); 155 156 papoSubExpr[nSubExprCount-1] = child; 157 } 158 159 /************************************************************************/ 160 /* ReverseSubExpressions() */ 161 /************************************************************************/ 162 163 void swq_expr_node::ReverseSubExpressions() 164 165 { 166 for( int i = 0; i < nSubExprCount / 2; i++ ) 167 { 168 std::swap(papoSubExpr[i], papoSubExpr[nSubExprCount - i - 1]); 169 } 170 } 171 172 /************************************************************************/ 173 /* Check() */ 174 /* */ 175 /* Check argument types, etc. */ 176 /************************************************************************/ 177 178 swq_field_type 179 swq_expr_node::Check( swq_field_list *poFieldList, 180 int bAllowFieldsInSecondaryTables, 181 int bAllowMismatchTypeOnFieldComparison, 182 swq_custom_func_registrar* poCustomFuncRegistrar, 183 int nDepth ) 184 185 { 186 if( nDepth == 32 ) 187 { 188 CPLError(CE_Failure, CPLE_AppDefined, 189 "Too many recursion levels in expression"); 190 return SWQ_ERROR; 191 } 192 193 /* -------------------------------------------------------------------- */ 194 /* Otherwise we take constants literally. */ 195 /* -------------------------------------------------------------------- */ 196 if( eNodeType == SNT_CONSTANT ) 197 return field_type; 198 199 /* -------------------------------------------------------------------- */ 200 /* If this is intended to be a field definition, but has not */ 201 /* yet been looked up, we do so now. */ 202 /* -------------------------------------------------------------------- */ 203 if( eNodeType == SNT_COLUMN && field_index == -1 ) 204 { 205 field_index = 206 swq_identify_field( table_name, string_value, poFieldList, 207 &field_type, &table_index ); 208 209 if( field_index < 0 ) 210 { 211 if( table_name ) 212 CPLError( CE_Failure, CPLE_AppDefined, 213 R"("%s"."%s" not recognised as an available field.)", 214 table_name, string_value ); 215 else 216 CPLError( CE_Failure, CPLE_AppDefined, 217 "\"%s\" not recognised as an available field.", 218 string_value ); 219 220 return SWQ_ERROR; 221 } 222 223 if( !bAllowFieldsInSecondaryTables && table_index != 0 ) 224 { 225 CPLError( 226 CE_Failure, CPLE_AppDefined, 227 "Cannot use field '%s' of a secondary table in this context", 228 string_value ); 229 return SWQ_ERROR; 230 } 231 } 232 233 if( eNodeType == SNT_COLUMN ) 234 return field_type; 235 236 /* -------------------------------------------------------------------- */ 237 /* We are dealing with an operation - fetch the definition. */ 238 /* -------------------------------------------------------------------- */ 239 const swq_operation *poOp = 240 (nOperation == SWQ_CUSTOM_FUNC && poCustomFuncRegistrar != nullptr ) ? 241 poCustomFuncRegistrar->GetOperator(string_value) : 242 swq_op_registrar::GetOperator(nOperation); 243 244 if( poOp == nullptr ) 245 { 246 if( nOperation == SWQ_CUSTOM_FUNC ) 247 CPLError( CE_Failure, CPLE_AppDefined, 248 "Check(): Unable to find definition for operator %s.", 249 string_value ); 250 else 251 CPLError( CE_Failure, CPLE_AppDefined, 252 "Check(): Unable to find definition for operator %d.", 253 nOperation ); 254 return SWQ_ERROR; 255 } 256 257 /* -------------------------------------------------------------------- */ 258 /* Check subexpressions first. */ 259 /* -------------------------------------------------------------------- */ 260 for( int i = 0; i < nSubExprCount; i++ ) 261 { 262 if( papoSubExpr[i]->Check(poFieldList, bAllowFieldsInSecondaryTables, 263 bAllowMismatchTypeOnFieldComparison, 264 poCustomFuncRegistrar, 265 nDepth + 1) == SWQ_ERROR ) 266 return SWQ_ERROR; 267 } 268 269 /* -------------------------------------------------------------------- */ 270 /* Check this node. */ 271 /* -------------------------------------------------------------------- */ 272 field_type = poOp->pfnChecker( this, bAllowMismatchTypeOnFieldComparison ); 273 274 return field_type; 275 } 276 277 /************************************************************************/ 278 /* Dump() */ 279 /************************************************************************/ 280 281 void swq_expr_node::Dump( FILE * fp, int depth ) 282 283 { 284 char spaces[60] = {}; 285 286 { 287 int i = 0; // Used after for. 288 for( ; i < depth*2 && i < static_cast<int>(sizeof(spaces)) - 1; i++ ) 289 spaces[i] = ' '; 290 spaces[i] = '\0'; 291 } 292 293 if( eNodeType == SNT_COLUMN ) 294 { 295 fprintf( fp, "%s Field %d\n", spaces, field_index ); 296 return; 297 } 298 299 if( eNodeType == SNT_CONSTANT ) 300 { 301 if( field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 || 302 field_type == SWQ_BOOLEAN ) 303 fprintf( fp, "%s " CPL_FRMT_GIB "\n", spaces, int_value ); 304 else if( field_type == SWQ_FLOAT ) 305 fprintf( fp, "%s %.15g\n", spaces, float_value ); 306 else if( field_type == SWQ_GEOMETRY ) 307 { 308 if( geometry_value == nullptr ) 309 fprintf( fp, "%s (null)\n", spaces ); 310 else 311 { 312 char* pszWKT = nullptr; 313 geometry_value->exportToWkt(&pszWKT); 314 fprintf( fp, "%s %s\n", spaces, pszWKT ); 315 CPLFree(pszWKT); 316 } 317 } 318 else 319 fprintf( fp, "%s %s\n", spaces, string_value ); 320 return; 321 } 322 323 CPLAssert( eNodeType == SNT_OPERATION ); 324 325 const swq_operation *op_def = 326 swq_op_registrar::GetOperator( nOperation ); 327 if( op_def ) 328 fprintf( fp, "%s%s\n", spaces, op_def->pszName ); 329 else 330 fprintf( fp, "%s%s\n", spaces, string_value ); 331 332 for( int i = 0; i < nSubExprCount; i++ ) 333 papoSubExpr[i]->Dump( fp, depth+1 ); 334 } 335 336 /************************************************************************/ 337 /* QuoteIfNecessary() */ 338 /* */ 339 /* Add quoting if necessary to unparse a string. */ 340 /************************************************************************/ 341 342 CPLString swq_expr_node::QuoteIfNecessary( const CPLString &osExpr, 343 char chQuote ) 344 345 { 346 if( osExpr[0] == '_' ) 347 return Quote(osExpr, chQuote); 348 if( osExpr == "*" ) 349 return osExpr; 350 351 for( int i = 0; i < static_cast<int>(osExpr.size()); i++ ) 352 { 353 char ch = osExpr[i]; 354 if( (!(isalnum(static_cast<int>(ch)) || ch == '_')) || ch == '.' ) 355 { 356 return Quote(osExpr, chQuote); 357 } 358 } 359 360 if( swq_is_reserved_keyword(osExpr) ) 361 { 362 return Quote(osExpr, chQuote); 363 } 364 365 return osExpr; 366 } 367 368 /************************************************************************/ 369 /* Quote() */ 370 /* */ 371 /* Add quoting necessary to unparse a string. */ 372 /************************************************************************/ 373 374 CPLString swq_expr_node::Quote( const CPLString &osTarget, char chQuote ) 375 376 { 377 CPLString osNew; 378 379 osNew += chQuote; 380 381 for( int i = 0; i < static_cast<int>(osTarget.size()); i++ ) 382 { 383 if( osTarget[i] == chQuote ) 384 { 385 osNew += chQuote; 386 osNew += chQuote; 387 } 388 else 389 osNew += osTarget[i]; 390 } 391 osNew += chQuote; 392 393 return osNew; 394 } 395 396 /************************************************************************/ 397 /* Unparse() */ 398 /************************************************************************/ 399 400 char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote ) 401 402 { 403 CPLString osExpr; 404 405 /* -------------------------------------------------------------------- */ 406 /* Handle constants. */ 407 /* -------------------------------------------------------------------- */ 408 if( eNodeType == SNT_CONSTANT ) 409 { 410 if( is_null ) 411 return CPLStrdup("NULL"); 412 413 if( field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 || 414 field_type == SWQ_BOOLEAN ) 415 osExpr.Printf( CPL_FRMT_GIB, int_value ); 416 else if( field_type == SWQ_FLOAT ) 417 { 418 osExpr.Printf( "%.15g", float_value ); 419 // Make sure this is interpreted as a floating point value 420 // and not as an integer later. 421 if( strchr(osExpr, '.') == nullptr && strchr(osExpr, 'e') == nullptr && 422 strchr(osExpr, 'E') == nullptr ) 423 osExpr += '.'; 424 } 425 else 426 { 427 osExpr = Quote( string_value ); 428 } 429 430 return CPLStrdup(osExpr); 431 } 432 433 /* -------------------------------------------------------------------- */ 434 /* Handle columns. */ 435 /* -------------------------------------------------------------------- */ 436 if( eNodeType == SNT_COLUMN ) 437 { 438 if( field_list == nullptr ) 439 { 440 if( table_name ) 441 osExpr.Printf( 442 "%s.%s", 443 QuoteIfNecessary(table_name, chColumnQuote).c_str(), 444 QuoteIfNecessary(string_value, chColumnQuote).c_str() ); 445 else 446 osExpr.Printf( 447 "%s", 448 QuoteIfNecessary(string_value, chColumnQuote).c_str() ); 449 } 450 else if( field_index != -1 451 && table_index < field_list->table_count 452 && table_index > 0 ) 453 { 454 // We deliberately browse through the list starting from the end 455 // This is for the case where the FID column exists both as 456 // FID and then real_fid_name. We want real_fid_name to be used 457 for( int i = field_list->count - 1; i >= 0; i-- ) 458 { 459 if( field_list->table_ids[i] == table_index && 460 field_list->ids[i] == field_index ) 461 { 462 osExpr.Printf( "%s.%s", 463 QuoteIfNecessary(field_list->table_defs[table_index].table_name, chColumnQuote).c_str(), 464 QuoteIfNecessary(field_list->names[i], chColumnQuote).c_str() ); 465 break; 466 } 467 } 468 } 469 else if( field_index != -1 ) 470 { 471 // We deliberately browse through the list starting from the end 472 // This is for the case where the FID column exists both as 473 // FID and then real_fid_name. We want real_fid_name to be used 474 for( int i = field_list->count - 1; i >= 0; i-- ) 475 { 476 if( field_list->table_ids[i] == table_index && 477 field_list->ids[i] == field_index ) 478 { 479 osExpr.Printf( "%s", QuoteIfNecessary(field_list->names[i], chColumnQuote).c_str() ); 480 break; 481 } 482 } 483 } 484 485 if( osExpr.empty() ) 486 { 487 return CPLStrdup(CPLSPrintf("%c%c", chColumnQuote, chColumnQuote)); 488 } 489 490 // The string is just alphanum and not a reserved SQL keyword, 491 // no needs to quote and escape. 492 return CPLStrdup(osExpr.c_str()); 493 } 494 495 /* -------------------------------------------------------------------- */ 496 /* Operation - start by unparsing all the subexpressions. */ 497 /* -------------------------------------------------------------------- */ 498 std::vector<char*> apszSubExpr; 499 apszSubExpr.reserve(nSubExprCount); 500 for( int i = 0; i < nSubExprCount; i++ ) 501 apszSubExpr.push_back( papoSubExpr[i]->Unparse(field_list, chColumnQuote) ); 502 503 osExpr = UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]); 504 505 /* -------------------------------------------------------------------- */ 506 /* cleanup subexpressions. */ 507 /* -------------------------------------------------------------------- */ 508 for( int i = 0; i < nSubExprCount; i++ ) 509 CPLFree( apszSubExpr[i] ); 510 511 return CPLStrdup( osExpr.c_str() ); 512 } 513 514 /************************************************************************/ 515 /* UnparseOperationFromUnparsedSubExpr() */ 516 /************************************************************************/ 517 518 CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr) 519 { 520 CPLString osExpr; 521 522 /* -------------------------------------------------------------------- */ 523 /* Put things together in a fashion depending on the operator. */ 524 /* -------------------------------------------------------------------- */ 525 const swq_operation *poOp = 526 swq_op_registrar::GetOperator( nOperation ); 527 528 if( poOp == nullptr && nOperation != SWQ_CUSTOM_FUNC ) 529 { 530 CPLAssert( false ); 531 return osExpr; 532 } 533 534 switch( nOperation ) 535 { 536 // Binary infix operators. 537 case SWQ_OR: 538 case SWQ_AND: 539 case SWQ_EQ: 540 case SWQ_NE: 541 case SWQ_GT: 542 case SWQ_LT: 543 case SWQ_GE: 544 case SWQ_LE: 545 case SWQ_LIKE: 546 case SWQ_ILIKE: 547 case SWQ_ADD: 548 case SWQ_SUBTRACT: 549 case SWQ_MULTIPLY: 550 case SWQ_DIVIDE: 551 case SWQ_MODULUS: 552 CPLAssert( nSubExprCount >= 2 ); 553 if( papoSubExpr[0]->eNodeType == SNT_COLUMN || 554 papoSubExpr[0]->eNodeType == SNT_CONSTANT ) 555 { 556 osExpr += apszSubExpr[0]; 557 } 558 else 559 { 560 osExpr += "("; 561 osExpr += apszSubExpr[0]; 562 osExpr += ")"; 563 } 564 osExpr += " "; 565 osExpr += poOp->pszName; 566 osExpr += " "; 567 if( papoSubExpr[1]->eNodeType == SNT_COLUMN || 568 papoSubExpr[1]->eNodeType == SNT_CONSTANT ) 569 { 570 osExpr += apszSubExpr[1]; 571 } 572 else 573 { 574 osExpr += "("; 575 osExpr += apszSubExpr[1]; 576 osExpr += ")"; 577 } 578 if( (nOperation == SWQ_LIKE || nOperation == SWQ_ILIKE) && nSubExprCount == 3 ) 579 osExpr += CPLSPrintf( " ESCAPE (%s)", apszSubExpr[2] ); 580 break; 581 582 case SWQ_NOT: 583 CPLAssert( nSubExprCount == 1 ); 584 osExpr.Printf( "NOT (%s)", apszSubExpr[0] ); 585 break; 586 587 case SWQ_ISNULL: 588 CPLAssert( nSubExprCount == 1 ); 589 osExpr.Printf( "%s IS NULL", apszSubExpr[0] ); 590 break; 591 592 case SWQ_IN: 593 osExpr.Printf( "%s IN (", apszSubExpr[0] ); 594 for( int i = 1; i < nSubExprCount; i++ ) 595 { 596 if( i > 1 ) 597 osExpr += ","; 598 osExpr += "("; 599 osExpr += apszSubExpr[i]; 600 osExpr += ")"; 601 } 602 osExpr += ")"; 603 break; 604 605 case SWQ_BETWEEN: 606 CPLAssert( nSubExprCount == 3 ); 607 osExpr.Printf( "%s %s (%s) AND (%s)", 608 apszSubExpr[0], 609 poOp->pszName, 610 apszSubExpr[1], 611 apszSubExpr[2] ); 612 break; 613 614 case SWQ_CAST: 615 osExpr = "CAST("; 616 for( int i = 0; i < nSubExprCount; i++ ) 617 { 618 if( i == 1 ) 619 osExpr += " AS "; 620 else if( i > 2 ) 621 osExpr += ", "; 622 623 const int nLen = static_cast<int>(strlen(apszSubExpr[i])); 624 if( (i == 1 && 625 (apszSubExpr[i][0] == '\'' && 626 nLen > 2 && apszSubExpr[i][nLen-1] == '\'')) || 627 (i == 2 && EQUAL(apszSubExpr[1], "'GEOMETRY")) ) 628 { 629 apszSubExpr[i][nLen-1] = '\0'; 630 osExpr += apszSubExpr[i] + 1; 631 } 632 else 633 osExpr += apszSubExpr[i]; 634 635 if( i == 1 && nSubExprCount > 2) 636 osExpr += "("; 637 else if( i > 1 && i == nSubExprCount - 1 ) 638 osExpr += ")"; 639 } 640 osExpr += ")"; 641 break; 642 643 default: // function style. 644 if( nOperation != SWQ_CUSTOM_FUNC ) 645 osExpr.Printf( "%s(", poOp->pszName ); 646 else 647 osExpr.Printf( "%s(", string_value ); 648 for( int i = 0; i < nSubExprCount; i++ ) 649 { 650 if( i > 0 ) 651 osExpr += ","; 652 osExpr += "("; 653 osExpr += apszSubExpr[i]; 654 osExpr += ")"; 655 } 656 osExpr += ")"; 657 break; 658 } 659 660 return osExpr; 661 } 662 663 /************************************************************************/ 664 /* Clone() */ 665 /************************************************************************/ 666 667 swq_expr_node *swq_expr_node::Clone() 668 { 669 swq_expr_node* poRetNode = new swq_expr_node(); 670 671 poRetNode->eNodeType = eNodeType; 672 poRetNode->field_type = field_type; 673 if( eNodeType == SNT_OPERATION ) 674 { 675 poRetNode->nOperation = nOperation; 676 poRetNode->nSubExprCount = nSubExprCount; 677 poRetNode->papoSubExpr = static_cast<swq_expr_node **>( 678 CPLMalloc( sizeof(void*) * nSubExprCount )); 679 for( int i = 0; i < nSubExprCount; i++ ) 680 poRetNode->papoSubExpr[i] = papoSubExpr[i]->Clone(); 681 } 682 else if( eNodeType == SNT_COLUMN ) 683 { 684 poRetNode->field_index = field_index; 685 poRetNode->table_index = table_index; 686 poRetNode->table_name = table_name ? CPLStrdup(table_name) : nullptr; 687 } 688 else if( eNodeType == SNT_CONSTANT ) 689 { 690 poRetNode->is_null = is_null; 691 poRetNode->int_value = int_value; 692 poRetNode->float_value = float_value; 693 if( geometry_value ) 694 poRetNode->geometry_value = geometry_value->clone(); 695 else 696 poRetNode->geometry_value = nullptr; 697 } 698 poRetNode->string_value = string_value ? CPLStrdup(string_value) : nullptr; 699 return poRetNode; 700 } 701 702 /************************************************************************/ 703 /* Evaluate() */ 704 /************************************************************************/ 705 706 swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher, 707 void *pRecord ) 708 709 { 710 return Evaluate(pfnFetcher, pRecord, 0); 711 } 712 713 swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher, 714 void *pRecord, int nRecLevel ) 715 716 { 717 swq_expr_node *poRetNode = nullptr; 718 if( nRecLevel == 32 ) 719 { 720 CPLError(CE_Failure, CPLE_AppDefined, 721 "Too many recursion levels in expression"); 722 return nullptr; 723 } 724 725 /* -------------------------------------------------------------------- */ 726 /* Duplicate ourselves if we are already a constant. */ 727 /* -------------------------------------------------------------------- */ 728 if( eNodeType == SNT_CONSTANT ) 729 { 730 return Clone(); 731 } 732 733 /* -------------------------------------------------------------------- */ 734 /* If this is a field value from a record, fetch and return it. */ 735 /* -------------------------------------------------------------------- */ 736 if( eNodeType == SNT_COLUMN ) 737 { 738 return pfnFetcher( this, pRecord ); 739 } 740 741 /* -------------------------------------------------------------------- */ 742 /* This is an operation, collect the arguments keeping track of */ 743 /* which we will need to free. */ 744 /* -------------------------------------------------------------------- */ 745 std::vector<swq_expr_node*> apoValues; 746 std::vector<int> anValueNeedsFree; 747 bool bError = false; 748 apoValues.reserve(nSubExprCount); 749 for( int i = 0; i < nSubExprCount && !bError; i++ ) 750 { 751 if( papoSubExpr[i]->eNodeType == SNT_CONSTANT ) 752 { 753 // avoid duplication. 754 apoValues.push_back( papoSubExpr[i] ); 755 anValueNeedsFree.push_back( FALSE ); 756 } 757 else 758 { 759 swq_expr_node* poSubExprVal = 760 papoSubExpr[i]->Evaluate(pfnFetcher, pRecord, nRecLevel + 1); 761 if( poSubExprVal == nullptr ) 762 bError = true; 763 else 764 { 765 apoValues.push_back(poSubExprVal); 766 anValueNeedsFree.push_back( TRUE ); 767 } 768 } 769 } 770 771 /* -------------------------------------------------------------------- */ 772 /* Fetch the operator definition and function. */ 773 /* -------------------------------------------------------------------- */ 774 if( !bError ) 775 { 776 const swq_operation *poOp = 777 swq_op_registrar::GetOperator( nOperation ); 778 if( poOp == nullptr ) 779 { 780 if( nOperation == SWQ_CUSTOM_FUNC ) 781 CPLError( CE_Failure, CPLE_AppDefined, 782 "Evaluate(): Unable to find definition for operator %s.", 783 string_value ); 784 else 785 CPLError( 786 CE_Failure, CPLE_AppDefined, 787 "Evaluate(): Unable to find definition for operator %d.", 788 nOperation ); 789 poRetNode = nullptr; 790 } 791 else 792 poRetNode = poOp->pfnEvaluator( this, &(apoValues[0]) ); 793 } 794 795 /* -------------------------------------------------------------------- */ 796 /* Cleanup */ 797 /* -------------------------------------------------------------------- */ 798 for( int i = 0; i < static_cast<int>(apoValues.size()); i++ ) 799 { 800 if( anValueNeedsFree[i] ) 801 delete apoValues[i]; 802 } 803 804 return poRetNode; 805 } 806 807 /************************************************************************/ 808 /* ReplaceBetweenByGEAndLERecurse() */ 809 /************************************************************************/ 810 811 void swq_expr_node::ReplaceBetweenByGEAndLERecurse() 812 { 813 if( eNodeType != SNT_OPERATION ) 814 return; 815 816 if( nOperation != SWQ_BETWEEN ) 817 { 818 for( int i = 0; i < nSubExprCount; i++ ) 819 papoSubExpr[i]->ReplaceBetweenByGEAndLERecurse(); 820 return; 821 } 822 823 if( nSubExprCount != 3 ) 824 return; 825 826 swq_expr_node* poExpr0 = papoSubExpr[0]; 827 swq_expr_node* poExpr1 = papoSubExpr[1]; 828 swq_expr_node* poExpr2 = papoSubExpr[2]; 829 830 nSubExprCount = 2; 831 nOperation = SWQ_AND; 832 papoSubExpr[0] = new swq_expr_node(SWQ_GE); 833 papoSubExpr[0]->PushSubExpression(poExpr0); 834 papoSubExpr[0]->PushSubExpression(poExpr1); 835 papoSubExpr[1] = new swq_expr_node(SWQ_LE); 836 papoSubExpr[1]->PushSubExpression(poExpr0->Clone()); 837 papoSubExpr[1]->PushSubExpression(poExpr2); 838 } 839 840 #endif // #ifndef DOXYGEN_SKIP 841