1 /******************************************************************************
2 *
3 * Component: OGR SQL Engine
4 * Purpose: Implementation of SWQGeneralEvaluator and SWQGeneralChecker
5 * functions used to represent functions during evaluation and
6 * parsing.
7 * Author: Frank Warmerdam <warmerdam@pobox.com>
8 *
9 ******************************************************************************
10 * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
11 * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included
21 * in all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 * DEALINGS IN THE SOFTWARE.
30 ****************************************************************************/
31
32 #include "cpl_port.h"
33 #include "ogr_swq.h"
34
35 #include <cctype>
36 #include <climits>
37 #include <cstdlib>
38 #include <cstring>
39 #include <string>
40
41 #include "cpl_conv.h"
42 #include "cpl_error.h"
43 #include "cpl_safemaths.hpp"
44 #include "cpl_string.h"
45 #include "ogr_geometry.h"
46 #include "ogr_p.h"
47
48 CPL_CVSID("$Id: swq_op_general.cpp 1a4fb15774d859246108c42c8392a3f9d180821c 2021-06-14 19:24:54 +0200 Alessandro Pasotti $")
49
50 /************************************************************************/
51 /* swq_test_like() */
52 /* */
53 /* Does input match pattern? */
54 /************************************************************************/
55
swq_test_like(const char * input,const char * pattern,char chEscape,bool insensitive)56 static int swq_test_like( const char *input, const char *pattern,
57 char chEscape, bool insensitive )
58
59 {
60 if( input == nullptr || pattern == nullptr )
61 return 0;
62
63 while( *input != '\0' )
64 {
65 if( *pattern == '\0' )
66 return 0;
67
68 else if( *pattern == chEscape )
69 {
70 pattern++;
71 if( *pattern == '\0' )
72 return 0;
73 if( (!insensitive && *pattern != *input) ||
74 (insensitive && tolower(*pattern) != tolower(*input)) )
75 {
76 return 0;
77 }
78 else
79 {
80 input++;
81 pattern++;
82 }
83 }
84
85 else if( *pattern == '_' )
86 {
87 input++;
88 pattern++;
89 }
90 else if( *pattern == '%' )
91 {
92 if( pattern[1] == '\0' )
93 return 1;
94
95 // Try eating varying amounts of the input till we get a positive.
96 for( int eat = 0; input[eat] != '\0'; eat++ )
97 {
98 if( swq_test_like(input + eat, pattern + 1, chEscape, insensitive) )
99 return 1;
100 }
101
102 return 0;
103 }
104 else
105 {
106 if( (!insensitive && *pattern != *input) ||
107 (insensitive && tolower(*pattern) != tolower(*input)) )
108 {
109 return 0;
110 }
111 else
112 {
113 input++;
114 pattern++;
115 }
116 }
117 }
118
119 if( *pattern != '\0' && strcmp(pattern, "%") != 0 )
120 return 0;
121 else
122 return 1;
123 }
124
125 /************************************************************************/
126 /* OGRHStoreGetValue() */
127 /************************************************************************/
128
OGRHStoreCheckEnd(char * pszIter,int bIsKey)129 static char* OGRHStoreCheckEnd( char* pszIter, int bIsKey )
130 {
131 pszIter++;
132 for( ; *pszIter != '\0'; pszIter ++ )
133 {
134 if( bIsKey )
135 {
136 if( *pszIter == ' ' )
137 {
138 ;
139 }
140 else if( *pszIter == '=' && pszIter[1] == '>' )
141 {
142 return pszIter + 2;
143 }
144 else
145 {
146 return nullptr;
147 }
148 }
149 else
150 {
151 if( *pszIter == ' ' )
152 {
153 ;
154 }
155 else if( *pszIter == ',' )
156 {
157 return pszIter + 1;
158 }
159 else
160 {
161 return nullptr;
162 }
163 }
164 }
165 return pszIter;
166 }
167
OGRHStoreGetNextString(char * pszIter,char ** ppszOut,int bIsKey)168 static char* OGRHStoreGetNextString( char* pszIter,
169 char** ppszOut,
170 int bIsKey )
171 {
172 char ch;
173 bool bInString = false;
174 char* pszOut = nullptr;
175 *ppszOut = nullptr;
176 for( ; (ch = *pszIter) != '\0'; pszIter ++ )
177 {
178 if( bInString )
179 {
180 if( ch == '"' )
181 {
182 *pszOut = '\0';
183 return OGRHStoreCheckEnd(pszIter, bIsKey);
184 }
185 else if( ch == '\\')
186 {
187 pszIter++;
188 if( (ch = *pszIter) == '\0' )
189 return nullptr;
190 }
191 *pszOut = ch;
192 pszOut++;
193 }
194 else
195 {
196 if( ch == ' ' )
197 {
198 if( pszOut != nullptr )
199 {
200 *pszIter = '\0';
201 return OGRHStoreCheckEnd(pszIter, bIsKey);
202 }
203 }
204 else if( bIsKey && ch == '=' && pszIter[1] == '>' )
205 {
206 if( pszOut != nullptr )
207 {
208 *pszIter = '\0';
209 return pszIter + 2;
210 }
211 }
212 else if( !bIsKey && ch == ',' )
213 {
214 if( pszOut != nullptr )
215 {
216 *pszIter = '\0';
217 return pszIter + 1;
218 }
219 }
220 else if( ch == '"' )
221 {
222 pszOut = pszIter + 1;
223 *ppszOut = pszOut;
224 bInString = true;
225 }
226 else if( pszOut == nullptr )
227 {
228 pszOut = pszIter;
229 *ppszOut = pszIter;
230 }
231 }
232 }
233
234 if( !bInString && pszOut != nullptr )
235 {
236 return pszIter;
237 }
238 return nullptr;
239 }
240
OGRHStoreGetNextKeyValue(char * pszHStore,char ** ppszKey,char ** ppszValue)241 static char* OGRHStoreGetNextKeyValue(char* pszHStore,
242 char** ppszKey,
243 char** ppszValue)
244 {
245 char* pszNext = OGRHStoreGetNextString(pszHStore, ppszKey, TRUE);
246 if( pszNext == nullptr || *pszNext == '\0' )
247 return nullptr;
248 return OGRHStoreGetNextString(pszNext, ppszValue, FALSE);
249 }
250
OGRHStoreGetValue(const char * pszHStore,const char * pszSearchedKey)251 char* OGRHStoreGetValue(const char* pszHStore, const char* pszSearchedKey)
252 {
253 char* pszHStoreDup = CPLStrdup(pszHStore);
254 char* pszHStoreIter = pszHStoreDup;
255 char* pszRet = nullptr;
256
257 while( true )
258 {
259 char* pszKey, *pszValue;
260 pszHStoreIter = OGRHStoreGetNextKeyValue(pszHStoreIter, &pszKey, &pszValue);
261 if( pszHStoreIter == nullptr )
262 {
263 break;
264 }
265 if( strcmp(pszKey, pszSearchedKey) == 0 )
266 {
267 pszRet = CPLStrdup(pszValue);
268 break;
269 }
270 if( *pszHStoreIter == '\0' )
271 {
272 break;
273 }
274 }
275 CPLFree(pszHStoreDup);
276 return pszRet;
277 }
278
279 #ifdef DEBUG_VERBOSE
280 /************************************************************************/
281 /* OGRFormatDate() */
282 /************************************************************************/
283
OGRFormatDate(const OGRField * psField)284 static const char * OGRFormatDate(const OGRField *psField)
285 {
286 return CPLSPrintf("%04d/%02d/%02d %02d:%02d:%06.3f",
287 psField->Date.Year,
288 psField->Date.Month,
289 psField->Date.Day,
290 psField->Date.Hour,
291 psField->Date.Minute,
292 psField->Date.Second );
293 }
294 #endif
295
296 /************************************************************************/
297 /* SWQGeneralEvaluator() */
298 /************************************************************************/
299
SWQGeneralEvaluator(swq_expr_node * node,swq_expr_node ** sub_node_values)300 swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
301 swq_expr_node **sub_node_values )
302
303 {
304 swq_expr_node *poRet = nullptr;
305
306 /* -------------------------------------------------------------------- */
307 /* Floating point operations. */
308 /* -------------------------------------------------------------------- */
309 if( sub_node_values[0]->field_type == SWQ_FLOAT
310 || (node->nSubExprCount > 1
311 && sub_node_values[1]->field_type == SWQ_FLOAT) )
312 {
313 poRet = new swq_expr_node(0);
314 poRet->field_type = node->field_type;
315
316 if( SWQ_IS_INTEGER(sub_node_values[0]->field_type) )
317 sub_node_values[0]->float_value =
318 static_cast<double>(sub_node_values[0]->int_value);
319 if( node->nSubExprCount > 1 &&
320 SWQ_IS_INTEGER(sub_node_values[1]->field_type) )
321 sub_node_values[1]->float_value =
322 static_cast<double>(sub_node_values[1]->int_value);
323
324 if( node->nOperation != SWQ_ISNULL )
325 {
326 for( int i = 0; i < node->nSubExprCount; i++ )
327 {
328 if( sub_node_values[i]->is_null )
329 {
330 if( poRet->field_type == SWQ_BOOLEAN )
331 {
332 poRet->int_value = FALSE;
333 return poRet;
334 }
335 else if( poRet->field_type == SWQ_FLOAT )
336 {
337 poRet->float_value = 0;
338 poRet->is_null = 1;
339 return poRet;
340 }
341 else if( SWQ_IS_INTEGER(poRet->field_type) )
342 {
343 poRet->field_type = SWQ_INTEGER;
344 poRet->int_value = 0;
345 poRet->is_null = 1;
346 return poRet;
347 }
348 }
349 }
350 }
351
352 switch( node->nOperation )
353 {
354 case SWQ_EQ:
355 poRet->int_value = sub_node_values[0]->float_value
356 == sub_node_values[1]->float_value;
357 break;
358
359 case SWQ_NE:
360 poRet->int_value = sub_node_values[0]->float_value
361 != sub_node_values[1]->float_value;
362 break;
363
364 case SWQ_GT:
365 poRet->int_value = sub_node_values[0]->float_value
366 > sub_node_values[1]->float_value;
367 break;
368
369 case SWQ_LT:
370 poRet->int_value = sub_node_values[0]->float_value
371 < sub_node_values[1]->float_value;
372 break;
373
374 case SWQ_GE:
375 poRet->int_value = sub_node_values[0]->float_value
376 >= sub_node_values[1]->float_value;
377 break;
378
379 case SWQ_LE:
380 poRet->int_value = sub_node_values[0]->float_value
381 <= sub_node_values[1]->float_value;
382 break;
383
384 case SWQ_IN:
385 {
386 poRet->int_value = 0;
387 for( int i = 1; i < node->nSubExprCount; i++ )
388 {
389 if( sub_node_values[0]->float_value
390 == sub_node_values[i]->float_value )
391 {
392 poRet->int_value = 1;
393 break;
394 }
395 }
396 }
397 break;
398
399 case SWQ_BETWEEN:
400 poRet->int_value = sub_node_values[0]->float_value
401 >= sub_node_values[1]->float_value &&
402 sub_node_values[0]->float_value
403 <= sub_node_values[2]->float_value;
404 break;
405
406 case SWQ_ISNULL:
407 poRet->int_value = sub_node_values[0]->is_null;
408 break;
409
410 case SWQ_ADD:
411 poRet->float_value = sub_node_values[0]->float_value
412 + sub_node_values[1]->float_value;
413 break;
414
415 case SWQ_SUBTRACT:
416 poRet->float_value = sub_node_values[0]->float_value
417 - sub_node_values[1]->float_value;
418 break;
419
420 case SWQ_MULTIPLY:
421 poRet->float_value = sub_node_values[0]->float_value
422 * sub_node_values[1]->float_value;
423 break;
424
425 case SWQ_DIVIDE:
426 if( sub_node_values[1]->float_value == 0 )
427 poRet->float_value = INT_MAX;
428 else
429 poRet->float_value = sub_node_values[0]->float_value
430 / sub_node_values[1]->float_value;
431 break;
432
433 case SWQ_MODULUS:
434 {
435 if( sub_node_values[1]->float_value == 0 )
436 poRet->float_value = INT_MAX;
437 else
438 poRet->float_value = fmod(sub_node_values[0]->float_value,
439 sub_node_values[1]->float_value);
440 break;
441 }
442
443 default:
444 CPLAssert( false );
445 delete poRet;
446 poRet = nullptr;
447 break;
448 }
449 }
450 /* -------------------------------------------------------------------- */
451 /* integer/boolean operations. */
452 /* -------------------------------------------------------------------- */
453 else if( SWQ_IS_INTEGER(sub_node_values[0]->field_type)
454 || sub_node_values[0]->field_type == SWQ_BOOLEAN )
455 {
456 poRet = new swq_expr_node(0);
457 poRet->field_type = node->field_type;
458
459 if( node->nOperation != SWQ_ISNULL )
460 {
461 for( int i = 0; i < node->nSubExprCount; i++ )
462 {
463 if( sub_node_values[i]->is_null )
464 {
465 if( poRet->field_type == SWQ_BOOLEAN )
466 {
467 poRet->int_value = FALSE;
468 return poRet;
469 }
470 else if( SWQ_IS_INTEGER(poRet->field_type) )
471 {
472 poRet->int_value = 0;
473 poRet->is_null = 1;
474 return poRet;
475 }
476 }
477 }
478 }
479
480 switch( node->nOperation )
481 {
482 case SWQ_AND:
483 poRet->int_value = sub_node_values[0]->int_value
484 && sub_node_values[1]->int_value;
485 break;
486
487 case SWQ_OR:
488 poRet->int_value = sub_node_values[0]->int_value
489 || sub_node_values[1]->int_value;
490 break;
491
492 case SWQ_NOT:
493 poRet->int_value = !sub_node_values[0]->int_value;
494 break;
495
496 case SWQ_EQ:
497 poRet->int_value = sub_node_values[0]->int_value
498 == sub_node_values[1]->int_value;
499 break;
500
501 case SWQ_NE:
502 poRet->int_value = sub_node_values[0]->int_value
503 != sub_node_values[1]->int_value;
504 break;
505
506 case SWQ_GT:
507 poRet->int_value = sub_node_values[0]->int_value
508 > sub_node_values[1]->int_value;
509 break;
510
511 case SWQ_LT:
512 poRet->int_value = sub_node_values[0]->int_value
513 < sub_node_values[1]->int_value;
514 break;
515
516 case SWQ_GE:
517 poRet->int_value = sub_node_values[0]->int_value
518 >= sub_node_values[1]->int_value;
519 break;
520
521 case SWQ_LE:
522 poRet->int_value = sub_node_values[0]->int_value
523 <= sub_node_values[1]->int_value;
524 break;
525
526 case SWQ_IN:
527 {
528 poRet->int_value = 0;
529 for( int i = 1; i < node->nSubExprCount; i++ )
530 {
531 if( sub_node_values[0]->int_value
532 == sub_node_values[i]->int_value )
533 {
534 poRet->int_value = 1;
535 break;
536 }
537 }
538 }
539 break;
540
541 case SWQ_BETWEEN:
542 poRet->int_value = sub_node_values[0]->int_value
543 >= sub_node_values[1]->int_value &&
544 sub_node_values[0]->int_value
545 <= sub_node_values[2]->int_value;
546 break;
547
548 case SWQ_ISNULL:
549 poRet->int_value = sub_node_values[0]->is_null;
550 break;
551
552 case SWQ_ADD:
553 try
554 {
555 poRet->int_value = (CPLSM(sub_node_values[0]->int_value)
556 + CPLSM(sub_node_values[1]->int_value)).v();
557 }
558 catch( const std::exception& )
559 {
560 CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
561 poRet->is_null = true;
562 }
563 break;
564
565 case SWQ_SUBTRACT:
566 try
567 {
568 poRet->int_value = (CPLSM(sub_node_values[0]->int_value)
569 - CPLSM(sub_node_values[1]->int_value)).v();
570 }
571 catch( const std::exception& )
572 {
573 CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
574 poRet->is_null = true;
575 }
576 break;
577
578 case SWQ_MULTIPLY:
579 try
580 {
581 poRet->int_value = (CPLSM(sub_node_values[0]->int_value)
582 * CPLSM(sub_node_values[1]->int_value)).v();
583 }
584 catch( const std::exception& )
585 {
586 CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
587 poRet->is_null = true;
588 }
589 break;
590
591 case SWQ_DIVIDE:
592 if( sub_node_values[1]->int_value == 0 )
593 poRet->int_value = INT_MAX;
594 else
595 {
596 try
597 {
598 poRet->int_value = (CPLSM(sub_node_values[0]->int_value)
599 / CPLSM(sub_node_values[1]->int_value)).v();
600 }
601 catch( const std::exception& )
602 {
603 CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
604 poRet->is_null = true;
605 }
606 }
607 break;
608
609 case SWQ_MODULUS:
610 if( sub_node_values[1]->int_value == 0 )
611 poRet->int_value = INT_MAX;
612 else
613 poRet->int_value = sub_node_values[0]->int_value
614 % sub_node_values[1]->int_value;
615 break;
616
617 default:
618 CPLAssert( false );
619 delete poRet;
620 poRet = nullptr;
621 break;
622 }
623 }
624
625 /* -------------------------------------------------------------------- */
626 /* datetime */
627 /* -------------------------------------------------------------------- */
628 else if( sub_node_values[0]->field_type == SWQ_TIMESTAMP
629 && (node->nOperation == SWQ_EQ
630 || node->nOperation == SWQ_GT
631 || node->nOperation == SWQ_GE
632 || node->nOperation == SWQ_LT
633 || node->nOperation == SWQ_LE
634 || node->nOperation == SWQ_IN
635 || node->nOperation == SWQ_BETWEEN) )
636 {
637 OGRField sField0, sField1;
638 poRet = new swq_expr_node(0);
639 poRet->field_type = node->field_type;
640
641 if( !OGRParseDate(sub_node_values[0]->string_value, &sField0, 0))
642 {
643 CPLError(
644 CE_Failure, CPLE_AppDefined,
645 "Failed to parse date '%s' evaluating OGR WHERE expression",
646 sub_node_values[0]->string_value);
647 delete poRet;
648 return nullptr;
649 }
650 if( !OGRParseDate(sub_node_values[1]->string_value, &sField1, 0))
651 {
652 CPLError(
653 CE_Failure, CPLE_AppDefined,
654 "Failed to parse date '%s' evaluating OGR WHERE expression",
655 sub_node_values[1]->string_value);
656 delete poRet;
657 return nullptr;
658 }
659
660 switch( node->nOperation )
661 {
662 case SWQ_GT:
663 poRet->int_value = OGRCompareDate(&sField0, &sField1) > 0;
664 break;
665
666 case SWQ_GE:
667 poRet->int_value = OGRCompareDate(&sField0, &sField1) >= 0;
668 break;
669
670 case SWQ_LT:
671 poRet->int_value = OGRCompareDate(&sField0, &sField1) < 0;
672 break;
673
674 case SWQ_LE:
675 poRet->int_value = OGRCompareDate(&sField0, &sField1) <= 0;
676 break;
677
678 case SWQ_EQ:
679 poRet->int_value = OGRCompareDate(&sField0, &sField1) == 0;
680 break;
681
682 case SWQ_BETWEEN:
683 {
684 OGRField sField2;
685 if( !OGRParseDate(sub_node_values[2]->string_value, &sField2, 0) )
686 {
687 CPLError(
688 CE_Failure, CPLE_AppDefined,
689 "Failed to parse date '%s' evaluating OGR WHERE expression",
690 sub_node_values[2]->string_value);
691 delete poRet;
692 return nullptr;
693 }
694
695 poRet->int_value =
696 (OGRCompareDate(&sField0, &sField1) >= 0)
697 && (OGRCompareDate(&sField0, &sField2) <= 0);
698 }
699 break;
700
701 case SWQ_IN:
702 {
703 OGRField sFieldIn;
704 bool bFound = false;
705 for( int i = 1; i < node->nSubExprCount; ++i )
706 {
707 if( !OGRParseDate(sub_node_values[i]->string_value, &sFieldIn, 0) )
708 {
709 CPLError(
710 CE_Failure, CPLE_AppDefined,
711 "Failed to parse date '%s' evaluating OGR WHERE expression",
712 sub_node_values[i]->string_value);
713 delete poRet;
714 return nullptr;
715 }
716 if ( OGRCompareDate(&sField0, &sFieldIn) == 0 )
717 {
718 bFound = true;
719 break;
720 }
721 }
722 poRet->int_value = bFound;
723 }
724 break;
725
726 default:
727 CPLAssert( false );
728 delete poRet;
729 poRet = nullptr;
730 break;
731 }
732 }
733
734 /* -------------------------------------------------------------------- */
735 /* String operations. */
736 /* -------------------------------------------------------------------- */
737 else
738 {
739 poRet = new swq_expr_node(0);
740 poRet->field_type = node->field_type;
741
742 if( node->nOperation != SWQ_ISNULL )
743 {
744 for( int i = 0; i < node->nSubExprCount; i++ )
745 {
746 if( sub_node_values[i]->is_null )
747 {
748 if( poRet->field_type == SWQ_BOOLEAN )
749 {
750 poRet->int_value = FALSE;
751 return poRet;
752 }
753 else if( poRet->field_type == SWQ_STRING )
754 {
755 poRet->string_value = CPLStrdup("");
756 poRet->is_null = 1;
757 return poRet;
758 }
759 }
760 }
761 }
762
763 switch( node->nOperation )
764 {
765 case SWQ_EQ:
766 {
767 // When comparing timestamps, the +00 at the end might be discarded
768 // if the other member has no explicit timezone.
769 if( (sub_node_values[0]->field_type == SWQ_TIMESTAMP ||
770 sub_node_values[0]->field_type == SWQ_STRING) &&
771 (sub_node_values[1]->field_type == SWQ_TIMESTAMP ||
772 sub_node_values[1]->field_type == SWQ_STRING) &&
773 strlen(sub_node_values[0]->string_value) > 3 &&
774 strlen(sub_node_values[1]->string_value) > 3 &&
775 (strcmp(sub_node_values[0]->string_value + strlen(sub_node_values[0]->string_value)-3, "+00") == 0 &&
776 sub_node_values[1]->string_value[strlen(sub_node_values[1]->string_value)-3] == ':') )
777 {
778 poRet->int_value =
779 EQUALN(sub_node_values[0]->string_value,
780 sub_node_values[1]->string_value,
781 strlen(sub_node_values[1]->string_value));
782 }
783 else if( (sub_node_values[0]->field_type == SWQ_TIMESTAMP ||
784 sub_node_values[0]->field_type == SWQ_STRING) &&
785 (sub_node_values[1]->field_type == SWQ_TIMESTAMP ||
786 sub_node_values[1]->field_type == SWQ_STRING) &&
787 strlen(sub_node_values[0]->string_value) > 3 &&
788 strlen(sub_node_values[1]->string_value) > 3 &&
789 (sub_node_values[0]->string_value[strlen(sub_node_values[0]->string_value)-3] == ':') &&
790 strcmp(sub_node_values[1]->string_value + strlen(sub_node_values[1]->string_value)-3, "+00") == 0)
791 {
792 poRet->int_value =
793 EQUALN(sub_node_values[0]->string_value,
794 sub_node_values[1]->string_value,
795 strlen(sub_node_values[0]->string_value));
796 }
797 else
798 {
799 poRet->int_value =
800 strcasecmp(sub_node_values[0]->string_value,
801 sub_node_values[1]->string_value) == 0;
802 }
803 break;
804 }
805
806 case SWQ_NE:
807 poRet->int_value =
808 strcasecmp(sub_node_values[0]->string_value,
809 sub_node_values[1]->string_value) != 0;
810 break;
811
812 case SWQ_GT:
813 poRet->int_value =
814 strcasecmp(sub_node_values[0]->string_value,
815 sub_node_values[1]->string_value) > 0;
816 break;
817
818 case SWQ_LT:
819 poRet->int_value =
820 strcasecmp(sub_node_values[0]->string_value,
821 sub_node_values[1]->string_value) < 0;
822 break;
823
824 case SWQ_GE:
825 poRet->int_value =
826 strcasecmp(sub_node_values[0]->string_value,
827 sub_node_values[1]->string_value) >= 0;
828 break;
829
830 case SWQ_LE:
831 poRet->int_value =
832 strcasecmp(sub_node_values[0]->string_value,
833 sub_node_values[1]->string_value) <= 0;
834 break;
835
836 case SWQ_IN:
837 {
838 poRet->int_value = 0;
839 for( int i = 1; i < node->nSubExprCount; i++ )
840 {
841 if( strcasecmp(sub_node_values[0]->string_value,
842 sub_node_values[i]->string_value) == 0 )
843 {
844 poRet->int_value = 1;
845 break;
846 }
847 }
848 }
849 break;
850
851 case SWQ_BETWEEN:
852 poRet->int_value =
853 strcasecmp(sub_node_values[0]->string_value,
854 sub_node_values[1]->string_value) >= 0 &&
855 strcasecmp(sub_node_values[0]->string_value,
856 sub_node_values[2]->string_value) <= 0;
857 break;
858
859 case SWQ_LIKE:
860 {
861 char chEscape = '\0';
862 if( node->nSubExprCount == 3 )
863 chEscape = sub_node_values[2]->string_value[0];
864 const bool bInsensitive =
865 CPLTestBool(CPLGetConfigOption("OGR_SQL_LIKE_AS_ILIKE", "FALSE"));
866 poRet->int_value = swq_test_like(sub_node_values[0]->string_value,
867 sub_node_values[1]->string_value,
868 chEscape, bInsensitive);
869 break;
870 }
871
872 case SWQ_ILIKE:
873 {
874 char chEscape = '\0';
875 if( node->nSubExprCount == 3 )
876 chEscape = sub_node_values[2]->string_value[0];
877 poRet->int_value = swq_test_like(sub_node_values[0]->string_value,
878 sub_node_values[1]->string_value,
879 chEscape, true);
880 break;
881 }
882
883 case SWQ_ISNULL:
884 poRet->int_value = sub_node_values[0]->is_null;
885 break;
886
887 case SWQ_CONCAT:
888 case SWQ_ADD:
889 {
890 CPLString osResult = sub_node_values[0]->string_value;
891
892 for( int i = 1; i < node->nSubExprCount; i++ )
893 osResult += sub_node_values[i]->string_value;
894
895 poRet->string_value = CPLStrdup(osResult);
896 poRet->is_null = sub_node_values[0]->is_null;
897 break;
898 }
899
900 case SWQ_SUBSTR:
901 {
902 const char *pszSrcStr = sub_node_values[0]->string_value;
903
904 int nOffset = 0;
905 if( SWQ_IS_INTEGER(sub_node_values[1]->field_type) )
906 nOffset = static_cast<int>(sub_node_values[1]->int_value);
907 else if( sub_node_values[1]->field_type == SWQ_FLOAT )
908 nOffset = static_cast<int>(sub_node_values[1]->float_value);
909 // else
910 // nOffset = 0;
911
912 int nSize = 0;
913 if( node->nSubExprCount < 3 )
914 nSize = 100000;
915 else if( SWQ_IS_INTEGER(sub_node_values[2]->field_type) )
916 nSize = static_cast<int>(sub_node_values[2]->int_value);
917 else if( sub_node_values[2]->field_type == SWQ_FLOAT )
918 nSize = static_cast<int>(sub_node_values[2]->float_value);
919 // else
920 // nSize = 0;
921
922 const int nSrcStrLen = static_cast<int>(strlen(pszSrcStr));
923
924 // In SQL, the first character is at offset 1.
925 // 0 is considered as 1.
926 if( nOffset > 0 )
927 nOffset--;
928 // Some implementations allow negative offsets, to start
929 // from the end of the string.
930 else if( nOffset < 0 )
931 {
932 if( nSrcStrLen + nOffset >= 0 )
933 nOffset = nSrcStrLen + nOffset;
934 else
935 nOffset = 0;
936 }
937
938 if( nSize < 0 || nOffset > nSrcStrLen )
939 {
940 nOffset = 0;
941 nSize = 0;
942 }
943 else if( nOffset + nSize > nSrcStrLen )
944 nSize = nSrcStrLen - nOffset;
945
946 CPLString osResult = pszSrcStr + nOffset;
947 if( static_cast<int>(osResult.size()) > nSize )
948 osResult.resize( nSize );
949
950 poRet->string_value = CPLStrdup(osResult);
951 poRet->is_null = sub_node_values[0]->is_null;
952 break;
953 }
954
955 case SWQ_HSTORE_GET_VALUE:
956 {
957 const char *pszHStore = sub_node_values[0]->string_value;
958 const char *pszSearchedKey = sub_node_values[1]->string_value;
959 char* pszRet = OGRHStoreGetValue(pszHStore, pszSearchedKey);
960 poRet->string_value = pszRet ? pszRet : CPLStrdup("");
961 poRet->is_null = (pszRet == nullptr);
962 break;
963 }
964
965 default:
966 CPLAssert( false );
967 delete poRet;
968 poRet = nullptr;
969 break;
970 }
971 }
972
973 return poRet;
974 }
975
976 /************************************************************************/
977 /* SWQAutoPromoteIntegerToInteger64OrFloat() */
978 /************************************************************************/
979
SWQAutoPromoteIntegerToInteger64OrFloat(swq_expr_node * poNode)980 static void SWQAutoPromoteIntegerToInteger64OrFloat( swq_expr_node *poNode )
981
982 {
983 if( poNode->nSubExprCount < 2 )
984 return;
985
986 swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
987
988 // We allow mixes of integer, integer64 and float, and string and dates.
989 // When encountered, we promote integers/integer64 to floats,
990 // integer to integer64 and strings to dates. We do that now.
991 for( int i = 1; i < poNode->nSubExprCount; i++ )
992 {
993 swq_expr_node *poSubNode = poNode->papoSubExpr[i];
994 if( SWQ_IS_INTEGER(eArgType)
995 && poSubNode->field_type == SWQ_FLOAT )
996 eArgType = SWQ_FLOAT;
997 else if( eArgType == SWQ_INTEGER
998 && poSubNode->field_type == SWQ_INTEGER64 )
999 eArgType = SWQ_INTEGER64;
1000 }
1001
1002 for( int i = 0; i < poNode->nSubExprCount; i++ )
1003 {
1004 swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1005
1006 if( eArgType == SWQ_FLOAT
1007 && SWQ_IS_INTEGER(poSubNode->field_type) )
1008 {
1009 if( poSubNode->eNodeType == SNT_CONSTANT )
1010 {
1011 poSubNode->float_value = static_cast<double>(poSubNode->int_value);
1012 poSubNode->field_type = SWQ_FLOAT;
1013 }
1014 }
1015 else if( eArgType == SWQ_INTEGER64 && poSubNode->field_type == SWQ_INTEGER )
1016 {
1017 if( poSubNode->eNodeType == SNT_CONSTANT )
1018 {
1019 poSubNode->field_type = SWQ_INTEGER64;
1020 }
1021 }
1022 }
1023 }
1024
1025 /************************************************************************/
1026 /* SWQAutoPromoteStringToDateTime() */
1027 /************************************************************************/
1028
SWQAutoPromoteStringToDateTime(swq_expr_node * poNode)1029 static void SWQAutoPromoteStringToDateTime( swq_expr_node *poNode )
1030
1031 {
1032 if( poNode->nSubExprCount < 2 )
1033 return;
1034
1035 swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
1036
1037 // We allow mixes of integer and float, and string and dates.
1038 // When encountered, we promote integers to floats, and strings to
1039 // dates. We do that now.
1040 for( int i = 1; i < poNode->nSubExprCount; i++ )
1041 {
1042 swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1043
1044 if( eArgType == SWQ_STRING
1045 && (poSubNode->field_type == SWQ_DATE
1046 || poSubNode->field_type == SWQ_TIME
1047 || poSubNode->field_type == SWQ_TIMESTAMP) )
1048 eArgType = SWQ_TIMESTAMP;
1049 }
1050
1051 for( int i = 0; i < poNode->nSubExprCount; i++ )
1052 {
1053 swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1054
1055 if( eArgType == SWQ_TIMESTAMP
1056 && (poSubNode->field_type == SWQ_STRING
1057 || poSubNode->field_type == SWQ_DATE
1058 || poSubNode->field_type == SWQ_TIME) )
1059 {
1060 if( poSubNode->eNodeType == SNT_CONSTANT )
1061 {
1062 poSubNode->field_type = SWQ_TIMESTAMP;
1063 }
1064 }
1065 }
1066 }
1067
1068 /************************************************************************/
1069 /* SWQAutoConvertStringToNumeric() */
1070 /* */
1071 /* Convert string constants to integer or float constants */
1072 /* when there is a mix of arguments of type numeric and string */
1073 /************************************************************************/
1074
SWQAutoConvertStringToNumeric(swq_expr_node * poNode)1075 static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
1076
1077 {
1078 if( poNode->nSubExprCount < 2 )
1079 return;
1080
1081 swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
1082
1083 for( int i = 1; i < poNode->nSubExprCount; i++ )
1084 {
1085 swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1086
1087 // Identify the mixture of the argument type.
1088 if( (eArgType == SWQ_STRING
1089 && (SWQ_IS_INTEGER(poSubNode->field_type)
1090 || poSubNode->field_type == SWQ_FLOAT)) ||
1091 (SWQ_IS_INTEGER(eArgType)
1092 && poSubNode->field_type == SWQ_STRING) )
1093 {
1094 eArgType = SWQ_FLOAT;
1095 break;
1096 }
1097 }
1098
1099 for( int i = 0; i < poNode->nSubExprCount; i++ )
1100 {
1101 swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1102
1103 if( eArgType == SWQ_FLOAT
1104 && poSubNode->field_type == SWQ_STRING )
1105 {
1106 if( poSubNode->eNodeType == SNT_CONSTANT )
1107 {
1108 // Apply the string to numeric conversion.
1109 char* endPtr = nullptr;
1110 poSubNode->float_value =
1111 CPLStrtod(poSubNode->string_value, &endPtr);
1112 if( !(endPtr == nullptr || *endPtr == '\0') )
1113 {
1114 CPLError(CE_Warning, CPLE_NotSupported,
1115 "Conversion failed when converting the string "
1116 "value '%s' to data type float.",
1117 poSubNode->string_value);
1118 continue;
1119 }
1120
1121 // Should also fill the integer value in this case.
1122 poSubNode->int_value = static_cast<GIntBig>(poSubNode->float_value);
1123 poSubNode->field_type = SWQ_FLOAT;
1124 }
1125 }
1126 }
1127 }
1128
1129 /************************************************************************/
1130 /* SWQCheckSubExprAreNotGeometries() */
1131 /************************************************************************/
1132
SWQCheckSubExprAreNotGeometries(swq_expr_node * poNode)1133 static bool SWQCheckSubExprAreNotGeometries( swq_expr_node *poNode )
1134 {
1135 for( int i = 0; i < poNode->nSubExprCount; i++ )
1136 {
1137 if( poNode->papoSubExpr[i]->field_type == SWQ_GEOMETRY )
1138 {
1139 CPLError( CE_Failure, CPLE_AppDefined,
1140 "Cannot use geometry field in this operation." );
1141 return false;
1142 }
1143 }
1144 return true;
1145 }
1146
1147 /************************************************************************/
1148 /* SWQGeneralChecker() */
1149 /* */
1150 /* Check the general purpose functions have appropriate types, */
1151 /* and count and indicate the function return type under the */
1152 /* circumstances. */
1153 /************************************************************************/
1154
SWQGeneralChecker(swq_expr_node * poNode,int bAllowMismatchTypeOnFieldComparison)1155 swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
1156 int bAllowMismatchTypeOnFieldComparison )
1157
1158 {
1159 swq_field_type eRetType = SWQ_ERROR;
1160 swq_field_type eArgType = SWQ_OTHER;
1161 // int nArgCount = -1;
1162
1163 switch( poNode->nOperation )
1164 {
1165 case SWQ_AND:
1166 case SWQ_OR:
1167 case SWQ_NOT:
1168 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1169 return SWQ_ERROR;
1170 eRetType = SWQ_BOOLEAN;
1171 break;
1172
1173 case SWQ_EQ:
1174 case SWQ_NE:
1175 case SWQ_GT:
1176 case SWQ_LT:
1177 case SWQ_GE:
1178 case SWQ_LE:
1179 case SWQ_IN:
1180 case SWQ_BETWEEN:
1181 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1182 return SWQ_ERROR;
1183 eRetType = SWQ_BOOLEAN;
1184 SWQAutoConvertStringToNumeric( poNode );
1185 SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
1186 SWQAutoPromoteStringToDateTime( poNode );
1187 eArgType = poNode->papoSubExpr[0]->field_type;
1188 break;
1189
1190 case SWQ_ISNULL:
1191 eRetType = SWQ_BOOLEAN;
1192 break;
1193
1194 case SWQ_LIKE:
1195 case SWQ_ILIKE:
1196 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1197 return SWQ_ERROR;
1198 eRetType = SWQ_BOOLEAN;
1199 eArgType = SWQ_STRING;
1200 break;
1201
1202 case SWQ_ADD:
1203 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1204 return SWQ_ERROR;
1205 SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
1206 if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
1207 {
1208 eRetType = SWQ_STRING;
1209 eArgType = SWQ_STRING;
1210 }
1211 else if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT || poNode->papoSubExpr[1]->field_type == SWQ_FLOAT )
1212 {
1213 eRetType = SWQ_FLOAT;
1214 eArgType = SWQ_FLOAT;
1215 }
1216 else if( poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 || poNode->papoSubExpr[1]->field_type == SWQ_INTEGER64 )
1217 {
1218 eRetType = SWQ_INTEGER64;
1219 eArgType = SWQ_INTEGER64;
1220 }
1221 else
1222 {
1223 eRetType = SWQ_INTEGER;
1224 eArgType = SWQ_INTEGER;
1225 }
1226 break;
1227
1228 case SWQ_SUBTRACT:
1229 case SWQ_MULTIPLY:
1230 case SWQ_DIVIDE:
1231 case SWQ_MODULUS:
1232 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1233 return SWQ_ERROR;
1234 SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
1235 if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT || poNode->papoSubExpr[1]->field_type == SWQ_FLOAT )
1236 {
1237 eRetType = SWQ_FLOAT;
1238 eArgType = SWQ_FLOAT;
1239 }
1240 else if( poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 || poNode->papoSubExpr[1]->field_type == SWQ_INTEGER64 )
1241 {
1242 eRetType = SWQ_INTEGER64;
1243 eArgType = SWQ_INTEGER64;
1244 }
1245 else
1246 {
1247 eRetType = SWQ_INTEGER;
1248 eArgType = SWQ_INTEGER;
1249 }
1250 break;
1251
1252 case SWQ_CONCAT:
1253 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1254 return SWQ_ERROR;
1255 eRetType = SWQ_STRING;
1256 eArgType = SWQ_STRING;
1257 break;
1258
1259 case SWQ_SUBSTR:
1260 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1261 return SWQ_ERROR;
1262 eRetType = SWQ_STRING;
1263 if( poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2 )
1264 {
1265 CPLError( CE_Failure, CPLE_AppDefined,
1266 "Expected 2 or 3 arguments to SUBSTR(), but got %d.",
1267 poNode->nSubExprCount );
1268 return SWQ_ERROR;
1269 }
1270 if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
1271 || poNode->papoSubExpr[1]->field_type != SWQ_INTEGER
1272 || (poNode->nSubExprCount > 2
1273 && poNode->papoSubExpr[2]->field_type != SWQ_INTEGER) )
1274 {
1275 CPLError(CE_Failure, CPLE_AppDefined,
1276 "Wrong argument type for SUBSTR(), "
1277 "expected SUBSTR(string,int,int) or SUBSTR(string,int).");
1278 return SWQ_ERROR;
1279 }
1280 break;
1281
1282 case SWQ_HSTORE_GET_VALUE:
1283 if( !SWQCheckSubExprAreNotGeometries(poNode) )
1284 return SWQ_ERROR;
1285 eRetType = SWQ_STRING;
1286 if( poNode->nSubExprCount != 2 )
1287 {
1288 CPLError( CE_Failure, CPLE_AppDefined,
1289 "Expected 2 arguments to hstore_get_value(), but got %d.",
1290 poNode->nSubExprCount );
1291 return SWQ_ERROR;
1292 }
1293 if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
1294 || poNode->papoSubExpr[1]->field_type != SWQ_STRING )
1295 {
1296 CPLError( CE_Failure, CPLE_AppDefined,
1297 "Wrong argument type for hstore_get_value(), "
1298 "expected hstore_get_value(string,string)." );
1299 return SWQ_ERROR;
1300 }
1301 break;
1302
1303 default:
1304 {
1305 const swq_operation *poOp =
1306 swq_op_registrar::GetOperator(poNode->nOperation);
1307
1308 CPLError( CE_Failure, CPLE_AppDefined,
1309 "SWQGeneralChecker() called on unsupported operation %s.",
1310 poOp->pszName);
1311 return SWQ_ERROR;
1312 }
1313 }
1314 /* -------------------------------------------------------------------- */
1315 /* Check argument types. */
1316 /* -------------------------------------------------------------------- */
1317 if( eArgType != SWQ_OTHER )
1318 {
1319 if( SWQ_IS_INTEGER(eArgType) || eArgType == SWQ_BOOLEAN )
1320 eArgType = SWQ_FLOAT;
1321
1322 for( int i = 0; i < poNode->nSubExprCount; i++ )
1323 {
1324 swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
1325 if( SWQ_IS_INTEGER(eThisArgType) || eThisArgType == SWQ_BOOLEAN )
1326 eThisArgType = SWQ_FLOAT;
1327
1328 if( eArgType != eThisArgType )
1329 {
1330 // Convenience for join. We allow comparing numeric columns
1331 // and string columns, by casting string columns to numeric.
1332 if( bAllowMismatchTypeOnFieldComparison &&
1333 poNode->nSubExprCount == 2 &&
1334 poNode->nOperation == SWQ_EQ &&
1335 poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
1336 poNode->papoSubExpr[i]->eNodeType == SNT_COLUMN &&
1337 eArgType == SWQ_FLOAT && eThisArgType == SWQ_STRING )
1338 {
1339 swq_expr_node* poNewNode = new swq_expr_node(SWQ_CAST);
1340 poNewNode->PushSubExpression(poNode->papoSubExpr[i]);
1341 poNewNode->PushSubExpression(new swq_expr_node("FLOAT"));
1342 SWQCastChecker(poNewNode, FALSE);
1343 poNode->papoSubExpr[i] = poNewNode;
1344 break;
1345 }
1346 if( bAllowMismatchTypeOnFieldComparison &&
1347 poNode->nSubExprCount == 2 &&
1348 poNode->nOperation == SWQ_EQ &&
1349 poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
1350 poNode->papoSubExpr[i]->eNodeType == SNT_COLUMN &&
1351 eThisArgType == SWQ_FLOAT && eArgType == SWQ_STRING )
1352 {
1353 swq_expr_node* poNewNode = new swq_expr_node(SWQ_CAST);
1354 poNewNode->PushSubExpression(poNode->papoSubExpr[0]);
1355 poNewNode->PushSubExpression(new swq_expr_node("FLOAT"));
1356 SWQCastChecker(poNewNode, FALSE);
1357 poNode->papoSubExpr[0] = poNewNode;
1358 break;
1359 }
1360
1361 const swq_operation *poOp =
1362 swq_op_registrar::GetOperator(poNode->nOperation);
1363
1364 CPLError( CE_Failure, CPLE_AppDefined,
1365 "Type mismatch or improper type of arguments "
1366 "to %s operator.",
1367 poOp->pszName );
1368 return SWQ_ERROR;
1369 }
1370 }
1371 }
1372
1373 /* -------------------------------------------------------------------- */
1374 /* Validate the arg count if requested. */
1375 /* -------------------------------------------------------------------- */
1376 #if 0
1377 // nArgCount was always -1, so this block was never executed.
1378 if( nArgCount != -1
1379 && nArgCount != poNode->nSubExprCount )
1380 {
1381 const swq_operation *poOp =
1382 swq_op_registrar::GetOperator(poNode->nOperation);
1383
1384 CPLError( CE_Failure, CPLE_AppDefined,
1385 "Expected %d arguments to %s, but got %d arguments.",
1386 nArgCount,
1387 poOp->pszName,
1388 poNode->nSubExprCount );
1389 return SWQ_ERROR;
1390 }
1391 #endif
1392
1393 return eRetType;
1394 }
1395
1396 /************************************************************************/
1397 /* SWQCastEvaluator() */
1398 /************************************************************************/
1399
SWQCastEvaluator(swq_expr_node * node,swq_expr_node ** sub_node_values)1400 swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
1401 swq_expr_node **sub_node_values )
1402
1403 {
1404 swq_expr_node *poRetNode = nullptr;
1405 swq_expr_node *poSrcNode = sub_node_values[0];
1406
1407 switch( node->field_type )
1408 {
1409 case SWQ_INTEGER:
1410 {
1411 poRetNode = new swq_expr_node( 0 );
1412 poRetNode->is_null = poSrcNode->is_null;
1413
1414 switch( poSrcNode->field_type )
1415 {
1416 case SWQ_INTEGER:
1417 case SWQ_BOOLEAN:
1418 poRetNode->int_value = poSrcNode->int_value;
1419 break;
1420
1421 case SWQ_INTEGER64:
1422 // TODO: Warn in case of overflow?
1423 poRetNode->int_value =
1424 static_cast<int>(poSrcNode->int_value);
1425 break;
1426
1427 case SWQ_FLOAT:
1428 // TODO: Warn in case of overflow?
1429 poRetNode->int_value =
1430 static_cast<int>(poSrcNode->float_value);
1431 break;
1432
1433 default:
1434 poRetNode->int_value = atoi(poSrcNode->string_value);
1435 break;
1436 }
1437 }
1438 break;
1439
1440 case SWQ_INTEGER64:
1441 {
1442 poRetNode = new swq_expr_node( 0 );
1443 poRetNode->is_null = poSrcNode->is_null;
1444 poRetNode->field_type = SWQ_INTEGER64;
1445
1446 switch( poSrcNode->field_type )
1447 {
1448 case SWQ_INTEGER:
1449 case SWQ_INTEGER64:
1450 case SWQ_BOOLEAN:
1451 poRetNode->int_value = poSrcNode->int_value;
1452 break;
1453
1454 case SWQ_FLOAT:
1455 poRetNode->int_value =
1456 static_cast<GIntBig>(poSrcNode->float_value);
1457 break;
1458
1459 default:
1460 poRetNode->int_value =
1461 CPLAtoGIntBig(poSrcNode->string_value);
1462 break;
1463 }
1464 }
1465 break;
1466
1467 case SWQ_FLOAT:
1468 {
1469 poRetNode = new swq_expr_node( 0.0 );
1470 poRetNode->is_null = poSrcNode->is_null;
1471
1472 switch( poSrcNode->field_type )
1473 {
1474 case SWQ_INTEGER:
1475 case SWQ_INTEGER64:
1476 case SWQ_BOOLEAN:
1477 poRetNode->float_value =
1478 static_cast<double>(poSrcNode->int_value);
1479 break;
1480
1481 case SWQ_FLOAT:
1482 poRetNode->float_value = poSrcNode->float_value;
1483 break;
1484
1485 default:
1486 poRetNode->float_value = CPLAtof(poSrcNode->string_value);
1487 break;
1488 }
1489 }
1490 break;
1491
1492 case SWQ_GEOMETRY:
1493 {
1494 poRetNode = new swq_expr_node( static_cast<OGRGeometry*>(nullptr) );
1495 if( !poSrcNode->is_null )
1496 {
1497 switch( poSrcNode->field_type )
1498 {
1499 case SWQ_GEOMETRY:
1500 {
1501 poRetNode->geometry_value =
1502 poSrcNode->geometry_value->clone();
1503 poRetNode->is_null = FALSE;
1504 break;
1505 }
1506
1507 case SWQ_STRING:
1508 {
1509 OGRGeometryFactory::createFromWkt(
1510 poSrcNode->string_value, nullptr,
1511 &(poRetNode->geometry_value));
1512 if( poRetNode->geometry_value != nullptr )
1513 poRetNode->is_null = FALSE;
1514 break;
1515 }
1516
1517 default:
1518 break;
1519 }
1520 }
1521 break;
1522 }
1523
1524 // Everything else is a string.
1525 default:
1526 {
1527 CPLString osRet;
1528
1529 switch( poSrcNode->field_type )
1530 {
1531 case SWQ_INTEGER:
1532 case SWQ_BOOLEAN:
1533 case SWQ_INTEGER64:
1534 osRet.Printf( CPL_FRMT_GIB, poSrcNode->int_value );
1535 break;
1536
1537 case SWQ_FLOAT:
1538 osRet.Printf( "%.15g", poSrcNode->float_value );
1539 break;
1540
1541 case SWQ_GEOMETRY:
1542 {
1543 if( poSrcNode->geometry_value != nullptr )
1544 {
1545 char* pszWKT = nullptr;
1546 poSrcNode->geometry_value->exportToWkt(&pszWKT);
1547 osRet = pszWKT;
1548 CPLFree(pszWKT);
1549 }
1550 else
1551 osRet = "";
1552 break;
1553 }
1554
1555 default:
1556 osRet = poSrcNode->string_value;
1557 break;
1558 }
1559
1560 if( node->nSubExprCount > 2 )
1561 {
1562 int nWidth = static_cast<int>(sub_node_values[2]->int_value);
1563 if( nWidth > 0 && static_cast<int>(osRet.size()) > nWidth )
1564 osRet.resize(nWidth);
1565 }
1566
1567 poRetNode = new swq_expr_node( osRet.c_str() );
1568 poRetNode->is_null = poSrcNode->is_null;
1569 }
1570 }
1571
1572 return poRetNode;
1573 }
1574
1575 /************************************************************************/
1576 /* SWQCastChecker() */
1577 /************************************************************************/
1578
SWQCastChecker(swq_expr_node * poNode,int)1579 swq_field_type SWQCastChecker( swq_expr_node *poNode,
1580 int /* bAllowMismatchTypeOnFieldComparison */ )
1581
1582 {
1583 swq_field_type eType = SWQ_ERROR;
1584 const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
1585
1586 if( poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY &&
1587 !(EQUAL(pszTypeName, "character") ||
1588 EQUAL(pszTypeName, "geometry")) )
1589 {
1590 CPLError( CE_Failure, CPLE_AppDefined, "Cannot cast geometry to %s",
1591 pszTypeName );
1592 }
1593 else if( EQUAL(pszTypeName, "boolean") )
1594 {
1595 eType = SWQ_BOOLEAN;
1596 }
1597 else if( EQUAL(pszTypeName, "character") )
1598 {
1599 eType = SWQ_STRING;
1600 }
1601 else if( EQUAL(pszTypeName, "integer") )
1602 {
1603 eType = SWQ_INTEGER;
1604 }
1605 else if( EQUAL(pszTypeName, "bigint") )
1606 {
1607 // Handle CAST(fid AS bigint) by changing the field_type of fid to
1608 // Integer64. A bit of a hack.
1609 if( poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
1610 poNode->papoSubExpr[0]->field_type == SWQ_INTEGER &&
1611 strcmp(poNode->papoSubExpr[0]->string_value, "fid") == 0 )
1612 {
1613 poNode->papoSubExpr[0]->field_type = SWQ_INTEGER64;
1614 }
1615 eType = SWQ_INTEGER64;
1616 }
1617 else if( EQUAL(pszTypeName, "smallint") )
1618 {
1619 eType = SWQ_INTEGER;
1620 }
1621 else if( EQUAL(pszTypeName, "float") )
1622 {
1623 eType = SWQ_FLOAT;
1624 }
1625 else if( EQUAL(pszTypeName, "numeric") )
1626 {
1627 eType = SWQ_FLOAT;
1628 }
1629 else if( EQUAL(pszTypeName, "timestamp") )
1630 {
1631 eType = SWQ_TIMESTAMP;
1632 }
1633 else if( EQUAL(pszTypeName, "date") )
1634 {
1635 eType = SWQ_DATE;
1636 }
1637 else if( EQUAL(pszTypeName, "time") )
1638 {
1639 eType = SWQ_TIME;
1640 }
1641 else if( EQUAL(pszTypeName, "geometry") )
1642 {
1643 if( !(poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY ||
1644 poNode->papoSubExpr[0]->field_type == SWQ_STRING) )
1645 {
1646 CPLError(CE_Failure, CPLE_AppDefined, "Cannot cast %s to geometry",
1647 SWQFieldTypeToString(poNode->papoSubExpr[0]->field_type));
1648 }
1649 else
1650 eType = SWQ_GEOMETRY;
1651 }
1652 else
1653 {
1654 CPLError( CE_Failure, CPLE_AppDefined,
1655 "Unrecognized typename %s in CAST operator.",
1656 pszTypeName );
1657 }
1658
1659 poNode->field_type = eType;
1660
1661 return eType;
1662 }
1663