Line data Source code
1 : /******************************************************************************
2 : *
3 : * Component: OGR SQL Engine
4 : * Purpose: Implementation of the swq_expr_node class used to represent a
5 : * node in an SQL expression.
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
10 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #ifndef DOXYGEN_SKIP
16 :
17 : #include "cpl_port.h"
18 : #include "ogr_swq.h"
19 :
20 : #include <algorithm>
21 : #include <cctype>
22 : #include <cstdio>
23 : #include <cstring>
24 : #include <string>
25 : #include <vector>
26 :
27 : #include "cpl_conv.h"
28 : #include "cpl_error.h"
29 : #include "cpl_multiproc.h"
30 : #include "cpl_string.h"
31 : #include "ogr_geometry.h"
32 :
33 : /************************************************************************/
34 : /* swq_expr_node() */
35 : /************************************************************************/
36 :
37 : swq_expr_node::swq_expr_node() = default;
38 :
39 : /************************************************************************/
40 : /* swq_expr_node(int) */
41 : /************************************************************************/
42 :
43 111753 : swq_expr_node::swq_expr_node(int nValueIn) : int_value(nValueIn)
44 : {
45 111753 : }
46 :
47 : /************************************************************************/
48 : /* swq_expr_node(GIntBig) */
49 : /************************************************************************/
50 :
51 4910 : swq_expr_node::swq_expr_node(GIntBig nValueIn)
52 4910 : : field_type(SWQ_INTEGER64), int_value(nValueIn)
53 : {
54 4910 : }
55 :
56 : /************************************************************************/
57 : /* swq_expr_node(double) */
58 : /************************************************************************/
59 :
60 6687 : swq_expr_node::swq_expr_node(double dfValueIn)
61 6687 : : field_type(SWQ_FLOAT), float_value(dfValueIn)
62 : {
63 6687 : }
64 :
65 : /************************************************************************/
66 : /* swq_expr_node(const char*) */
67 : /************************************************************************/
68 :
69 29902 : swq_expr_node::swq_expr_node(const char *pszValueIn)
70 29902 : : field_type(SWQ_STRING), is_null(pszValueIn == nullptr),
71 29902 : string_value(CPLStrdup(pszValueIn ? pszValueIn : ""))
72 : {
73 29902 : }
74 :
75 : /************************************************************************/
76 : /* swq_expr_node(OGRGeometry *) */
77 : /************************************************************************/
78 :
79 35 : swq_expr_node::swq_expr_node(OGRGeometry *poGeomIn)
80 35 : : field_type(SWQ_GEOMETRY), is_null(poGeomIn == nullptr),
81 35 : geometry_value(poGeomIn ? poGeomIn->clone() : nullptr)
82 : {
83 35 : }
84 :
85 : /************************************************************************/
86 : /* swq_expr_node(swq_op) */
87 : /************************************************************************/
88 :
89 21492 : swq_expr_node::swq_expr_node(swq_op eOp)
90 21492 : : eNodeType(SNT_OPERATION), nOperation(eOp)
91 : {
92 21492 : }
93 :
94 : /************************************************************************/
95 : /* ~swq_expr_node() */
96 : /************************************************************************/
97 :
98 357718 : swq_expr_node::~swq_expr_node()
99 :
100 : {
101 178859 : reset();
102 178859 : }
103 :
104 : /************************************************************************/
105 : /* reset() */
106 : /************************************************************************/
107 :
108 181525 : void swq_expr_node::reset()
109 : {
110 181525 : CPLFree(table_name);
111 181525 : table_name = nullptr;
112 181525 : CPLFree(string_value);
113 181525 : string_value = nullptr;
114 :
115 214554 : for (int i = 0; i < nSubExprCount; i++)
116 33029 : delete papoSubExpr[i];
117 181525 : CPLFree(papoSubExpr);
118 181525 : nSubExprCount = 0;
119 181525 : papoSubExpr = nullptr;
120 181525 : delete geometry_value;
121 181525 : geometry_value = nullptr;
122 181525 : }
123 :
124 : /************************************************************************/
125 : /* operator==() */
126 : /************************************************************************/
127 :
128 1984 : bool swq_expr_node::operator==(const swq_expr_node &other) const
129 : {
130 1984 : if (eNodeType != other.eNodeType || field_type != other.field_type ||
131 1168 : nOperation != other.nOperation || field_index != other.field_index ||
132 1140 : table_index != other.table_index ||
133 1128 : nSubExprCount != other.nSubExprCount || is_null != other.is_null ||
134 1104 : int_value != other.int_value || float_value != other.float_value ||
135 1080 : bHidden != other.bHidden)
136 : {
137 904 : return false;
138 : }
139 1168 : for (int i = 0; i < nSubExprCount; ++i)
140 : {
141 92 : if (!(*(papoSubExpr[i]) == *(other.papoSubExpr[i])))
142 : {
143 4 : return false;
144 : }
145 : }
146 1076 : if (table_name && !other.table_name)
147 : {
148 4 : return false;
149 : }
150 1072 : if (!table_name && other.table_name)
151 : {
152 4 : return false;
153 : }
154 1068 : if (table_name && other.table_name &&
155 92 : strcmp(table_name, other.table_name) != 0)
156 : {
157 4 : return false;
158 : }
159 1064 : if (string_value && !other.string_value)
160 : {
161 0 : return false;
162 : }
163 1064 : if (!string_value && other.string_value)
164 : {
165 0 : return false;
166 : }
167 1064 : if (string_value && other.string_value &&
168 136 : strcmp(string_value, other.string_value) != 0)
169 : {
170 4 : return false;
171 : }
172 1060 : if (geometry_value && !other.geometry_value)
173 : {
174 0 : return false;
175 : }
176 1060 : if (!geometry_value && other.geometry_value)
177 : {
178 0 : return false;
179 : }
180 1152 : if (geometry_value && other.geometry_value &&
181 92 : !geometry_value->Equals(other.geometry_value))
182 : {
183 4 : return false;
184 : }
185 1056 : return true;
186 : }
187 :
188 : /************************************************************************/
189 : /* swq_expr_node(const swq_expr_node& other) */
190 : /************************************************************************/
191 :
192 1728 : swq_expr_node::swq_expr_node(const swq_expr_node &other)
193 : {
194 1728 : *this = other;
195 1728 : }
196 :
197 : /************************************************************************/
198 : /* operator= (const swq_expr_node& other) */
199 : /************************************************************************/
200 :
201 2190 : swq_expr_node &swq_expr_node::operator=(const swq_expr_node &other)
202 : {
203 2190 : if (this != &other)
204 : {
205 2190 : reset();
206 2190 : eNodeType = other.eNodeType;
207 2190 : field_type = other.field_type;
208 2190 : nOperation = other.nOperation;
209 2190 : field_index = other.field_index;
210 2190 : table_index = other.table_index;
211 2190 : if (other.table_name)
212 172 : table_name = CPLStrdup(other.table_name);
213 2399 : for (int i = 0; i < other.nSubExprCount; ++i)
214 209 : PushSubExpression(new swq_expr_node(*(other.papoSubExpr[i])));
215 2190 : is_null = other.is_null;
216 2190 : int_value = other.int_value;
217 2190 : float_value = other.float_value;
218 2190 : if (other.geometry_value)
219 174 : geometry_value = other.geometry_value->clone();
220 2190 : if (other.string_value)
221 326 : string_value = CPLStrdup(other.string_value);
222 2190 : bHidden = other.bHidden;
223 : }
224 2190 : return *this;
225 : }
226 :
227 : /************************************************************************/
228 : /* swq_expr_node(swq_expr_node&& other) */
229 : /************************************************************************/
230 :
231 0 : swq_expr_node::swq_expr_node(swq_expr_node &&other)
232 : {
233 0 : *this = std::move(other);
234 0 : }
235 :
236 : /************************************************************************/
237 : /* operator= (swq_expr_node&& other) */
238 : /************************************************************************/
239 :
240 476 : swq_expr_node &swq_expr_node::operator=(swq_expr_node &&other)
241 : {
242 476 : if (this != &other)
243 : {
244 476 : reset();
245 476 : eNodeType = other.eNodeType;
246 476 : field_type = other.field_type;
247 476 : nOperation = other.nOperation;
248 476 : field_index = other.field_index;
249 476 : table_index = other.table_index;
250 476 : std::swap(table_name, other.table_name);
251 476 : std::swap(nSubExprCount, other.nSubExprCount);
252 476 : std::swap(papoSubExpr, other.papoSubExpr);
253 476 : is_null = other.is_null;
254 476 : int_value = other.int_value;
255 476 : float_value = other.float_value;
256 476 : std::swap(geometry_value, other.geometry_value);
257 476 : std::swap(string_value, other.string_value);
258 476 : bHidden = other.bHidden;
259 : }
260 476 : return *this;
261 : }
262 :
263 : /************************************************************************/
264 : /* MarkAsTimestamp() */
265 : /************************************************************************/
266 :
267 312 : void swq_expr_node::MarkAsTimestamp()
268 :
269 : {
270 312 : CPLAssert(eNodeType == SNT_CONSTANT);
271 312 : CPLAssert(field_type == SWQ_STRING);
272 312 : field_type = SWQ_TIMESTAMP;
273 312 : }
274 :
275 : /************************************************************************/
276 : /* PushSubExpression() */
277 : /************************************************************************/
278 :
279 38282 : void swq_expr_node::PushSubExpression(swq_expr_node *child)
280 :
281 : {
282 38282 : nSubExprCount++;
283 38282 : papoSubExpr = static_cast<swq_expr_node **>(
284 38282 : CPLRealloc(papoSubExpr, sizeof(void *) * nSubExprCount));
285 :
286 38282 : papoSubExpr[nSubExprCount - 1] = child;
287 38282 : }
288 :
289 : /************************************************************************/
290 : /* ReverseSubExpressions() */
291 : /************************************************************************/
292 :
293 583 : void swq_expr_node::ReverseSubExpressions()
294 :
295 : {
296 995 : for (int i = 0; i < nSubExprCount / 2; i++)
297 : {
298 412 : std::swap(papoSubExpr[i], papoSubExpr[nSubExprCount - i - 1]);
299 : }
300 583 : }
301 :
302 : /************************************************************************/
303 : /* Check() */
304 : /* */
305 : /* Check argument types, etc. */
306 : /************************************************************************/
307 :
308 38787 : swq_field_type swq_expr_node::Check(
309 : swq_field_list *poFieldList, int bAllowFieldsInSecondaryTables,
310 : int bAllowMismatchTypeOnFieldComparison,
311 : swq_custom_func_registrar *poCustomFuncRegistrar, int nDepth)
312 :
313 : {
314 38787 : if (nDepth == 32)
315 : {
316 0 : CPLError(CE_Failure, CPLE_AppDefined,
317 : "Too many recursion levels in expression");
318 0 : return SWQ_ERROR;
319 : }
320 :
321 : /* -------------------------------------------------------------------- */
322 : /* Otherwise we take constants literally. */
323 : /* -------------------------------------------------------------------- */
324 38787 : if (eNodeType == SNT_CONSTANT)
325 14037 : return field_type;
326 :
327 : /* -------------------------------------------------------------------- */
328 : /* If this is intended to be a field definition, but has not */
329 : /* yet been looked up, we do so now. */
330 : /* -------------------------------------------------------------------- */
331 24750 : if (eNodeType == SNT_COLUMN && field_index == -1)
332 : {
333 8447 : field_index = swq_identify_field(table_name, string_value, poFieldList,
334 : &field_type, &table_index);
335 :
336 8447 : if (field_index < 0)
337 : {
338 4 : if (table_name)
339 3 : CPLError(CE_Failure, CPLE_AppDefined,
340 : R"("%s"."%s" not recognised as an available field.)",
341 : table_name, string_value);
342 : else
343 1 : CPLError(CE_Failure, CPLE_AppDefined,
344 : "\"%s\" not recognised as an available field.",
345 : string_value);
346 :
347 4 : return SWQ_ERROR;
348 : }
349 :
350 8443 : if (!bAllowFieldsInSecondaryTables && table_index != 0)
351 : {
352 1 : CPLError(
353 : CE_Failure, CPLE_AppDefined,
354 : "Cannot use field '%s' of a secondary table in this context",
355 : string_value);
356 1 : return SWQ_ERROR;
357 : }
358 : }
359 :
360 24745 : if (eNodeType == SNT_COLUMN)
361 8442 : return field_type;
362 :
363 : /* -------------------------------------------------------------------- */
364 : /* We are dealing with an operation - fetch the definition. */
365 : /* -------------------------------------------------------------------- */
366 : const swq_operation *poOp =
367 112 : (nOperation == SWQ_CUSTOM_FUNC && poCustomFuncRegistrar != nullptr)
368 16415 : ? poCustomFuncRegistrar->GetOperator(string_value)
369 16191 : : swq_op_registrar::GetOperator(nOperation);
370 :
371 16303 : if (poOp == nullptr)
372 : {
373 0 : if (nOperation == SWQ_CUSTOM_FUNC)
374 0 : CPLError(CE_Failure, CPLE_AppDefined,
375 : "Check(): Unable to find definition for operator %s.",
376 : string_value);
377 : else
378 0 : CPLError(CE_Failure, CPLE_AppDefined,
379 : "Check(): Unable to find definition for operator %d.",
380 0 : nOperation);
381 0 : return SWQ_ERROR;
382 : }
383 :
384 : /* -------------------------------------------------------------------- */
385 : /* Check subexpressions first. */
386 : /* -------------------------------------------------------------------- */
387 48601 : for (int i = 0; i < nSubExprCount; i++)
388 : {
389 32320 : if (papoSubExpr[i]->Check(poFieldList, bAllowFieldsInSecondaryTables,
390 : bAllowMismatchTypeOnFieldComparison,
391 : poCustomFuncRegistrar,
392 32320 : nDepth + 1) == SWQ_ERROR)
393 22 : return SWQ_ERROR;
394 : }
395 :
396 : /* -------------------------------------------------------------------- */
397 : /* Check this node. */
398 : /* -------------------------------------------------------------------- */
399 16281 : field_type = poOp->pfnChecker(this, bAllowMismatchTypeOnFieldComparison);
400 :
401 16281 : return field_type;
402 : }
403 :
404 : /************************************************************************/
405 : /* Dump() */
406 : /************************************************************************/
407 :
408 0 : void swq_expr_node::Dump(FILE *fp, int depth)
409 :
410 : {
411 0 : char spaces[60] = {};
412 :
413 : {
414 0 : int i = 0; // Used after for.
415 0 : for (; i < depth * 2 && i < static_cast<int>(sizeof(spaces)) - 1; i++)
416 0 : spaces[i] = ' ';
417 0 : spaces[i] = '\0';
418 : }
419 :
420 0 : if (eNodeType == SNT_COLUMN)
421 : {
422 0 : fprintf(fp, "%s Field %d\n", spaces, field_index);
423 0 : return;
424 : }
425 :
426 0 : if (eNodeType == SNT_CONSTANT)
427 : {
428 0 : if (field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 ||
429 0 : field_type == SWQ_BOOLEAN)
430 0 : fprintf(fp, "%s " CPL_FRMT_GIB "\n", spaces, int_value);
431 0 : else if (field_type == SWQ_FLOAT)
432 0 : fprintf(fp, "%s %.15g\n", spaces, float_value);
433 0 : else if (field_type == SWQ_GEOMETRY)
434 : {
435 0 : if (geometry_value == nullptr)
436 0 : fprintf(fp, "%s (null)\n", spaces);
437 : else
438 : {
439 0 : char *pszWKT = nullptr;
440 0 : geometry_value->exportToWkt(&pszWKT);
441 0 : fprintf(fp, "%s %s\n", spaces, pszWKT);
442 0 : CPLFree(pszWKT);
443 : }
444 : }
445 : else
446 0 : fprintf(fp, "%s %s\n", spaces, string_value);
447 0 : return;
448 : }
449 :
450 0 : CPLAssert(eNodeType == SNT_OPERATION);
451 :
452 0 : const swq_operation *op_def = swq_op_registrar::GetOperator(nOperation);
453 0 : if (op_def)
454 0 : fprintf(fp, "%s%s\n", spaces, op_def->pszName);
455 : else
456 0 : fprintf(fp, "%s%s\n", spaces, string_value);
457 :
458 0 : for (int i = 0; i < nSubExprCount; i++)
459 0 : papoSubExpr[i]->Dump(fp, depth + 1);
460 : }
461 :
462 : /************************************************************************/
463 : /* QuoteIfNecessary() */
464 : /* */
465 : /* Add quoting if necessary to unparse a string. */
466 : /************************************************************************/
467 :
468 414 : CPLString swq_expr_node::QuoteIfNecessary(const CPLString &osExpr, char chQuote)
469 :
470 : {
471 414 : if (osExpr[0] == '_')
472 0 : return Quote(osExpr, chQuote);
473 414 : if (osExpr == "*")
474 3 : return osExpr;
475 :
476 2719 : for (int i = 0; i < static_cast<int>(osExpr.size()); i++)
477 : {
478 2316 : char ch = osExpr[i];
479 2316 : if ((!(isalnum(static_cast<unsigned char>(ch)) || ch == '_')) ||
480 : ch == '.')
481 : {
482 8 : return Quote(osExpr, chQuote);
483 : }
484 : }
485 :
486 403 : if (swq_is_reserved_keyword(osExpr))
487 : {
488 1 : return Quote(osExpr, chQuote);
489 : }
490 :
491 402 : return osExpr;
492 : }
493 :
494 : /************************************************************************/
495 : /* Quote() */
496 : /* */
497 : /* Add quoting necessary to unparse a string. */
498 : /************************************************************************/
499 :
500 122 : CPLString swq_expr_node::Quote(const CPLString &osTarget, char chQuote)
501 :
502 : {
503 122 : CPLString osNew;
504 :
505 122 : osNew += chQuote;
506 :
507 1237 : for (int i = 0; i < static_cast<int>(osTarget.size()); i++)
508 : {
509 1115 : if (osTarget[i] == chQuote)
510 : {
511 0 : osNew += chQuote;
512 0 : osNew += chQuote;
513 : }
514 : else
515 1115 : osNew += osTarget[i];
516 : }
517 122 : osNew += chQuote;
518 :
519 122 : return osNew;
520 : }
521 :
522 : /************************************************************************/
523 : /* Unparse() */
524 : /************************************************************************/
525 :
526 3228 : char *swq_expr_node::Unparse(swq_field_list *field_list, char chColumnQuote)
527 :
528 : {
529 6456 : CPLString osExpr;
530 :
531 : /* -------------------------------------------------------------------- */
532 : /* Handle constants. */
533 : /* -------------------------------------------------------------------- */
534 3228 : if (eNodeType == SNT_CONSTANT)
535 : {
536 1689 : if (is_null)
537 37 : return CPLStrdup("NULL");
538 :
539 1652 : if (field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 ||
540 147 : field_type == SWQ_BOOLEAN)
541 1505 : osExpr.Printf(CPL_FRMT_GIB, int_value);
542 147 : else if (field_type == SWQ_FLOAT)
543 : {
544 34 : osExpr.Printf("%.15g", float_value);
545 : // Make sure this is interpreted as a floating point value
546 : // and not as an integer later.
547 34 : if (strchr(osExpr, '.') == nullptr &&
548 66 : strchr(osExpr, 'e') == nullptr &&
549 32 : strchr(osExpr, 'E') == nullptr)
550 32 : osExpr += '.';
551 : }
552 : else
553 : {
554 113 : osExpr = Quote(string_value);
555 : }
556 :
557 1652 : return CPLStrdup(osExpr);
558 : }
559 :
560 : /* -------------------------------------------------------------------- */
561 : /* Handle columns. */
562 : /* -------------------------------------------------------------------- */
563 1539 : if (eNodeType == SNT_COLUMN)
564 : {
565 386 : if (field_list == nullptr)
566 : {
567 9 : if (table_name)
568 : osExpr.Printf(
569 : "%s.%s",
570 4 : QuoteIfNecessary(table_name, chColumnQuote).c_str(),
571 6 : QuoteIfNecessary(string_value, chColumnQuote).c_str());
572 : else
573 : osExpr.Printf(
574 : "%s",
575 7 : QuoteIfNecessary(string_value, chColumnQuote).c_str());
576 : }
577 377 : else if (field_index != -1 && table_index < field_list->table_count &&
578 377 : table_index > 0)
579 : {
580 : // We deliberately browse through the list starting from the end
581 : // This is for the case where the FID column exists both as
582 : // FID and then real_fid_name. We want real_fid_name to be used
583 26 : for (int i = field_list->count - 1; i >= 0; i--)
584 : {
585 26 : if (field_list->table_ids[i] == table_index &&
586 6 : field_list->ids[i] == field_index)
587 : {
588 : osExpr.Printf(
589 : "%s.%s",
590 8 : QuoteIfNecessary(
591 4 : field_list->table_defs[table_index].table_name,
592 : chColumnQuote)
593 : .c_str(),
594 8 : QuoteIfNecessary(field_list->names[i], chColumnQuote)
595 8 : .c_str());
596 4 : break;
597 : }
598 4 : }
599 : }
600 373 : else if (field_index != -1)
601 : {
602 : // We deliberately browse through the list starting from the end
603 : // This is for the case where the FID column exists both as
604 : // FID and then real_fid_name. We want real_fid_name to be used
605 2709 : for (int i = field_list->count - 1; i >= 0; i--)
606 : {
607 2709 : if (field_list->table_ids[i] == table_index &&
608 2691 : field_list->ids[i] == field_index)
609 : {
610 746 : osExpr.Printf("%s", QuoteIfNecessary(field_list->names[i],
611 : chColumnQuote)
612 373 : .c_str());
613 373 : break;
614 : }
615 : }
616 : }
617 :
618 386 : if (osExpr.empty())
619 : {
620 0 : return CPLStrdup(CPLSPrintf("%c%c", chColumnQuote, chColumnQuote));
621 : }
622 :
623 : // The string is just alphanum and not a reserved SQL keyword,
624 : // no needs to quote and escape.
625 386 : return CPLStrdup(osExpr.c_str());
626 : }
627 :
628 : /* -------------------------------------------------------------------- */
629 : /* Operation - start by unparsing all the subexpressions. */
630 : /* -------------------------------------------------------------------- */
631 2306 : std::vector<char *> apszSubExpr;
632 1153 : apszSubExpr.reserve(nSubExprCount);
633 3379 : for (int i = 0; i < nSubExprCount; i++)
634 2226 : apszSubExpr.push_back(
635 2226 : papoSubExpr[i]->Unparse(field_list, chColumnQuote));
636 :
637 1153 : osExpr = UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
638 :
639 : /* -------------------------------------------------------------------- */
640 : /* cleanup subexpressions. */
641 : /* -------------------------------------------------------------------- */
642 3379 : for (int i = 0; i < nSubExprCount; i++)
643 2226 : CPLFree(apszSubExpr[i]);
644 :
645 1153 : return CPLStrdup(osExpr.c_str());
646 : }
647 :
648 : /************************************************************************/
649 : /* UnparseOperationFromUnparsedSubExpr() */
650 : /************************************************************************/
651 :
652 1272 : CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char **apszSubExpr)
653 : {
654 1272 : CPLString osExpr;
655 :
656 : /* -------------------------------------------------------------------- */
657 : /* Put things together in a fashion depending on the operator. */
658 : /* -------------------------------------------------------------------- */
659 1272 : const swq_operation *poOp = swq_op_registrar::GetOperator(nOperation);
660 :
661 1272 : if (poOp == nullptr && nOperation != SWQ_CUSTOM_FUNC)
662 : {
663 0 : CPLAssert(false);
664 : return osExpr;
665 : }
666 :
667 7156 : const auto AddSubExpr = [this, apszSubExpr, &osExpr](int idx)
668 : {
669 2426 : if (papoSubExpr[idx]->eNodeType == SNT_COLUMN ||
670 1866 : papoSubExpr[idx]->eNodeType == SNT_CONSTANT)
671 : {
672 2207 : osExpr += apszSubExpr[idx];
673 : }
674 : else
675 : {
676 219 : osExpr += '(';
677 219 : osExpr += apszSubExpr[idx];
678 219 : osExpr += ')';
679 : }
680 3698 : };
681 :
682 1272 : switch (nOperation)
683 : {
684 : // Binary infix operators.
685 1058 : case SWQ_OR:
686 : case SWQ_AND:
687 : case SWQ_EQ:
688 : case SWQ_NE:
689 : case SWQ_GT:
690 : case SWQ_LT:
691 : case SWQ_GE:
692 : case SWQ_LE:
693 : case SWQ_LIKE:
694 : case SWQ_ILIKE:
695 : case SWQ_ADD:
696 : case SWQ_SUBTRACT:
697 : case SWQ_MULTIPLY:
698 : case SWQ_DIVIDE:
699 : case SWQ_MODULUS:
700 1058 : CPLAssert(nSubExprCount >= 2);
701 1058 : AddSubExpr(0);
702 1058 : osExpr += " ";
703 1058 : osExpr += poOp->pszName;
704 1058 : osExpr += " ";
705 1058 : AddSubExpr(1);
706 1058 : if ((nOperation == SWQ_LIKE || nOperation == SWQ_ILIKE) &&
707 11 : nSubExprCount == 3)
708 : {
709 1 : osExpr += " ESCAPE ";
710 1 : AddSubExpr(2);
711 : }
712 1058 : break;
713 :
714 81 : case SWQ_NOT:
715 81 : CPLAssert(nSubExprCount == 1);
716 81 : osExpr = "NOT ";
717 81 : AddSubExpr(0);
718 81 : break;
719 :
720 36 : case SWQ_ISNULL:
721 36 : CPLAssert(nSubExprCount == 1);
722 36 : AddSubExpr(0);
723 36 : osExpr += " IS NULL";
724 36 : break;
725 :
726 42 : case SWQ_IN:
727 42 : AddSubExpr(0);
728 42 : osExpr += " IN(";
729 112 : for (int i = 1; i < nSubExprCount; i++)
730 : {
731 70 : if (i > 1)
732 28 : osExpr += ",";
733 70 : AddSubExpr(i);
734 : }
735 42 : osExpr += ")";
736 42 : break;
737 :
738 2 : case SWQ_BETWEEN:
739 2 : CPLAssert(nSubExprCount == 3);
740 2 : AddSubExpr(0);
741 2 : osExpr += ' ';
742 2 : osExpr += poOp->pszName;
743 2 : osExpr += ' ';
744 2 : AddSubExpr(1);
745 2 : osExpr += " AND ";
746 2 : AddSubExpr(2);
747 2 : break;
748 :
749 36 : case SWQ_CAST:
750 36 : osExpr = "CAST(";
751 112 : for (int i = 0; i < nSubExprCount; i++)
752 : {
753 76 : if (i == 1)
754 36 : osExpr += " AS ";
755 40 : else if (i > 2)
756 1 : osExpr += ", ";
757 :
758 76 : const int nLen = static_cast<int>(strlen(apszSubExpr[i]));
759 76 : if ((i == 1 && (apszSubExpr[i][0] == '\'' && nLen > 2 &&
760 76 : apszSubExpr[i][nLen - 1] == '\'')) ||
761 3 : (i == 2 && EQUAL(apszSubExpr[1], "'GEOMETRY")))
762 : {
763 38 : apszSubExpr[i][nLen - 1] = '\0';
764 38 : osExpr += apszSubExpr[i] + 1;
765 : }
766 : else
767 38 : AddSubExpr(i);
768 :
769 76 : if (i == 1 && nSubExprCount > 2)
770 3 : osExpr += "(";
771 73 : else if (i > 1 && i == nSubExprCount - 1)
772 3 : osExpr += ")";
773 : }
774 36 : osExpr += ")";
775 36 : break;
776 :
777 17 : default: // function style.
778 17 : if (nOperation != SWQ_CUSTOM_FUNC)
779 1 : osExpr.Printf("%s(", poOp->pszName);
780 : else
781 16 : osExpr.Printf("%s(", string_value);
782 53 : for (int i = 0; i < nSubExprCount; i++)
783 : {
784 36 : if (i > 0)
785 19 : osExpr += ",";
786 36 : AddSubExpr(i);
787 : }
788 17 : osExpr += ")";
789 17 : break;
790 : }
791 :
792 2544 : return osExpr;
793 : }
794 :
795 : /************************************************************************/
796 : /* Clone() */
797 : /************************************************************************/
798 :
799 74 : swq_expr_node *swq_expr_node::Clone()
800 : {
801 74 : return new swq_expr_node(*this);
802 : }
803 :
804 : /************************************************************************/
805 : /* Evaluate() */
806 : /************************************************************************/
807 :
808 66100 : swq_expr_node *swq_expr_node::Evaluate(swq_field_fetcher pfnFetcher,
809 : void *pRecord,
810 : const swq_evaluation_context &sContext)
811 :
812 : {
813 66100 : return Evaluate(pfnFetcher, pRecord, sContext, 0);
814 : }
815 :
816 121885 : swq_expr_node *swq_expr_node::Evaluate(swq_field_fetcher pfnFetcher,
817 : void *pRecord,
818 : const swq_evaluation_context &sContext,
819 : int nRecLevel)
820 :
821 : {
822 121885 : swq_expr_node *poRetNode = nullptr;
823 121885 : if (nRecLevel == 32)
824 : {
825 0 : CPLError(CE_Failure, CPLE_AppDefined,
826 : "Too many recursion levels in expression");
827 0 : return nullptr;
828 : }
829 :
830 : /* -------------------------------------------------------------------- */
831 : /* Duplicate ourselves if we are already a constant. */
832 : /* -------------------------------------------------------------------- */
833 121885 : if (eNodeType == SNT_CONSTANT)
834 : {
835 69 : return Clone();
836 : }
837 :
838 : /* -------------------------------------------------------------------- */
839 : /* If this is a field value from a record, fetch and return it. */
840 : /* -------------------------------------------------------------------- */
841 121816 : if (eNodeType == SNT_COLUMN)
842 : {
843 40617 : return pfnFetcher(this, pRecord);
844 : }
845 :
846 : /* -------------------------------------------------------------------- */
847 : /* This is an operation, collect the arguments keeping track of */
848 : /* which we will need to free. */
849 : /* -------------------------------------------------------------------- */
850 162398 : std::vector<swq_expr_node *> apoValues;
851 81199 : std::vector<int> anValueNeedsFree;
852 81199 : bool bError = false;
853 81199 : apoValues.reserve(nSubExprCount);
854 242875 : for (int i = 0; i < nSubExprCount && !bError; i++)
855 : {
856 161676 : if (papoSubExpr[i]->eNodeType == SNT_CONSTANT)
857 : {
858 : // avoid duplication.
859 105891 : apoValues.push_back(papoSubExpr[i]);
860 105891 : anValueNeedsFree.push_back(FALSE);
861 : }
862 : else
863 : {
864 55785 : swq_expr_node *poSubExprVal = papoSubExpr[i]->Evaluate(
865 55785 : pfnFetcher, pRecord, sContext, nRecLevel + 1);
866 55785 : if (poSubExprVal == nullptr)
867 0 : bError = true;
868 : else
869 : {
870 55785 : apoValues.push_back(poSubExprVal);
871 55785 : anValueNeedsFree.push_back(TRUE);
872 : }
873 : }
874 : }
875 :
876 : /* -------------------------------------------------------------------- */
877 : /* Fetch the operator definition and function. */
878 : /* -------------------------------------------------------------------- */
879 81199 : if (!bError)
880 : {
881 81199 : const swq_operation *poOp = swq_op_registrar::GetOperator(nOperation);
882 81199 : if (poOp == nullptr)
883 : {
884 0 : if (nOperation == SWQ_CUSTOM_FUNC)
885 0 : CPLError(
886 : CE_Failure, CPLE_AppDefined,
887 : "Evaluate(): Unable to find definition for operator %s.",
888 : string_value);
889 : else
890 0 : CPLError(
891 : CE_Failure, CPLE_AppDefined,
892 : "Evaluate(): Unable to find definition for operator %d.",
893 0 : nOperation);
894 0 : poRetNode = nullptr;
895 : }
896 : else
897 81199 : poRetNode = poOp->pfnEvaluator(this, &(apoValues[0]), sContext);
898 : }
899 :
900 : /* -------------------------------------------------------------------- */
901 : /* Cleanup */
902 : /* -------------------------------------------------------------------- */
903 242875 : for (int i = 0; i < static_cast<int>(apoValues.size()); i++)
904 : {
905 161676 : if (anValueNeedsFree[i])
906 55785 : delete apoValues[i];
907 : }
908 :
909 : // cppcheck-suppress returnDanglingLifetime
910 81199 : return poRetNode;
911 : }
912 :
913 : /************************************************************************/
914 : /* ReplaceBetweenByGEAndLERecurse() */
915 : /************************************************************************/
916 :
917 6047 : void swq_expr_node::ReplaceBetweenByGEAndLERecurse()
918 : {
919 6047 : if (eNodeType != SNT_OPERATION)
920 3825 : return;
921 :
922 2222 : if (nOperation != SWQ_BETWEEN)
923 : {
924 6535 : for (int i = 0; i < nSubExprCount; i++)
925 4316 : papoSubExpr[i]->ReplaceBetweenByGEAndLERecurse();
926 2219 : return;
927 : }
928 :
929 3 : if (nSubExprCount != 3)
930 0 : return;
931 :
932 3 : swq_expr_node *poExpr0 = papoSubExpr[0];
933 3 : swq_expr_node *poExpr1 = papoSubExpr[1];
934 3 : swq_expr_node *poExpr2 = papoSubExpr[2];
935 :
936 3 : nSubExprCount = 2;
937 3 : nOperation = SWQ_AND;
938 3 : papoSubExpr[0] = new swq_expr_node(SWQ_GE);
939 3 : papoSubExpr[0]->PushSubExpression(poExpr0);
940 3 : papoSubExpr[0]->PushSubExpression(poExpr1);
941 3 : papoSubExpr[1] = new swq_expr_node(SWQ_LE);
942 3 : papoSubExpr[1]->PushSubExpression(poExpr0->Clone());
943 3 : papoSubExpr[1]->PushSubExpression(poExpr2);
944 : }
945 :
946 : /************************************************************************/
947 : /* PushNotOperationDownToStack() */
948 : /************************************************************************/
949 :
950 : // Do things like:
951 : // NOT(A AND B) ==> (NOT A) OR (NOT B)
952 : // NOT(A OR B) ==> (NOT A) AND (NOT B)
953 : // NOT(NOT A) ==> A
954 : // NOT(A == B) ==> A <> B
955 : // NOT(A != B) ==> A == B
956 : // NOT(A >= B) ==> A < B
957 : // NOT(A > B) ==> A <= B
958 : // NOT(A <= B) ==> A > B
959 : // NOT(A < B) ==> A >= B
960 846 : void swq_expr_node::PushNotOperationDownToStack()
961 : {
962 846 : if (eNodeType != SNT_OPERATION)
963 474 : return;
964 :
965 372 : if (nOperation == SWQ_NOT && papoSubExpr[0]->eNodeType == SNT_OPERATION)
966 : {
967 42 : if (papoSubExpr[0]->nOperation == SWQ_NOT)
968 : {
969 2 : auto poChild = papoSubExpr[0]->papoSubExpr[0];
970 2 : poChild->PushNotOperationDownToStack();
971 2 : papoSubExpr[0]->papoSubExpr[0] = nullptr;
972 2 : *this = std::move(*poChild);
973 2 : delete poChild;
974 2 : return;
975 : }
976 :
977 40 : else if (papoSubExpr[0]->nOperation == SWQ_AND)
978 : {
979 3 : for (int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
980 : {
981 2 : auto notOp = new swq_expr_node(SWQ_NOT);
982 2 : notOp->PushSubExpression(papoSubExpr[0]->papoSubExpr[i]);
983 2 : notOp->PushNotOperationDownToStack();
984 2 : papoSubExpr[0]->papoSubExpr[i] = notOp;
985 : }
986 1 : papoSubExpr[0]->nOperation = SWQ_OR;
987 1 : auto poChild = papoSubExpr[0];
988 1 : papoSubExpr[0] = nullptr;
989 1 : *this = std::move(*poChild);
990 1 : delete poChild;
991 1 : return;
992 : }
993 :
994 39 : else if (papoSubExpr[0]->nOperation == SWQ_OR)
995 : {
996 9 : for (int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
997 : {
998 6 : auto notOp = new swq_expr_node(SWQ_NOT);
999 6 : notOp->PushSubExpression(papoSubExpr[0]->papoSubExpr[i]);
1000 6 : notOp->PushNotOperationDownToStack();
1001 6 : papoSubExpr[0]->papoSubExpr[i] = notOp;
1002 : }
1003 3 : papoSubExpr[0]->nOperation = SWQ_AND;
1004 3 : auto poChild = papoSubExpr[0];
1005 3 : papoSubExpr[0] = nullptr;
1006 3 : *this = std::move(*poChild);
1007 3 : delete poChild;
1008 3 : return;
1009 : }
1010 :
1011 36 : else if (papoSubExpr[0]->nOperation == SWQ_EQ)
1012 : {
1013 3 : auto poChild = papoSubExpr[0];
1014 3 : papoSubExpr[0] = nullptr;
1015 3 : poChild->nOperation = SWQ_NE;
1016 3 : *this = std::move(*poChild);
1017 3 : delete poChild;
1018 3 : return;
1019 : }
1020 33 : else if (papoSubExpr[0]->nOperation == SWQ_NE)
1021 : {
1022 1 : auto poChild = papoSubExpr[0];
1023 1 : papoSubExpr[0] = nullptr;
1024 1 : poChild->nOperation = SWQ_EQ;
1025 1 : *this = std::move(*poChild);
1026 1 : delete poChild;
1027 1 : return;
1028 : }
1029 32 : else if (papoSubExpr[0]->nOperation == SWQ_GT)
1030 : {
1031 1 : auto poChild = papoSubExpr[0];
1032 1 : papoSubExpr[0] = nullptr;
1033 1 : poChild->nOperation = SWQ_LE;
1034 1 : *this = std::move(*poChild);
1035 1 : delete poChild;
1036 1 : return;
1037 : }
1038 31 : else if (papoSubExpr[0]->nOperation == SWQ_GE)
1039 : {
1040 1 : auto poChild = papoSubExpr[0];
1041 1 : papoSubExpr[0] = nullptr;
1042 1 : poChild->nOperation = SWQ_LT;
1043 1 : *this = std::move(*poChild);
1044 1 : delete poChild;
1045 1 : return;
1046 : }
1047 30 : else if (papoSubExpr[0]->nOperation == SWQ_LT)
1048 : {
1049 1 : auto poChild = papoSubExpr[0];
1050 1 : papoSubExpr[0] = nullptr;
1051 1 : poChild->nOperation = SWQ_GE;
1052 1 : *this = std::move(*poChild);
1053 1 : delete poChild;
1054 1 : return;
1055 : }
1056 29 : else if (papoSubExpr[0]->nOperation == SWQ_LE)
1057 : {
1058 1 : auto poChild = papoSubExpr[0];
1059 1 : papoSubExpr[0] = nullptr;
1060 1 : poChild->nOperation = SWQ_GT;
1061 1 : *this = std::move(*poChild);
1062 1 : delete poChild;
1063 1 : return;
1064 : }
1065 : }
1066 :
1067 987 : for (int i = 0; i < nSubExprCount; i++)
1068 629 : papoSubExpr[i]->PushNotOperationDownToStack();
1069 : }
1070 :
1071 : #endif // #ifndef DOXYGEN_SKIP
|