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