Coverage Report

Created: 2025-06-13 06:29

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