Line data Source code
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 : * SPDX-License-Identifier: MIT
14 : ****************************************************************************/
15 :
16 : #include "cpl_port.h"
17 : #include "ogr_swq.h"
18 :
19 : #include <cctype>
20 : #include <climits>
21 : #include <cstdlib>
22 : #include <cstring>
23 : #include <string>
24 :
25 : #include "cpl_conv.h"
26 : #include "cpl_error.h"
27 : #include "cpl_safemaths.hpp"
28 : #include "cpl_string.h"
29 : #include "ogr_api.h"
30 : #include "ogr_geometry.h"
31 : #include "ogr_p.h"
32 : #include "utf8.h"
33 :
34 : /************************************************************************/
35 : /* swq_test_like() */
36 : /* */
37 : /* Does input match pattern? */
38 : /************************************************************************/
39 :
40 68401800 : int swq_test_like(const char *input, const char *pattern, char chEscape,
41 : bool insensitive, bool bUTF8Strings)
42 :
43 : {
44 68401800 : if (input == nullptr || pattern == nullptr)
45 0 : return 0;
46 :
47 73462900 : while (*input != '\0')
48 : {
49 73461800 : if (*pattern == '\0')
50 4 : return 0;
51 :
52 73461800 : else if (*pattern == chEscape)
53 : {
54 17 : pattern++;
55 17 : if (*pattern == '\0')
56 0 : return 0;
57 17 : if (*pattern != *input)
58 : {
59 0 : return 0;
60 : }
61 : else
62 : {
63 17 : input++;
64 17 : pattern++;
65 : }
66 : }
67 :
68 73461700 : else if (*pattern == '_')
69 : {
70 45324 : pattern++;
71 45324 : if (bUTF8Strings && static_cast<unsigned int>(*input) > 127)
72 : {
73 : // Continuation bytes of such characters are of the form
74 : // 10xxxxxx (0x80), whereas single-byte are 0xxxxxxx
75 : // and the start of a multi-byte is 11xxxxxx
76 8 : do
77 : {
78 16 : input++;
79 16 : } while (static_cast<unsigned int>(*input) > 127);
80 : }
81 : else
82 : {
83 45316 : input++;
84 : }
85 : }
86 73416400 : else if (*pattern == '%')
87 : {
88 143862 : if (pattern[1] == '\0')
89 14461 : return 1;
90 :
91 : // Try eating varying amounts of the input till we get a positive.
92 68259000 : for (int eat = 0; input[eat] != '\0'; eat++)
93 : {
94 68131300 : if (swq_test_like(input + eat, pattern + 1, chEscape,
95 68131300 : insensitive, bUTF8Strings))
96 1661 : return 1;
97 : }
98 :
99 127740 : return 0;
100 : }
101 : else
102 : {
103 73272600 : if (bUTF8Strings && insensitive)
104 : {
105 : const auto IsStringLongEnough =
106 146544000 : [](const char *str, size_t nReqSize)
107 : {
108 146544000 : while (nReqSize >= 2)
109 : {
110 41 : if (str[1] == 0)
111 0 : return false;
112 41 : str++;
113 41 : nReqSize--;
114 : }
115 146544000 : return true;
116 : };
117 :
118 73272200 : const auto pattern_codepoint_size = utf8codepointcalcsize(
119 : reinterpret_cast<const utf8_int8_t *>(pattern));
120 73272200 : if (!IsStringLongEnough(pattern, pattern_codepoint_size))
121 68256700 : return 0;
122 73272200 : utf8_int32_t pattern_codepoint = 0;
123 73272200 : utf8codepoint(reinterpret_cast<const utf8_int8_t *>(pattern),
124 : &pattern_codepoint);
125 :
126 73272200 : const auto input_codepoint_size = utf8codepointcalcsize(
127 : reinterpret_cast<const utf8_int8_t *>(input));
128 73272200 : if (!IsStringLongEnough(input, input_codepoint_size))
129 0 : return 0;
130 73272200 : utf8_int32_t input_codepoint = 0;
131 73272200 : utf8codepoint(reinterpret_cast<const utf8_int8_t *>(input),
132 : &input_codepoint);
133 :
134 212432000 : if (!(input_codepoint == pattern_codepoint ||
135 70903300 : utf8uprcodepoint(input_codepoint) ==
136 70903300 : utf8uprcodepoint(pattern_codepoint) ||
137 68256700 : utf8lwrcodepoint(input_codepoint) ==
138 68256700 : utf8lwrcodepoint(pattern_codepoint)))
139 : {
140 68256700 : return 0;
141 : }
142 :
143 5015450 : pattern += pattern_codepoint_size;
144 5015450 : input += input_codepoint_size;
145 : }
146 438 : else if ((!insensitive && *pattern != *input) ||
147 46 : (insensitive &&
148 46 : CPLTolower(static_cast<unsigned char>(*pattern)) !=
149 46 : CPLTolower(static_cast<unsigned char>(*input))))
150 : {
151 132 : return 0;
152 : }
153 : else
154 : {
155 260 : input++;
156 260 : pattern++;
157 : }
158 : }
159 : }
160 :
161 1118 : if (*pattern != '\0' && strcmp(pattern, "%") != 0)
162 819 : return 0;
163 : else
164 299 : return 1;
165 : }
166 :
167 : /************************************************************************/
168 : /* OGRHStoreGetValue() */
169 : /************************************************************************/
170 :
171 20 : static char *OGRHStoreCheckEnd(char *pszIter, int bIsKey)
172 : {
173 20 : pszIter++;
174 31 : for (; *pszIter != '\0'; pszIter++)
175 : {
176 24 : if (bIsKey)
177 : {
178 19 : if (*pszIter == ' ')
179 : {
180 : ;
181 : }
182 12 : else if (*pszIter == '=' && pszIter[1] == '>')
183 : {
184 11 : return pszIter + 2;
185 : }
186 : else
187 : {
188 1 : return nullptr;
189 : }
190 : }
191 : else
192 : {
193 5 : if (*pszIter == ' ')
194 : {
195 : ;
196 : }
197 1 : else if (*pszIter == ',')
198 : {
199 0 : return pszIter + 1;
200 : }
201 : else
202 : {
203 1 : return nullptr;
204 : }
205 : }
206 : }
207 7 : return pszIter;
208 : }
209 :
210 46 : static char *OGRHStoreGetNextString(char *pszIter, char **ppszOut, int bIsKey)
211 : {
212 : char ch;
213 46 : bool bInString = false;
214 46 : char *pszOut = nullptr;
215 46 : *ppszOut = nullptr;
216 124 : for (; (ch = *pszIter) != '\0'; pszIter++)
217 : {
218 110 : if (bInString)
219 : {
220 36 : if (ch == '"')
221 : {
222 17 : *pszOut = '\0';
223 17 : return OGRHStoreCheckEnd(pszIter, bIsKey);
224 : }
225 19 : else if (ch == '\\')
226 : {
227 1 : pszIter++;
228 1 : if ((ch = *pszIter) == '\0')
229 0 : return nullptr;
230 : }
231 19 : *pszOut = ch;
232 19 : pszOut++;
233 : }
234 : else
235 : {
236 74 : if (ch == ' ')
237 : {
238 16 : if (pszOut != nullptr)
239 : {
240 3 : *pszIter = '\0';
241 3 : return OGRHStoreCheckEnd(pszIter, bIsKey);
242 : }
243 : }
244 58 : else if (bIsKey && ch == '=' && pszIter[1] == '>')
245 : {
246 11 : if (pszOut != nullptr)
247 : {
248 11 : *pszIter = '\0';
249 11 : return pszIter + 2;
250 : }
251 : }
252 47 : else if (!bIsKey && ch == ',')
253 : {
254 1 : if (pszOut != nullptr)
255 : {
256 1 : *pszIter = '\0';
257 1 : return pszIter + 1;
258 : }
259 : }
260 46 : else if (ch == '"')
261 : {
262 19 : pszOut = pszIter + 1;
263 19 : *ppszOut = pszOut;
264 19 : bInString = true;
265 : }
266 27 : else if (pszOut == nullptr)
267 : {
268 25 : pszOut = pszIter;
269 25 : *ppszOut = pszIter;
270 : }
271 : }
272 : }
273 :
274 14 : if (!bInString && pszOut != nullptr)
275 : {
276 10 : return pszIter;
277 : }
278 4 : return nullptr;
279 : }
280 :
281 26 : static char *OGRHStoreGetNextKeyValue(char *pszHStore, char **ppszKey,
282 : char **ppszValue)
283 : {
284 26 : char *pszNext = OGRHStoreGetNextString(pszHStore, ppszKey, TRUE);
285 26 : if (pszNext == nullptr || *pszNext == '\0')
286 6 : return nullptr;
287 20 : return OGRHStoreGetNextString(pszNext, ppszValue, FALSE);
288 : }
289 :
290 25 : char *OGRHStoreGetValue(const char *pszHStore, const char *pszSearchedKey)
291 : {
292 25 : char *pszHStoreDup = CPLStrdup(pszHStore);
293 25 : char *pszHStoreIter = pszHStoreDup;
294 25 : char *pszRet = nullptr;
295 :
296 : while (true)
297 : {
298 : char *pszKey, *pszValue;
299 : pszHStoreIter =
300 26 : OGRHStoreGetNextKeyValue(pszHStoreIter, &pszKey, &pszValue);
301 26 : if (pszHStoreIter == nullptr)
302 : {
303 10 : break;
304 : }
305 16 : if (strcmp(pszKey, pszSearchedKey) == 0)
306 : {
307 11 : pszRet = CPLStrdup(pszValue);
308 11 : break;
309 : }
310 5 : if (*pszHStoreIter == '\0')
311 : {
312 4 : break;
313 : }
314 1 : }
315 25 : CPLFree(pszHStoreDup);
316 25 : return pszRet;
317 : }
318 :
319 : #ifdef DEBUG_VERBOSE
320 : /************************************************************************/
321 : /* OGRFormatDate() */
322 : /************************************************************************/
323 :
324 : #ifdef __GNUC__
325 : #pragma GCC diagnostic push
326 : #pragma GCC diagnostic ignored "-Wunused-function"
327 : #endif
328 : static const char *OGRFormatDate(const OGRField *psField)
329 : {
330 : return CPLSPrintf("%04d/%02d/%02d %02d:%02d:%06.3f", psField->Date.Year,
331 : psField->Date.Month, psField->Date.Day,
332 : psField->Date.Hour, psField->Date.Minute,
333 : psField->Date.Second);
334 : }
335 :
336 : #ifdef __GNUC__
337 : #pragma GCC diagnostic pop
338 : #endif
339 :
340 : #endif
341 :
342 : /************************************************************************/
343 : /* SWQGeneralEvaluator() */
344 : /************************************************************************/
345 :
346 80963 : swq_expr_node *SWQGeneralEvaluator(swq_expr_node *node,
347 : swq_expr_node **sub_node_values,
348 : const swq_evaluation_context &sContext)
349 :
350 : {
351 80963 : swq_expr_node *poRet = nullptr;
352 :
353 : /* -------------------------------------------------------------------- */
354 : /* Floating point operations. */
355 : /* -------------------------------------------------------------------- */
356 80963 : if (sub_node_values[0]->field_type == SWQ_FLOAT ||
357 74670 : (node->nSubExprCount > 1 &&
358 73682 : sub_node_values[1]->field_type == SWQ_FLOAT))
359 : {
360 6374 : poRet = new swq_expr_node(0);
361 6374 : poRet->field_type = node->field_type;
362 :
363 6374 : if (SWQ_IS_INTEGER(sub_node_values[0]->field_type))
364 81 : sub_node_values[0]->float_value =
365 81 : static_cast<double>(sub_node_values[0]->int_value);
366 6374 : if (node->nSubExprCount > 1 &&
367 6352 : SWQ_IS_INTEGER(sub_node_values[1]->field_type))
368 41 : sub_node_values[1]->float_value =
369 41 : static_cast<double>(sub_node_values[1]->int_value);
370 :
371 6374 : if (node->nOperation != SWQ_ISNULL && node->nOperation != SWQ_IN)
372 : {
373 18783 : for (int i = 0; i < node->nSubExprCount; i++)
374 : {
375 12552 : if (sub_node_values[i]->is_null)
376 : {
377 63 : if (poRet->field_type == SWQ_BOOLEAN)
378 : {
379 48 : poRet->int_value = FALSE;
380 48 : poRet->is_null = 1;
381 48 : return poRet;
382 : }
383 15 : else if (poRet->field_type == SWQ_FLOAT)
384 : {
385 15 : poRet->float_value = 0;
386 15 : poRet->is_null = 1;
387 15 : return poRet;
388 : }
389 0 : else if (SWQ_IS_INTEGER(poRet->field_type))
390 : {
391 0 : poRet->field_type = SWQ_INTEGER;
392 0 : poRet->int_value = 0;
393 0 : poRet->is_null = 1;
394 0 : return poRet;
395 : }
396 : }
397 : }
398 : }
399 :
400 6311 : switch (node->nOperation)
401 : {
402 2202 : case SWQ_EQ:
403 2202 : poRet->int_value = sub_node_values[0]->float_value ==
404 2202 : sub_node_values[1]->float_value;
405 2202 : break;
406 :
407 3664 : case SWQ_NE:
408 3664 : poRet->int_value = sub_node_values[0]->float_value !=
409 3664 : sub_node_values[1]->float_value;
410 3664 : break;
411 :
412 129 : case SWQ_GT:
413 129 : poRet->int_value = sub_node_values[0]->float_value >
414 129 : sub_node_values[1]->float_value;
415 129 : break;
416 :
417 118 : case SWQ_LT:
418 118 : poRet->int_value = sub_node_values[0]->float_value <
419 118 : sub_node_values[1]->float_value;
420 118 : break;
421 :
422 36 : case SWQ_GE:
423 36 : poRet->int_value = sub_node_values[0]->float_value >=
424 36 : sub_node_values[1]->float_value;
425 36 : break;
426 :
427 35 : case SWQ_LE:
428 35 : poRet->int_value = sub_node_values[0]->float_value <=
429 35 : sub_node_values[1]->float_value;
430 35 : break;
431 :
432 58 : case SWQ_IN:
433 : {
434 58 : poRet->int_value = 0;
435 58 : if (sub_node_values[0]->is_null)
436 : {
437 22 : poRet->is_null = 1;
438 : }
439 : else
440 : {
441 36 : bool bNullFound = false;
442 68 : for (int i = 1; i < node->nSubExprCount; i++)
443 : {
444 45 : if (sub_node_values[i]->is_null)
445 : {
446 14 : bNullFound = true;
447 : }
448 31 : else if (sub_node_values[0]->float_value ==
449 31 : sub_node_values[i]->float_value)
450 : {
451 13 : poRet->int_value = 1;
452 13 : break;
453 : }
454 : }
455 36 : if (bNullFound && !poRet->int_value)
456 : {
457 12 : poRet->is_null = 1;
458 : }
459 : }
460 : }
461 58 : break;
462 :
463 5 : case SWQ_BETWEEN:
464 10 : poRet->int_value = sub_node_values[0]->float_value >=
465 9 : sub_node_values[1]->float_value &&
466 4 : sub_node_values[0]->float_value <=
467 4 : sub_node_values[2]->float_value;
468 5 : break;
469 :
470 22 : case SWQ_ISNULL:
471 22 : poRet->int_value = sub_node_values[0]->is_null;
472 22 : break;
473 :
474 8 : case SWQ_ADD:
475 8 : poRet->float_value = sub_node_values[0]->float_value +
476 8 : sub_node_values[1]->float_value;
477 8 : break;
478 :
479 5 : case SWQ_SUBTRACT:
480 5 : poRet->float_value = sub_node_values[0]->float_value -
481 5 : sub_node_values[1]->float_value;
482 5 : break;
483 :
484 5 : case SWQ_MULTIPLY:
485 5 : poRet->float_value = sub_node_values[0]->float_value *
486 5 : sub_node_values[1]->float_value;
487 5 : break;
488 :
489 19 : case SWQ_DIVIDE:
490 19 : if (sub_node_values[1]->float_value == 0)
491 0 : poRet->float_value = INT_MAX;
492 : else
493 19 : poRet->float_value = sub_node_values[0]->float_value /
494 19 : sub_node_values[1]->float_value;
495 19 : break;
496 :
497 5 : case SWQ_MODULUS:
498 : {
499 5 : if (sub_node_values[1]->float_value == 0)
500 0 : poRet->float_value = INT_MAX;
501 : else
502 5 : poRet->float_value = fmod(sub_node_values[0]->float_value,
503 5 : sub_node_values[1]->float_value);
504 5 : break;
505 : }
506 :
507 0 : default:
508 0 : CPLAssert(false);
509 : delete poRet;
510 : poRet = nullptr;
511 : break;
512 6311 : }
513 : }
514 : /* -------------------------------------------------------------------- */
515 : /* integer/boolean operations. */
516 : /* -------------------------------------------------------------------- */
517 74589 : else if (SWQ_IS_INTEGER(sub_node_values[0]->field_type) ||
518 21596 : sub_node_values[0]->field_type == SWQ_BOOLEAN)
519 : {
520 60651 : poRet = new swq_expr_node(0);
521 60651 : poRet->field_type = node->field_type;
522 :
523 60651 : if (node->nOperation != SWQ_ISNULL && node->nOperation != SWQ_OR &&
524 58035 : node->nOperation != SWQ_AND && node->nOperation != SWQ_NOT &&
525 52765 : node->nOperation != SWQ_IN)
526 : {
527 156815 : for (int i = 0; i < node->nSubExprCount; i++)
528 : {
529 104753 : if (sub_node_values[i]->is_null)
530 : {
531 568 : if (poRet->field_type == SWQ_BOOLEAN ||
532 17 : SWQ_IS_INTEGER(poRet->field_type))
533 : {
534 568 : poRet->int_value = 0;
535 568 : poRet->is_null = 1;
536 568 : return poRet;
537 : }
538 : }
539 : }
540 : }
541 :
542 60083 : switch (node->nOperation)
543 : {
544 4777 : case SWQ_AND:
545 6144 : poRet->int_value = sub_node_values[0]->int_value &&
546 1367 : sub_node_values[1]->int_value;
547 4777 : poRet->is_null =
548 4777 : sub_node_values[0]->is_null && sub_node_values[1]->is_null;
549 4777 : break;
550 :
551 2402 : case SWQ_OR:
552 4699 : poRet->int_value = sub_node_values[0]->int_value ||
553 2297 : sub_node_values[1]->int_value;
554 2402 : poRet->is_null =
555 2402 : sub_node_values[0]->is_null || sub_node_values[1]->is_null;
556 2402 : break;
557 :
558 493 : case SWQ_NOT:
559 872 : poRet->int_value = !sub_node_values[0]->int_value &&
560 379 : !sub_node_values[0]->is_null;
561 493 : poRet->is_null = sub_node_values[0]->is_null;
562 493 : break;
563 :
564 45348 : case SWQ_EQ:
565 45348 : poRet->int_value = sub_node_values[0]->int_value ==
566 45348 : sub_node_values[1]->int_value;
567 45348 : break;
568 :
569 6040 : case SWQ_NE:
570 6040 : poRet->int_value = sub_node_values[0]->int_value !=
571 6040 : sub_node_values[1]->int_value;
572 6040 : break;
573 :
574 139 : case SWQ_GT:
575 139 : poRet->int_value = sub_node_values[0]->int_value >
576 139 : sub_node_values[1]->int_value;
577 139 : break;
578 :
579 213 : case SWQ_LT:
580 213 : poRet->int_value = sub_node_values[0]->int_value <
581 213 : sub_node_values[1]->int_value;
582 213 : break;
583 :
584 101 : case SWQ_GE:
585 101 : poRet->int_value = sub_node_values[0]->int_value >=
586 101 : sub_node_values[1]->int_value;
587 101 : break;
588 :
589 83 : case SWQ_LE:
590 83 : poRet->int_value = sub_node_values[0]->int_value <=
591 83 : sub_node_values[1]->int_value;
592 83 : break;
593 :
594 135 : case SWQ_IN:
595 : {
596 135 : poRet->int_value = 0;
597 135 : if (sub_node_values[0]->is_null)
598 : {
599 5 : poRet->is_null = 1;
600 : }
601 : else
602 : {
603 130 : bool bNullFound = false;
604 318 : for (int i = 1; i < node->nSubExprCount; i++)
605 : {
606 228 : if (sub_node_values[i]->is_null)
607 : {
608 0 : bNullFound = true;
609 : }
610 228 : else if (sub_node_values[0]->int_value ==
611 228 : sub_node_values[i]->int_value)
612 : {
613 40 : poRet->int_value = 1;
614 40 : break;
615 : }
616 : }
617 130 : if (bNullFound && !poRet->int_value)
618 : {
619 0 : poRet->is_null = 1;
620 : }
621 : }
622 : }
623 135 : break;
624 :
625 25 : case SWQ_BETWEEN:
626 50 : poRet->int_value = sub_node_values[0]->int_value >=
627 47 : sub_node_values[1]->int_value &&
628 22 : sub_node_values[0]->int_value <=
629 22 : sub_node_values[2]->int_value;
630 25 : break;
631 :
632 214 : case SWQ_ISNULL:
633 214 : poRet->int_value = sub_node_values[0]->is_null;
634 214 : break;
635 :
636 36 : case SWQ_ADD:
637 : try
638 : {
639 38 : poRet->int_value = (CPLSM(sub_node_values[0]->int_value) +
640 108 : CPLSM(sub_node_values[1]->int_value))
641 34 : .v();
642 : }
643 2 : catch (const std::exception &)
644 : {
645 2 : CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
646 2 : poRet->is_null = true;
647 : }
648 36 : break;
649 :
650 17 : case SWQ_SUBTRACT:
651 : try
652 : {
653 19 : poRet->int_value = (CPLSM(sub_node_values[0]->int_value) -
654 51 : CPLSM(sub_node_values[1]->int_value))
655 15 : .v();
656 : }
657 2 : catch (const std::exception &)
658 : {
659 2 : CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
660 2 : poRet->is_null = true;
661 : }
662 17 : break;
663 :
664 25 : case SWQ_MULTIPLY:
665 : try
666 : {
667 32 : poRet->int_value = (CPLSM(sub_node_values[0]->int_value) *
668 75 : CPLSM(sub_node_values[1]->int_value))
669 18 : .v();
670 : }
671 7 : catch (const std::exception &)
672 : {
673 7 : CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
674 7 : poRet->is_null = true;
675 : }
676 25 : break;
677 :
678 12 : case SWQ_DIVIDE:
679 12 : if (sub_node_values[1]->int_value == 0)
680 1 : poRet->int_value = INT_MAX;
681 : else
682 : {
683 : try
684 : {
685 10 : poRet->int_value =
686 12 : (CPLSM(sub_node_values[0]->int_value) /
687 33 : CPLSM(sub_node_values[1]->int_value))
688 10 : .v();
689 : }
690 1 : catch (const std::exception &)
691 : {
692 1 : CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
693 1 : poRet->is_null = true;
694 : }
695 : }
696 12 : break;
697 :
698 23 : case SWQ_MODULUS:
699 23 : if (sub_node_values[1]->int_value == 0)
700 0 : poRet->int_value = INT_MAX;
701 : else
702 23 : poRet->int_value = sub_node_values[0]->int_value %
703 23 : sub_node_values[1]->int_value;
704 23 : break;
705 :
706 0 : default:
707 0 : CPLAssert(false);
708 : delete poRet;
709 : poRet = nullptr;
710 : break;
711 60083 : }
712 : }
713 :
714 : /* -------------------------------------------------------------------- */
715 : /* datetime */
716 : /* -------------------------------------------------------------------- */
717 13938 : else if (sub_node_values[0]->field_type == SWQ_TIMESTAMP &&
718 307 : (node->nOperation == SWQ_EQ || node->nOperation == SWQ_GT ||
719 145 : node->nOperation == SWQ_GE || node->nOperation == SWQ_LT ||
720 101 : node->nOperation == SWQ_LE || node->nOperation == SWQ_IN ||
721 72 : node->nOperation == SWQ_BETWEEN))
722 : {
723 240 : if (node->field_type == SWQ_BOOLEAN && node->nOperation != SWQ_IN)
724 : {
725 621 : for (int i = 0; i < node->nSubExprCount; i++)
726 : {
727 420 : if (sub_node_values[i]->is_null)
728 : {
729 13 : poRet = new swq_expr_node(FALSE);
730 13 : poRet->field_type = node->field_type;
731 13 : poRet->is_null = 1;
732 18 : return poRet;
733 : }
734 : }
735 : }
736 :
737 : OGRField sField0, sField1;
738 227 : OGR_RawField_SetUnset(&sField0);
739 227 : OGR_RawField_SetUnset(&sField1);
740 227 : poRet = new swq_expr_node(0);
741 227 : poRet->field_type = node->field_type;
742 :
743 233 : if (!OGRParseDate(sub_node_values[0]->string_value, &sField0, 0) &&
744 6 : node->nOperation != SWQ_IN)
745 : {
746 1 : CPLError(
747 : CE_Failure, CPLE_AppDefined,
748 : "Failed to parse date '%s' evaluating OGR WHERE expression",
749 1 : sub_node_values[0]->string_value);
750 1 : delete poRet;
751 1 : return nullptr;
752 : }
753 426 : if (node->nOperation != SWQ_IN &&
754 200 : !OGRParseDate(sub_node_values[1]->string_value, &sField1, 0))
755 : {
756 2 : CPLError(
757 : CE_Failure, CPLE_AppDefined,
758 : "Failed to parse date '%s' evaluating OGR WHERE expression",
759 2 : sub_node_values[1]->string_value);
760 2 : delete poRet;
761 2 : return nullptr;
762 : }
763 :
764 224 : switch (node->nOperation)
765 : {
766 10 : case SWQ_GT:
767 10 : poRet->int_value = OGRCompareDate(&sField0, &sField1) > 0;
768 10 : break;
769 :
770 3 : case SWQ_GE:
771 3 : poRet->int_value = OGRCompareDate(&sField0, &sField1) >= 0;
772 3 : break;
773 :
774 40 : case SWQ_LT:
775 40 : poRet->int_value = OGRCompareDate(&sField0, &sField1) < 0;
776 40 : break;
777 :
778 2 : case SWQ_LE:
779 2 : poRet->int_value = OGRCompareDate(&sField0, &sField1) <= 0;
780 2 : break;
781 :
782 138 : case SWQ_EQ:
783 138 : poRet->int_value = OGRCompareDate(&sField0, &sField1) == 0;
784 138 : break;
785 :
786 5 : case SWQ_BETWEEN:
787 : {
788 : OGRField sField2;
789 5 : if (!OGRParseDate(sub_node_values[2]->string_value, &sField2,
790 : 0))
791 : {
792 1 : CPLError(CE_Failure, CPLE_AppDefined,
793 : "Failed to parse date '%s' evaluating OGR WHERE "
794 : "expression",
795 1 : sub_node_values[2]->string_value);
796 1 : delete poRet;
797 1 : return nullptr;
798 : }
799 :
800 7 : poRet->int_value = (OGRCompareDate(&sField0, &sField1) >= 0) &&
801 3 : (OGRCompareDate(&sField0, &sField2) <= 0);
802 : }
803 4 : break;
804 :
805 26 : case SWQ_IN:
806 : {
807 26 : poRet->int_value = 0;
808 26 : if (sub_node_values[0]->is_null)
809 : {
810 5 : poRet->is_null = 1;
811 : }
812 : else
813 : {
814 : OGRField sFieldIn;
815 21 : bool bNullFound = false;
816 33 : for (int i = 1; i < node->nSubExprCount; i++)
817 : {
818 27 : if (sub_node_values[i]->is_null)
819 : {
820 2 : bNullFound = true;
821 : }
822 : else
823 : {
824 25 : if (!OGRParseDate(sub_node_values[i]->string_value,
825 : &sFieldIn, 0))
826 : {
827 1 : CPLError(
828 : CE_Failure, CPLE_AppDefined,
829 : "Failed to parse date '%s' evaluating OGR "
830 : "WHERE expression",
831 1 : sub_node_values[i]->string_value);
832 1 : delete poRet;
833 1 : return nullptr;
834 : }
835 24 : if (OGRCompareDate(&sField0, &sFieldIn) == 0)
836 : {
837 14 : poRet->int_value = 1;
838 14 : break;
839 : }
840 : }
841 : }
842 20 : if (bNullFound && !poRet->int_value)
843 : {
844 2 : poRet->is_null = 1;
845 : }
846 : }
847 : }
848 25 : break;
849 :
850 0 : default:
851 0 : CPLAssert(false);
852 : delete poRet;
853 : poRet = nullptr;
854 : break;
855 222 : }
856 : }
857 :
858 : /* -------------------------------------------------------------------- */
859 : /* String operations. */
860 : /* -------------------------------------------------------------------- */
861 : else
862 : {
863 13698 : poRet = new swq_expr_node(0);
864 13698 : poRet->field_type = node->field_type;
865 :
866 13698 : if (node->nOperation != SWQ_ISNULL && node->nOperation != SWQ_IN)
867 : {
868 39655 : for (int i = 0; i < node->nSubExprCount; i++)
869 : {
870 26535 : if (sub_node_values[i]->is_null)
871 : {
872 262 : if (poRet->field_type == SWQ_BOOLEAN)
873 : {
874 253 : poRet->int_value = FALSE;
875 253 : poRet->is_null = 1;
876 253 : return poRet;
877 : }
878 9 : else if (poRet->field_type == SWQ_STRING)
879 : {
880 9 : poRet->string_value = CPLStrdup("");
881 9 : poRet->is_null = 1;
882 9 : return poRet;
883 : }
884 : }
885 : }
886 : }
887 :
888 13436 : switch (node->nOperation)
889 : {
890 5170 : case SWQ_EQ:
891 : {
892 : // When comparing timestamps, the +00 at the end might be
893 : // discarded if the other member has no explicit timezone.
894 5170 : if ((sub_node_values[0]->field_type == SWQ_TIMESTAMP ||
895 5170 : sub_node_values[0]->field_type == SWQ_STRING) &&
896 5170 : (sub_node_values[1]->field_type == SWQ_TIMESTAMP ||
897 5170 : sub_node_values[1]->field_type == SWQ_STRING) &&
898 5169 : strlen(sub_node_values[0]->string_value) > 3 &&
899 4686 : strlen(sub_node_values[1]->string_value) > 3 &&
900 4566 : (strcmp(sub_node_values[0]->string_value +
901 4566 : strlen(sub_node_values[0]->string_value) - 3,
902 0 : "+00") == 0 &&
903 0 : sub_node_values[1]->string_value
904 0 : [strlen(sub_node_values[1]->string_value) - 3] ==
905 : ':'))
906 : {
907 0 : if (!sub_node_values[1]->string_value)
908 : {
909 0 : poRet->int_value = false;
910 : }
911 : else
912 : {
913 0 : poRet->int_value =
914 0 : EQUALN(sub_node_values[0]->string_value,
915 : sub_node_values[1]->string_value,
916 : strlen(sub_node_values[1]->string_value));
917 : }
918 : }
919 5170 : else if ((sub_node_values[0]->field_type == SWQ_TIMESTAMP ||
920 5170 : sub_node_values[0]->field_type == SWQ_STRING) &&
921 5170 : (sub_node_values[1]->field_type == SWQ_TIMESTAMP ||
922 5170 : sub_node_values[1]->field_type == SWQ_STRING) &&
923 5169 : strlen(sub_node_values[0]->string_value) > 3 &&
924 4686 : strlen(sub_node_values[1]->string_value) > 3 &&
925 4566 : (sub_node_values[0]->string_value
926 4566 : [strlen(sub_node_values[0]->string_value) - 3] ==
927 0 : ':') &&
928 0 : strcmp(sub_node_values[1]->string_value +
929 0 : strlen(sub_node_values[1]->string_value) -
930 : 3,
931 : "+00") == 0)
932 : {
933 0 : if (!sub_node_values[1]->string_value)
934 : {
935 0 : poRet->int_value = false;
936 : }
937 : else
938 : {
939 0 : poRet->int_value =
940 0 : EQUALN(sub_node_values[0]->string_value,
941 : sub_node_values[1]->string_value,
942 : strlen(sub_node_values[0]->string_value));
943 : }
944 : }
945 : else
946 : {
947 5170 : if (!sub_node_values[1]->string_value)
948 : {
949 1 : poRet->int_value = false;
950 : }
951 : else
952 : {
953 5169 : poRet->int_value =
954 5169 : strcasecmp(sub_node_values[0]->string_value,
955 5169 : sub_node_values[1]->string_value) == 0;
956 : }
957 : }
958 5170 : break;
959 : }
960 :
961 7538 : case SWQ_NE:
962 : {
963 7538 : if (!sub_node_values[1]->string_value)
964 : {
965 1 : poRet->int_value = false;
966 : }
967 : else
968 : {
969 7537 : poRet->int_value =
970 7537 : strcasecmp(sub_node_values[0]->string_value,
971 7537 : sub_node_values[1]->string_value) != 0;
972 : }
973 7538 : break;
974 : }
975 :
976 50 : case SWQ_GT:
977 : {
978 50 : if (!sub_node_values[1]->string_value)
979 : {
980 1 : poRet->int_value = false;
981 : }
982 : else
983 : {
984 49 : poRet->int_value =
985 49 : strcasecmp(sub_node_values[0]->string_value,
986 49 : sub_node_values[1]->string_value) > 0;
987 : }
988 50 : break;
989 : }
990 :
991 46 : case SWQ_LT:
992 : {
993 46 : if (!sub_node_values[1]->string_value)
994 : {
995 1 : poRet->int_value = false;
996 : }
997 : else
998 : {
999 45 : poRet->int_value =
1000 45 : strcasecmp(sub_node_values[0]->string_value,
1001 45 : sub_node_values[1]->string_value) < 0;
1002 : }
1003 46 : break;
1004 : }
1005 :
1006 32 : case SWQ_GE:
1007 : {
1008 32 : if (!sub_node_values[1]->string_value)
1009 : {
1010 1 : poRet->int_value = false;
1011 : }
1012 : else
1013 : {
1014 31 : poRet->int_value =
1015 31 : strcasecmp(sub_node_values[0]->string_value,
1016 31 : sub_node_values[1]->string_value) >= 0;
1017 : }
1018 32 : break;
1019 : }
1020 :
1021 43 : case SWQ_LE:
1022 : {
1023 43 : if (!sub_node_values[1]->string_value)
1024 : {
1025 1 : poRet->int_value = false;
1026 : }
1027 : else
1028 : {
1029 42 : poRet->int_value =
1030 42 : strcasecmp(sub_node_values[0]->string_value,
1031 42 : sub_node_values[1]->string_value) <= 0;
1032 : }
1033 43 : break;
1034 : }
1035 :
1036 35 : case SWQ_IN:
1037 : {
1038 35 : poRet->int_value = 0;
1039 35 : if (sub_node_values[0]->is_null)
1040 : {
1041 8 : poRet->is_null = 1;
1042 : }
1043 : else
1044 : {
1045 27 : bool bNullFound = false;
1046 54 : for (int i = 1; i < node->nSubExprCount; i++)
1047 : {
1048 40 : if (sub_node_values[i]->is_null ||
1049 38 : !sub_node_values[i]->string_value)
1050 : {
1051 4 : bNullFound = true;
1052 : }
1053 : else
1054 : {
1055 36 : if (strcasecmp(sub_node_values[0]->string_value,
1056 36 : sub_node_values[i]->string_value) ==
1057 : 0)
1058 : {
1059 13 : poRet->int_value = 1;
1060 13 : break;
1061 : }
1062 : }
1063 : }
1064 27 : if (bNullFound && !poRet->int_value)
1065 : {
1066 3 : poRet->is_null = 1;
1067 : }
1068 : }
1069 : }
1070 35 : break;
1071 :
1072 7 : case SWQ_BETWEEN:
1073 : {
1074 7 : if (!sub_node_values[1]->string_value)
1075 : {
1076 1 : poRet->int_value = false;
1077 : }
1078 : else
1079 : {
1080 6 : poRet->int_value =
1081 6 : strcasecmp(sub_node_values[0]->string_value,
1082 11 : sub_node_values[1]->string_value) >= 0 &&
1083 5 : strcasecmp(sub_node_values[0]->string_value,
1084 5 : sub_node_values[2]->string_value) <= 0;
1085 : }
1086 7 : break;
1087 : }
1088 :
1089 109 : case SWQ_LIKE:
1090 : {
1091 109 : if (!sub_node_values[1]->string_value)
1092 : {
1093 0 : poRet->int_value = false;
1094 : }
1095 : else
1096 : {
1097 109 : char chEscape = '\0';
1098 109 : if (node->nSubExprCount == 3)
1099 11 : chEscape = sub_node_values[2]->string_value[0];
1100 109 : const bool bInsensitive = CPLTestBool(
1101 : CPLGetConfigOption("OGR_SQL_LIKE_AS_ILIKE", "FALSE"));
1102 109 : poRet->int_value = swq_test_like(
1103 109 : sub_node_values[0]->string_value,
1104 109 : sub_node_values[1]->string_value, chEscape,
1105 109 : bInsensitive, sContext.bUTF8Strings);
1106 : }
1107 109 : break;
1108 : }
1109 :
1110 67 : case SWQ_ILIKE:
1111 : {
1112 67 : if (!sub_node_values[1]->string_value)
1113 : {
1114 0 : poRet->int_value = false;
1115 : }
1116 : else
1117 : {
1118 67 : char chEscape = '\0';
1119 67 : if (node->nSubExprCount == 3)
1120 0 : chEscape = sub_node_values[2]->string_value[0];
1121 67 : poRet->int_value =
1122 67 : swq_test_like(sub_node_values[0]->string_value,
1123 67 : sub_node_values[1]->string_value,
1124 67 : chEscape, true, sContext.bUTF8Strings);
1125 : }
1126 67 : break;
1127 : }
1128 :
1129 281 : case SWQ_ISNULL:
1130 281 : poRet->int_value = sub_node_values[0]->is_null;
1131 281 : break;
1132 :
1133 23 : case SWQ_CONCAT:
1134 : case SWQ_ADD:
1135 : {
1136 46 : CPLString osResult = sub_node_values[0]->string_value;
1137 :
1138 48 : for (int i = 1; i < node->nSubExprCount; i++)
1139 25 : osResult += sub_node_values[i]->string_value;
1140 :
1141 23 : poRet->string_value = CPLStrdup(osResult);
1142 23 : poRet->is_null = sub_node_values[0]->is_null;
1143 23 : break;
1144 : }
1145 :
1146 14 : case SWQ_SUBSTR:
1147 : {
1148 14 : const char *pszSrcStr = sub_node_values[0]->string_value;
1149 :
1150 14 : int nOffset = 0;
1151 14 : if (SWQ_IS_INTEGER(sub_node_values[1]->field_type))
1152 14 : nOffset = static_cast<int>(sub_node_values[1]->int_value);
1153 0 : else if (sub_node_values[1]->field_type == SWQ_FLOAT)
1154 0 : nOffset = static_cast<int>(sub_node_values[1]->float_value);
1155 : // else
1156 : // nOffset = 0;
1157 :
1158 14 : int nSize = 0;
1159 14 : if (node->nSubExprCount < 3)
1160 2 : nSize = 100000;
1161 12 : else if (SWQ_IS_INTEGER(sub_node_values[2]->field_type))
1162 12 : nSize = static_cast<int>(sub_node_values[2]->int_value);
1163 0 : else if (sub_node_values[2]->field_type == SWQ_FLOAT)
1164 0 : nSize = static_cast<int>(sub_node_values[2]->float_value);
1165 : // else
1166 : // nSize = 0;
1167 :
1168 14 : const int nSrcStrLen = static_cast<int>(strlen(pszSrcStr));
1169 :
1170 : // In SQL, the first character is at offset 1.
1171 : // 0 is considered as 1.
1172 14 : if (nOffset > 0)
1173 12 : nOffset--;
1174 : // Some implementations allow negative offsets, to start
1175 : // from the end of the string.
1176 2 : else if (nOffset < 0)
1177 : {
1178 2 : if (nSrcStrLen + nOffset >= 0)
1179 2 : nOffset = nSrcStrLen + nOffset;
1180 : else
1181 0 : nOffset = 0;
1182 : }
1183 :
1184 14 : if (nSize < 0 || nOffset > nSrcStrLen)
1185 : {
1186 0 : nOffset = 0;
1187 0 : nSize = 0;
1188 : }
1189 14 : else if (nOffset + nSize > nSrcStrLen)
1190 2 : nSize = nSrcStrLen - nOffset;
1191 :
1192 28 : CPLString osResult = pszSrcStr + nOffset;
1193 14 : if (static_cast<int>(osResult.size()) > nSize)
1194 0 : osResult.resize(nSize);
1195 :
1196 14 : poRet->string_value = CPLStrdup(osResult);
1197 14 : poRet->is_null = sub_node_values[0]->is_null;
1198 14 : break;
1199 : }
1200 :
1201 21 : case SWQ_HSTORE_GET_VALUE:
1202 : {
1203 21 : if (!sub_node_values[1]->string_value)
1204 : {
1205 0 : poRet->int_value = false;
1206 : }
1207 : else
1208 : {
1209 21 : const char *pszHStore = sub_node_values[0]->string_value;
1210 21 : const char *pszSearchedKey =
1211 21 : sub_node_values[1]->string_value;
1212 21 : char *pszRet = OGRHStoreGetValue(pszHStore, pszSearchedKey);
1213 21 : poRet->string_value = pszRet ? pszRet : CPLStrdup("");
1214 21 : poRet->is_null = (pszRet == nullptr);
1215 : }
1216 21 : break;
1217 : }
1218 :
1219 0 : default:
1220 0 : CPLAssert(false);
1221 : delete poRet;
1222 : poRet = nullptr;
1223 : break;
1224 : }
1225 : }
1226 :
1227 80052 : return poRet;
1228 : }
1229 :
1230 : /************************************************************************/
1231 : /* SWQAutoPromoteIntegerToInteger64OrFloat() */
1232 : /************************************************************************/
1233 :
1234 10743 : static void SWQAutoPromoteIntegerToInteger64OrFloat(swq_expr_node *poNode)
1235 :
1236 : {
1237 10743 : if (poNode->nSubExprCount < 2)
1238 0 : return;
1239 :
1240 10743 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
1241 :
1242 : // We allow mixes of integer, integer64 and float, and string and dates.
1243 : // When encountered, we promote integers/integer64 to floats,
1244 : // integer to integer64 and strings to dates. We do that now.
1245 21615 : for (int i = 1; i < poNode->nSubExprCount; i++)
1246 : {
1247 10872 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1248 10872 : if (SWQ_IS_INTEGER(eArgType) && poSubNode->field_type == SWQ_FLOAT)
1249 84 : eArgType = SWQ_FLOAT;
1250 10788 : else if (eArgType == SWQ_INTEGER &&
1251 8011 : poSubNode->field_type == SWQ_INTEGER64)
1252 23 : eArgType = SWQ_INTEGER64;
1253 : }
1254 :
1255 32358 : for (int i = 0; i < poNode->nSubExprCount; i++)
1256 : {
1257 21615 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1258 :
1259 21615 : if (eArgType == SWQ_FLOAT && SWQ_IS_INTEGER(poSubNode->field_type))
1260 : {
1261 281 : if (poSubNode->eNodeType == SNT_CONSTANT)
1262 : {
1263 234 : poSubNode->float_value =
1264 234 : static_cast<double>(poSubNode->int_value);
1265 234 : poSubNode->field_type = SWQ_FLOAT;
1266 : }
1267 : }
1268 21334 : else if (eArgType == SWQ_INTEGER64 &&
1269 1319 : poSubNode->field_type == SWQ_INTEGER)
1270 : {
1271 636 : if (poSubNode->eNodeType == SNT_CONSTANT)
1272 : {
1273 617 : poSubNode->field_type = SWQ_INTEGER64;
1274 : }
1275 : }
1276 : }
1277 : }
1278 :
1279 : /************************************************************************/
1280 : /* SWQAutoPromoteStringToDateTime() */
1281 : /************************************************************************/
1282 :
1283 10638 : static void SWQAutoPromoteStringToDateTime(swq_expr_node *poNode)
1284 :
1285 : {
1286 10638 : if (poNode->nSubExprCount < 2)
1287 0 : return;
1288 :
1289 10638 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
1290 :
1291 : // We allow mixes of integer and float, and string and dates.
1292 : // When encountered, we promote integers to floats, and strings to
1293 : // dates. We do that now.
1294 21405 : for (int i = 1; i < poNode->nSubExprCount; i++)
1295 : {
1296 10767 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1297 :
1298 10767 : if (eArgType == SWQ_STRING && (poSubNode->field_type == SWQ_DATE ||
1299 1314 : poSubNode->field_type == SWQ_TIME ||
1300 1314 : poSubNode->field_type == SWQ_TIMESTAMP))
1301 1 : eArgType = SWQ_TIMESTAMP;
1302 : }
1303 :
1304 32043 : for (int i = 0; i < poNode->nSubExprCount; i++)
1305 : {
1306 21405 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1307 :
1308 21405 : if (eArgType == SWQ_TIMESTAMP && (poSubNode->field_type == SWQ_STRING ||
1309 136 : poSubNode->field_type == SWQ_DATE ||
1310 136 : poSubNode->field_type == SWQ_TIME))
1311 : {
1312 148 : if (poSubNode->eNodeType == SNT_CONSTANT)
1313 : {
1314 148 : poSubNode->field_type = SWQ_TIMESTAMP;
1315 : }
1316 : }
1317 : }
1318 : }
1319 :
1320 : /************************************************************************/
1321 : /* SWQAutoConvertStringToNumeric() */
1322 : /* */
1323 : /* Convert string constants to integer or float constants */
1324 : /* when there is a mix of arguments of type numeric and string */
1325 : /************************************************************************/
1326 :
1327 10638 : static void SWQAutoConvertStringToNumeric(swq_expr_node *poNode)
1328 :
1329 : {
1330 10638 : if (poNode->nSubExprCount < 2)
1331 0 : return;
1332 :
1333 10638 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
1334 :
1335 21365 : for (int i = 1; i < poNode->nSubExprCount; i++)
1336 : {
1337 10759 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1338 :
1339 : // Identify the mixture of the argument type.
1340 10759 : if ((eArgType == SWQ_STRING && (SWQ_IS_INTEGER(poSubNode->field_type) ||
1341 10756 : poSubNode->field_type == SWQ_FLOAT)) ||
1342 10754 : (SWQ_IS_INTEGER(eArgType) && poSubNode->field_type == SWQ_STRING))
1343 : {
1344 32 : eArgType = SWQ_FLOAT;
1345 32 : break;
1346 : }
1347 : }
1348 :
1349 32043 : for (int i = 0; i < poNode->nSubExprCount; i++)
1350 : {
1351 21405 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
1352 :
1353 21405 : if (eArgType == SWQ_FLOAT && poSubNode->field_type == SWQ_STRING)
1354 : {
1355 46 : if (poSubNode->eNodeType == SNT_CONSTANT)
1356 : {
1357 : // Apply the string to numeric conversion.
1358 43 : char *endPtr = nullptr;
1359 43 : poSubNode->float_value =
1360 43 : CPLStrtod(poSubNode->string_value, &endPtr);
1361 43 : if (!(endPtr == nullptr || *endPtr == '\0'))
1362 : {
1363 1 : CPLError(CE_Warning, CPLE_NotSupported,
1364 : "Conversion failed when converting the string "
1365 : "value '%s' to data type float.",
1366 : poSubNode->string_value);
1367 1 : continue;
1368 : }
1369 :
1370 : // Should also fill the integer value in this case.
1371 42 : poSubNode->int_value =
1372 42 : static_cast<GIntBig>(poSubNode->float_value);
1373 42 : poSubNode->field_type = SWQ_FLOAT;
1374 : }
1375 : }
1376 : }
1377 : }
1378 :
1379 : /************************************************************************/
1380 : /* SWQCheckSubExprAreNotGeometries() */
1381 : /************************************************************************/
1382 :
1383 15882 : static bool SWQCheckSubExprAreNotGeometries(swq_expr_node *poNode)
1384 : {
1385 47494 : for (int i = 0; i < poNode->nSubExprCount; i++)
1386 : {
1387 31622 : if (poNode->papoSubExpr[i]->field_type == SWQ_GEOMETRY)
1388 : {
1389 10 : CPLError(CE_Failure, CPLE_AppDefined,
1390 : "Cannot use geometry field in this operation.");
1391 10 : return false;
1392 : }
1393 : }
1394 15872 : return true;
1395 : }
1396 :
1397 : /************************************************************************/
1398 : /* SWQGeneralChecker() */
1399 : /* */
1400 : /* Check the general purpose functions have appropriate types, */
1401 : /* and count and indicate the function return type under the */
1402 : /* circumstances. */
1403 : /************************************************************************/
1404 :
1405 16101 : swq_field_type SWQGeneralChecker(swq_expr_node *poNode,
1406 : int bAllowMismatchTypeOnFieldComparison)
1407 :
1408 : {
1409 16101 : swq_field_type eRetType = SWQ_ERROR;
1410 16101 : swq_field_type eArgType = SWQ_OTHER;
1411 : // int nArgCount = -1;
1412 :
1413 16101 : switch (poNode->nOperation)
1414 : {
1415 5010 : case SWQ_AND:
1416 : case SWQ_OR:
1417 : case SWQ_NOT:
1418 5010 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1419 0 : return SWQ_ERROR;
1420 5010 : eRetType = SWQ_BOOLEAN;
1421 5010 : break;
1422 :
1423 10640 : case SWQ_EQ:
1424 : case SWQ_NE:
1425 : case SWQ_GT:
1426 : case SWQ_LT:
1427 : case SWQ_GE:
1428 : case SWQ_LE:
1429 : case SWQ_IN:
1430 : case SWQ_BETWEEN:
1431 10640 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1432 2 : return SWQ_ERROR;
1433 10638 : eRetType = SWQ_BOOLEAN;
1434 10638 : SWQAutoConvertStringToNumeric(poNode);
1435 10638 : SWQAutoPromoteIntegerToInteger64OrFloat(poNode);
1436 10638 : SWQAutoPromoteStringToDateTime(poNode);
1437 10638 : eArgType = poNode->papoSubExpr[0]->field_type;
1438 10638 : break;
1439 :
1440 219 : case SWQ_ISNULL:
1441 219 : eRetType = SWQ_BOOLEAN;
1442 219 : break;
1443 :
1444 84 : case SWQ_LIKE:
1445 : case SWQ_ILIKE:
1446 84 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1447 1 : return SWQ_ERROR;
1448 83 : eRetType = SWQ_BOOLEAN;
1449 83 : eArgType = SWQ_STRING;
1450 83 : break;
1451 :
1452 38 : case SWQ_ADD:
1453 38 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1454 2 : return SWQ_ERROR;
1455 36 : SWQAutoPromoteIntegerToInteger64OrFloat(poNode);
1456 36 : if (poNode->papoSubExpr[0]->field_type == SWQ_STRING)
1457 : {
1458 1 : eRetType = SWQ_STRING;
1459 1 : eArgType = SWQ_STRING;
1460 : }
1461 35 : else if (poNode->papoSubExpr[0]->field_type == SWQ_FLOAT ||
1462 25 : poNode->papoSubExpr[1]->field_type == SWQ_FLOAT)
1463 : {
1464 13 : eRetType = SWQ_FLOAT;
1465 13 : eArgType = SWQ_FLOAT;
1466 : }
1467 22 : else if (poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 ||
1468 17 : poNode->papoSubExpr[1]->field_type == SWQ_INTEGER64)
1469 : {
1470 6 : eRetType = SWQ_INTEGER64;
1471 6 : eArgType = SWQ_INTEGER64;
1472 : }
1473 : else
1474 : {
1475 16 : eRetType = SWQ_INTEGER;
1476 16 : eArgType = SWQ_INTEGER;
1477 : }
1478 36 : break;
1479 :
1480 72 : case SWQ_SUBTRACT:
1481 : case SWQ_MULTIPLY:
1482 : case SWQ_DIVIDE:
1483 : case SWQ_MODULUS:
1484 72 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1485 3 : return SWQ_ERROR;
1486 69 : SWQAutoPromoteIntegerToInteger64OrFloat(poNode);
1487 69 : if (poNode->papoSubExpr[0]->field_type == SWQ_FLOAT ||
1488 45 : poNode->papoSubExpr[1]->field_type == SWQ_FLOAT)
1489 : {
1490 25 : eRetType = SWQ_FLOAT;
1491 25 : eArgType = SWQ_FLOAT;
1492 : }
1493 44 : else if (poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 ||
1494 16 : poNode->papoSubExpr[1]->field_type == SWQ_INTEGER64)
1495 : {
1496 29 : eRetType = SWQ_INTEGER64;
1497 29 : eArgType = SWQ_INTEGER64;
1498 : }
1499 : else
1500 : {
1501 15 : eRetType = SWQ_INTEGER;
1502 15 : eArgType = SWQ_INTEGER;
1503 : }
1504 69 : break;
1505 :
1506 7 : case SWQ_CONCAT:
1507 7 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1508 1 : return SWQ_ERROR;
1509 6 : eRetType = SWQ_STRING;
1510 6 : eArgType = SWQ_STRING;
1511 6 : break;
1512 :
1513 6 : case SWQ_SUBSTR:
1514 6 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1515 1 : return SWQ_ERROR;
1516 5 : eRetType = SWQ_STRING;
1517 5 : if (poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2)
1518 : {
1519 1 : CPLError(CE_Failure, CPLE_AppDefined,
1520 : "Expected 2 or 3 arguments to SUBSTR(), but got %d.",
1521 : poNode->nSubExprCount);
1522 1 : return SWQ_ERROR;
1523 : }
1524 4 : if (poNode->papoSubExpr[0]->field_type != SWQ_STRING ||
1525 3 : poNode->papoSubExpr[1]->field_type != SWQ_INTEGER ||
1526 3 : (poNode->nSubExprCount > 2 &&
1527 2 : poNode->papoSubExpr[2]->field_type != SWQ_INTEGER))
1528 : {
1529 1 : CPLError(
1530 : CE_Failure, CPLE_AppDefined,
1531 : "Wrong argument type for SUBSTR(), "
1532 : "expected SUBSTR(string,int,int) or SUBSTR(string,int).");
1533 1 : return SWQ_ERROR;
1534 : }
1535 3 : break;
1536 :
1537 25 : case SWQ_HSTORE_GET_VALUE:
1538 25 : if (!SWQCheckSubExprAreNotGeometries(poNode))
1539 0 : return SWQ_ERROR;
1540 25 : eRetType = SWQ_STRING;
1541 25 : if (poNode->nSubExprCount != 2)
1542 : {
1543 1 : CPLError(
1544 : CE_Failure, CPLE_AppDefined,
1545 : "Expected 2 arguments to hstore_get_value(), but got %d.",
1546 : poNode->nSubExprCount);
1547 1 : return SWQ_ERROR;
1548 : }
1549 24 : if (poNode->papoSubExpr[0]->field_type != SWQ_STRING ||
1550 23 : poNode->papoSubExpr[1]->field_type != SWQ_STRING)
1551 : {
1552 1 : CPLError(CE_Failure, CPLE_AppDefined,
1553 : "Wrong argument type for hstore_get_value(), "
1554 : "expected hstore_get_value(string,string).");
1555 1 : return SWQ_ERROR;
1556 : }
1557 23 : break;
1558 :
1559 0 : default:
1560 : {
1561 : const swq_operation *poOp =
1562 0 : swq_op_registrar::GetOperator(poNode->nOperation);
1563 :
1564 0 : CPLError(CE_Failure, CPLE_AppDefined,
1565 : "SWQGeneralChecker() called on unsupported operation %s.",
1566 0 : poOp->pszName);
1567 0 : return SWQ_ERROR;
1568 : }
1569 : }
1570 : /* -------------------------------------------------------------------- */
1571 : /* Check argument types. */
1572 : /* -------------------------------------------------------------------- */
1573 16087 : if (eArgType != SWQ_OTHER)
1574 : {
1575 10815 : if (SWQ_IS_INTEGER(eArgType) || eArgType == SWQ_BOOLEAN)
1576 8728 : eArgType = SWQ_FLOAT;
1577 :
1578 32571 : for (int i = 0; i < poNode->nSubExprCount; i++)
1579 : {
1580 21761 : swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
1581 21761 : if (SWQ_IS_INTEGER(eThisArgType) || eThisArgType == SWQ_BOOLEAN)
1582 17476 : eThisArgType = SWQ_FLOAT;
1583 :
1584 21761 : if (eArgType != eThisArgType)
1585 : {
1586 : // Convenience for join. We allow comparing numeric columns
1587 : // and string columns, by casting string columns to numeric.
1588 5 : if (bAllowMismatchTypeOnFieldComparison &&
1589 3 : poNode->nSubExprCount == 2 &&
1590 3 : poNode->nOperation == SWQ_EQ &&
1591 3 : poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
1592 3 : poNode->papoSubExpr[i]->eNodeType == SNT_COLUMN &&
1593 2 : eArgType == SWQ_FLOAT && eThisArgType == SWQ_STRING)
1594 : {
1595 2 : swq_expr_node *poNewNode = new swq_expr_node(SWQ_CAST);
1596 2 : poNewNode->PushSubExpression(poNode->papoSubExpr[i]);
1597 2 : poNewNode->PushSubExpression(new swq_expr_node("FLOAT"));
1598 2 : SWQCastChecker(poNewNode, FALSE);
1599 2 : poNode->papoSubExpr[i] = poNewNode;
1600 2 : break;
1601 : }
1602 3 : if (bAllowMismatchTypeOnFieldComparison &&
1603 1 : poNode->nSubExprCount == 2 &&
1604 1 : poNode->nOperation == SWQ_EQ &&
1605 1 : poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
1606 1 : poNode->papoSubExpr[i]->eNodeType == SNT_COLUMN &&
1607 1 : eThisArgType == SWQ_FLOAT && eArgType == SWQ_STRING)
1608 : {
1609 1 : swq_expr_node *poNewNode = new swq_expr_node(SWQ_CAST);
1610 1 : poNewNode->PushSubExpression(poNode->papoSubExpr[0]);
1611 1 : poNewNode->PushSubExpression(new swq_expr_node("FLOAT"));
1612 1 : SWQCastChecker(poNewNode, FALSE);
1613 1 : poNode->papoSubExpr[0] = poNewNode;
1614 1 : break;
1615 : }
1616 :
1617 : const swq_operation *poOp =
1618 2 : swq_op_registrar::GetOperator(poNode->nOperation);
1619 :
1620 2 : CPLError(CE_Failure, CPLE_AppDefined,
1621 : "Type mismatch or improper type of arguments "
1622 : "to %s operator.",
1623 2 : poOp->pszName);
1624 2 : return SWQ_ERROR;
1625 : }
1626 : }
1627 : }
1628 :
1629 : /* -------------------------------------------------------------------- */
1630 : /* Validate the arg count if requested. */
1631 : /* -------------------------------------------------------------------- */
1632 : #if 0
1633 : // nArgCount was always -1, so this block was never executed.
1634 : if( nArgCount != -1
1635 : && nArgCount != poNode->nSubExprCount )
1636 : {
1637 : const swq_operation *poOp =
1638 : swq_op_registrar::GetOperator(poNode->nOperation);
1639 :
1640 : CPLError( CE_Failure, CPLE_AppDefined,
1641 : "Expected %d arguments to %s, but got %d arguments.",
1642 : nArgCount,
1643 : poOp->pszName,
1644 : poNode->nSubExprCount );
1645 : return SWQ_ERROR;
1646 : }
1647 : #endif
1648 :
1649 16085 : return eRetType;
1650 : }
1651 :
1652 : /************************************************************************/
1653 : /* SWQCastEvaluator() */
1654 : /************************************************************************/
1655 :
1656 236 : swq_expr_node *SWQCastEvaluator(swq_expr_node *node,
1657 : swq_expr_node **sub_node_values,
1658 : const swq_evaluation_context &)
1659 :
1660 : {
1661 236 : swq_expr_node *poRetNode = nullptr;
1662 236 : swq_expr_node *poSrcNode = sub_node_values[0];
1663 :
1664 236 : switch (node->field_type)
1665 : {
1666 22 : case SWQ_INTEGER:
1667 : {
1668 22 : poRetNode = new swq_expr_node(0);
1669 22 : poRetNode->is_null = poSrcNode->is_null;
1670 :
1671 22 : switch (poSrcNode->field_type)
1672 : {
1673 6 : case SWQ_INTEGER:
1674 : case SWQ_BOOLEAN:
1675 6 : poRetNode->int_value = poSrcNode->int_value;
1676 6 : break;
1677 :
1678 0 : case SWQ_INTEGER64:
1679 : // TODO: Warn in case of overflow?
1680 0 : poRetNode->int_value =
1681 0 : static_cast<int>(poSrcNode->int_value);
1682 0 : break;
1683 :
1684 1 : case SWQ_FLOAT:
1685 : // TODO: Warn in case of overflow?
1686 1 : poRetNode->int_value =
1687 1 : static_cast<int>(poSrcNode->float_value);
1688 1 : break;
1689 :
1690 15 : default:
1691 15 : poRetNode->int_value = atoi(poSrcNode->string_value);
1692 15 : break;
1693 : }
1694 : }
1695 22 : break;
1696 :
1697 4 : case SWQ_INTEGER64:
1698 : {
1699 4 : poRetNode = new swq_expr_node(0);
1700 4 : poRetNode->is_null = poSrcNode->is_null;
1701 4 : poRetNode->field_type = SWQ_INTEGER64;
1702 :
1703 4 : switch (poSrcNode->field_type)
1704 : {
1705 4 : case SWQ_INTEGER:
1706 : case SWQ_INTEGER64:
1707 : case SWQ_BOOLEAN:
1708 4 : poRetNode->int_value = poSrcNode->int_value;
1709 4 : break;
1710 :
1711 0 : case SWQ_FLOAT:
1712 0 : poRetNode->int_value =
1713 0 : static_cast<GIntBig>(poSrcNode->float_value);
1714 0 : break;
1715 :
1716 0 : default:
1717 0 : poRetNode->int_value =
1718 0 : CPLAtoGIntBig(poSrcNode->string_value);
1719 0 : break;
1720 : }
1721 : }
1722 4 : break;
1723 :
1724 176 : case SWQ_FLOAT:
1725 : {
1726 176 : poRetNode = new swq_expr_node(0.0);
1727 176 : poRetNode->is_null = poSrcNode->is_null;
1728 :
1729 176 : switch (poSrcNode->field_type)
1730 : {
1731 3 : case SWQ_INTEGER:
1732 : case SWQ_INTEGER64:
1733 : case SWQ_BOOLEAN:
1734 3 : poRetNode->float_value =
1735 3 : static_cast<double>(poSrcNode->int_value);
1736 3 : break;
1737 :
1738 0 : case SWQ_FLOAT:
1739 0 : poRetNode->float_value = poSrcNode->float_value;
1740 0 : break;
1741 :
1742 173 : default:
1743 173 : poRetNode->float_value = CPLAtof(poSrcNode->string_value);
1744 173 : break;
1745 : }
1746 : }
1747 176 : break;
1748 :
1749 15 : case SWQ_GEOMETRY:
1750 : {
1751 15 : poRetNode = new swq_expr_node(static_cast<OGRGeometry *>(nullptr));
1752 15 : if (!poSrcNode->is_null)
1753 : {
1754 13 : switch (poSrcNode->field_type)
1755 : {
1756 6 : case SWQ_GEOMETRY:
1757 : {
1758 6 : poRetNode->geometry_value =
1759 6 : poSrcNode->geometry_value->clone();
1760 6 : poRetNode->is_null = FALSE;
1761 6 : break;
1762 : }
1763 :
1764 7 : case SWQ_STRING:
1765 : {
1766 7 : OGRGeometryFactory::createFromWkt(
1767 7 : poSrcNode->string_value, nullptr,
1768 : &(poRetNode->geometry_value));
1769 7 : if (poRetNode->geometry_value != nullptr)
1770 7 : poRetNode->is_null = FALSE;
1771 7 : break;
1772 : }
1773 :
1774 0 : default:
1775 0 : break;
1776 : }
1777 : }
1778 15 : break;
1779 : }
1780 :
1781 : // Everything else is a string.
1782 19 : default:
1783 : {
1784 19 : CPLString osRet;
1785 :
1786 19 : switch (poSrcNode->field_type)
1787 : {
1788 6 : case SWQ_INTEGER:
1789 : case SWQ_BOOLEAN:
1790 : case SWQ_INTEGER64:
1791 6 : osRet.Printf(CPL_FRMT_GIB, poSrcNode->int_value);
1792 6 : break;
1793 :
1794 0 : case SWQ_FLOAT:
1795 0 : osRet.Printf("%.15g", poSrcNode->float_value);
1796 0 : break;
1797 :
1798 3 : case SWQ_GEOMETRY:
1799 : {
1800 3 : if (poSrcNode->geometry_value != nullptr)
1801 : {
1802 2 : char *pszWKT = nullptr;
1803 2 : poSrcNode->geometry_value->exportToWkt(&pszWKT);
1804 2 : osRet = pszWKT;
1805 2 : CPLFree(pszWKT);
1806 : }
1807 : else
1808 1 : osRet = "";
1809 3 : break;
1810 : }
1811 :
1812 10 : default:
1813 10 : osRet = poSrcNode->string_value;
1814 10 : break;
1815 : }
1816 :
1817 19 : if (node->nSubExprCount > 2)
1818 : {
1819 13 : int nWidth = static_cast<int>(sub_node_values[2]->int_value);
1820 13 : if (nWidth > 0 && static_cast<int>(osRet.size()) > nWidth)
1821 0 : osRet.resize(nWidth);
1822 : }
1823 :
1824 19 : poRetNode = new swq_expr_node(osRet.c_str());
1825 19 : poRetNode->is_null = poSrcNode->is_null;
1826 : }
1827 : }
1828 :
1829 236 : return poRetNode;
1830 : }
1831 :
1832 : /************************************************************************/
1833 : /* SWQCastChecker() */
1834 : /************************************************************************/
1835 :
1836 89 : swq_field_type SWQCastChecker(swq_expr_node *poNode,
1837 : int /* bAllowMismatchTypeOnFieldComparison */)
1838 :
1839 : {
1840 89 : swq_field_type eType = SWQ_ERROR;
1841 89 : const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
1842 :
1843 89 : if (poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY &&
1844 13 : !(EQUAL(pszTypeName, "character") || EQUAL(pszTypeName, "geometry")))
1845 : {
1846 1 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot cast geometry to %s",
1847 : pszTypeName);
1848 : }
1849 88 : else if (EQUAL(pszTypeName, "boolean"))
1850 : {
1851 1 : eType = SWQ_BOOLEAN;
1852 : }
1853 87 : else if (EQUAL(pszTypeName, "character"))
1854 : {
1855 9 : eType = SWQ_STRING;
1856 : }
1857 78 : else if (EQUAL(pszTypeName, "integer"))
1858 : {
1859 12 : eType = SWQ_INTEGER;
1860 : }
1861 66 : else if (EQUAL(pszTypeName, "bigint"))
1862 : {
1863 : // Handle CAST(fid AS bigint) by changing the field_type of fid to
1864 : // Integer64. A bit of a hack.
1865 5 : if (poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
1866 3 : poNode->papoSubExpr[0]->field_type == SWQ_INTEGER &&
1867 1 : strcmp(poNode->papoSubExpr[0]->string_value, "fid") == 0)
1868 : {
1869 1 : poNode->papoSubExpr[0]->field_type = SWQ_INTEGER64;
1870 : }
1871 5 : eType = SWQ_INTEGER64;
1872 : }
1873 61 : else if (EQUAL(pszTypeName, "smallint"))
1874 : {
1875 1 : eType = SWQ_INTEGER;
1876 : }
1877 60 : else if (EQUAL(pszTypeName, "float"))
1878 : {
1879 38 : eType = SWQ_FLOAT;
1880 : }
1881 22 : else if (EQUAL(pszTypeName, "numeric"))
1882 : {
1883 2 : eType = SWQ_FLOAT;
1884 : }
1885 20 : else if (EQUAL(pszTypeName, "timestamp"))
1886 : {
1887 0 : eType = SWQ_TIMESTAMP;
1888 : }
1889 20 : else if (EQUAL(pszTypeName, "date"))
1890 : {
1891 0 : eType = SWQ_DATE;
1892 : }
1893 20 : else if (EQUAL(pszTypeName, "time"))
1894 : {
1895 0 : eType = SWQ_TIME;
1896 : }
1897 20 : else if (EQUAL(pszTypeName, "geometry"))
1898 : {
1899 20 : if (!(poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY ||
1900 11 : poNode->papoSubExpr[0]->field_type == SWQ_STRING))
1901 : {
1902 1 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot cast %s to geometry",
1903 1 : SWQFieldTypeToString(poNode->papoSubExpr[0]->field_type));
1904 : }
1905 : else
1906 19 : eType = SWQ_GEOMETRY;
1907 : }
1908 : else
1909 : {
1910 0 : CPLError(CE_Failure, CPLE_AppDefined,
1911 : "Unrecognized typename %s in CAST operator.", pszTypeName);
1912 : }
1913 :
1914 89 : poNode->field_type = eType;
1915 :
1916 89 : return eType;
1917 : }
|