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 <cinttypes>
23 : #include <cstdio>
24 : #include <cstring>
25 : #include <string>
26 : #include <queue>
27 : #include <vector>
28 :
29 : #include "cpl_conv.h"
30 : #include "cpl_error.h"
31 : #include "cpl_multiproc.h"
32 : #include "cpl_string.h"
33 : #include "ogr_geometry.h"
34 :
35 : /************************************************************************/
36 : /* swq_expr_node() */
37 : /************************************************************************/
38 :
39 : swq_expr_node::swq_expr_node() = default;
40 :
41 : /************************************************************************/
42 : /* swq_expr_node(int) */
43 : /************************************************************************/
44 :
45 116375 : swq_expr_node::swq_expr_node(int nValueIn) : int_value(nValueIn)
46 : {
47 116375 : }
48 :
49 : /************************************************************************/
50 : /* swq_expr_node(GIntBig) */
51 : /************************************************************************/
52 :
53 4932 : swq_expr_node::swq_expr_node(GIntBig nValueIn)
54 4932 : : field_type(SWQ_INTEGER64), int_value(nValueIn)
55 : {
56 4932 : }
57 :
58 : /************************************************************************/
59 : /* swq_expr_node(double) */
60 : /************************************************************************/
61 :
62 6752 : swq_expr_node::swq_expr_node(double dfValueIn)
63 6752 : : field_type(SWQ_FLOAT), float_value(dfValueIn)
64 : {
65 6752 : }
66 :
67 : /************************************************************************/
68 : /* swq_expr_node(const char*) */
69 : /************************************************************************/
70 :
71 29975 : swq_expr_node::swq_expr_node(const char *pszValueIn)
72 29975 : : field_type(SWQ_STRING), is_null(pszValueIn == nullptr),
73 29975 : string_value(CPLStrdup(pszValueIn ? pszValueIn : ""))
74 : {
75 29975 : }
76 :
77 : /************************************************************************/
78 : /* swq_expr_node(OGRGeometry *) */
79 : /************************************************************************/
80 :
81 35 : swq_expr_node::swq_expr_node(OGRGeometry *poGeomIn)
82 35 : : field_type(SWQ_GEOMETRY), is_null(poGeomIn == nullptr),
83 35 : geometry_value(poGeomIn ? poGeomIn->clone() : nullptr)
84 : {
85 35 : }
86 :
87 : /************************************************************************/
88 : /* swq_expr_node(swq_op) */
89 : /************************************************************************/
90 :
91 26766 : swq_expr_node::swq_expr_node(swq_op eOp)
92 26766 : : eNodeType(SNT_OPERATION), nOperation(eOp)
93 : {
94 26766 : }
95 :
96 : /************************************************************************/
97 : /* ~swq_expr_node() */
98 : /************************************************************************/
99 :
100 377836 : swq_expr_node::~swq_expr_node()
101 :
102 : {
103 188918 : reset();
104 188918 : }
105 :
106 : /************************************************************************/
107 : /* reset() */
108 : /************************************************************************/
109 :
110 191592 : void swq_expr_node::reset()
111 : {
112 191592 : CPLFree(table_name);
113 191592 : table_name = nullptr;
114 191592 : CPLFree(string_value);
115 191592 : string_value = nullptr;
116 :
117 235165 : for (int i = 0; i < nSubExprCount; i++)
118 43573 : delete papoSubExpr[i];
119 191592 : CPLFree(papoSubExpr);
120 191592 : nSubExprCount = 0;
121 191592 : papoSubExpr = nullptr;
122 191592 : delete geometry_value;
123 191592 : geometry_value = nullptr;
124 191592 : }
125 :
126 : /************************************************************************/
127 : /* operator==() */
128 : /************************************************************************/
129 :
130 1984 : bool swq_expr_node::operator==(const swq_expr_node &other) const
131 : {
132 1984 : if (eNodeType != other.eNodeType || field_type != other.field_type ||
133 1168 : nOperation != other.nOperation || field_index != other.field_index ||
134 1140 : table_index != other.table_index ||
135 1128 : nSubExprCount != other.nSubExprCount || is_null != other.is_null ||
136 1104 : int_value != other.int_value || float_value != other.float_value ||
137 1080 : bHidden != other.bHidden)
138 : {
139 904 : return false;
140 : }
141 1168 : for (int i = 0; i < nSubExprCount; ++i)
142 : {
143 92 : if (!(*(papoSubExpr[i]) == *(other.papoSubExpr[i])))
144 : {
145 4 : return false;
146 : }
147 : }
148 1076 : if (table_name && !other.table_name)
149 : {
150 4 : return false;
151 : }
152 1072 : if (!table_name && other.table_name)
153 : {
154 4 : return false;
155 : }
156 1068 : if (table_name && other.table_name &&
157 92 : strcmp(table_name, other.table_name) != 0)
158 : {
159 4 : return false;
160 : }
161 1064 : if (string_value && !other.string_value)
162 : {
163 0 : return false;
164 : }
165 1064 : if (!string_value && other.string_value)
166 : {
167 0 : return false;
168 : }
169 1064 : if (string_value && other.string_value &&
170 136 : strcmp(string_value, other.string_value) != 0)
171 : {
172 4 : return false;
173 : }
174 1060 : if (geometry_value && !other.geometry_value)
175 : {
176 0 : return false;
177 : }
178 1060 : if (!geometry_value && other.geometry_value)
179 : {
180 0 : return false;
181 : }
182 1152 : if (geometry_value && other.geometry_value &&
183 92 : !geometry_value->Equals(other.geometry_value))
184 : {
185 4 : return false;
186 : }
187 1056 : return true;
188 : }
189 :
190 : /************************************************************************/
191 : /* swq_expr_node(const swq_expr_node& other) */
192 : /************************************************************************/
193 :
194 1736 : swq_expr_node::swq_expr_node(const swq_expr_node &other)
195 : {
196 1736 : *this = other;
197 1736 : }
198 :
199 : /************************************************************************/
200 : /* operator= (const swq_expr_node& other) */
201 : /************************************************************************/
202 :
203 2198 : swq_expr_node &swq_expr_node::operator=(const swq_expr_node &other)
204 : {
205 2198 : if (this != &other)
206 : {
207 2198 : reset();
208 2198 : eNodeType = other.eNodeType;
209 2198 : field_type = other.field_type;
210 2198 : nOperation = other.nOperation;
211 2198 : field_index = other.field_index;
212 2198 : table_index = other.table_index;
213 2198 : if (other.table_name)
214 172 : table_name = CPLStrdup(other.table_name);
215 2407 : for (int i = 0; i < other.nSubExprCount; ++i)
216 209 : PushSubExpression(new swq_expr_node(*(other.papoSubExpr[i])));
217 2198 : is_null = other.is_null;
218 2198 : int_value = other.int_value;
219 2198 : float_value = other.float_value;
220 2198 : if (other.geometry_value)
221 174 : geometry_value = other.geometry_value->clone();
222 2198 : if (other.string_value)
223 332 : string_value = CPLStrdup(other.string_value);
224 2198 : bHidden = other.bHidden;
225 2198 : nDepth = other.nDepth;
226 : }
227 2198 : return *this;
228 : }
229 :
230 : /************************************************************************/
231 : /* swq_expr_node(swq_expr_node&& other) */
232 : /************************************************************************/
233 :
234 0 : swq_expr_node::swq_expr_node(swq_expr_node &&other)
235 : {
236 0 : *this = std::move(other);
237 0 : }
238 :
239 : /************************************************************************/
240 : /* operator= (swq_expr_node&& other) */
241 : /************************************************************************/
242 :
243 476 : swq_expr_node &swq_expr_node::operator=(swq_expr_node &&other)
244 : {
245 476 : if (this != &other)
246 : {
247 476 : reset();
248 476 : eNodeType = other.eNodeType;
249 476 : field_type = other.field_type;
250 476 : nOperation = other.nOperation;
251 476 : field_index = other.field_index;
252 476 : table_index = other.table_index;
253 476 : std::swap(table_name, other.table_name);
254 476 : std::swap(nSubExprCount, other.nSubExprCount);
255 476 : std::swap(papoSubExpr, other.papoSubExpr);
256 476 : is_null = other.is_null;
257 476 : int_value = other.int_value;
258 476 : float_value = other.float_value;
259 476 : std::swap(geometry_value, other.geometry_value);
260 476 : std::swap(string_value, other.string_value);
261 476 : bHidden = other.bHidden;
262 476 : nDepth = other.nDepth;
263 : }
264 476 : return *this;
265 : }
266 :
267 : /************************************************************************/
268 : /* MarkAsTimestamp() */
269 : /************************************************************************/
270 :
271 312 : void swq_expr_node::MarkAsTimestamp()
272 :
273 : {
274 312 : CPLAssert(eNodeType == SNT_CONSTANT);
275 312 : CPLAssert(field_type == SWQ_STRING);
276 312 : field_type = SWQ_TIMESTAMP;
277 312 : }
278 :
279 : /************************************************************************/
280 : /* PushSubExpression() */
281 : /************************************************************************/
282 :
283 48825 : void swq_expr_node::PushSubExpression(swq_expr_node *child)
284 :
285 : {
286 48825 : nSubExprCount++;
287 48825 : papoSubExpr = static_cast<swq_expr_node **>(
288 48825 : CPLRealloc(papoSubExpr, sizeof(void *) * nSubExprCount));
289 :
290 48825 : papoSubExpr[nSubExprCount - 1] = child;
291 :
292 48825 : nDepth = std::max(nDepth, 1 + child->nDepth);
293 48825 : }
294 :
295 : /************************************************************************/
296 : /* ReverseSubExpressions() */
297 : /************************************************************************/
298 :
299 591 : void swq_expr_node::ReverseSubExpressions()
300 :
301 : {
302 1011 : for (int i = 0; i < nSubExprCount / 2; i++)
303 : {
304 420 : std::swap(papoSubExpr[i], papoSubExpr[nSubExprCount - i - 1]);
305 : }
306 591 : }
307 :
308 : /************************************************************************/
309 : /* Check() */
310 : /* */
311 : /* Check argument types, etc. */
312 : /************************************************************************/
313 :
314 : swq_field_type
315 43972 : swq_expr_node::Check(swq_field_list *poFieldList,
316 : int bAllowFieldsInSecondaryTables,
317 : int bAllowMismatchTypeOnFieldComparison,
318 : swq_custom_func_registrar *poCustomFuncRegistrar)
319 :
320 : {
321 : /* -------------------------------------------------------------------- */
322 : /* Otherwise we take constants literally. */
323 : /* -------------------------------------------------------------------- */
324 43972 : if (eNodeType == SNT_CONSTANT)
325 16616 : 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 27356 : if (eNodeType == SNT_COLUMN && field_index == -1)
332 : {
333 8449 : field_index = swq_identify_field(table_name, string_value, poFieldList,
334 : &field_type, &table_index);
335 :
336 8449 : if (field_index < 0)
337 : {
338 5 : 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 2 : CPLError(CE_Failure, CPLE_AppDefined,
344 : "\"%s\" not recognised as an available field.",
345 : string_value);
346 :
347 5 : return SWQ_ERROR;
348 : }
349 :
350 8444 : 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 27350 : if (eNodeType == SNT_COLUMN)
361 8443 : 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 19019 : ? poCustomFuncRegistrar->GetOperator(string_value)
369 18795 : : swq_op_registrar::GetOperator(nOperation);
370 :
371 18907 : 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 56411 : for (int i = 0; i < nSubExprCount; i++)
388 : {
389 37526 : if (papoSubExpr[i]->Check(poFieldList, bAllowFieldsInSecondaryTables,
390 : bAllowMismatchTypeOnFieldComparison,
391 37526 : poCustomFuncRegistrar) == SWQ_ERROR)
392 22 : return SWQ_ERROR;
393 : }
394 :
395 : /* -------------------------------------------------------------------- */
396 : /* Check this node. */
397 : /* -------------------------------------------------------------------- */
398 18885 : field_type = poOp->pfnChecker(this, bAllowMismatchTypeOnFieldComparison);
399 :
400 18885 : return field_type;
401 : }
402 :
403 : /************************************************************************/
404 : /* Dump() */
405 : /************************************************************************/
406 :
407 0 : void swq_expr_node::Dump(FILE *fp, int depth)
408 :
409 : {
410 0 : char spaces[60] = {};
411 :
412 : {
413 0 : int i = 0; // Used after for.
414 0 : for (; i < depth * 2 && i < static_cast<int>(sizeof(spaces)) - 1; i++)
415 0 : spaces[i] = ' ';
416 0 : spaces[i] = '\0';
417 : }
418 :
419 0 : if (eNodeType == SNT_COLUMN)
420 : {
421 0 : fprintf(fp, "%s Field %d\n", spaces, field_index);
422 0 : return;
423 : }
424 :
425 0 : if (eNodeType == SNT_CONSTANT)
426 : {
427 0 : if (field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 ||
428 0 : field_type == SWQ_BOOLEAN)
429 0 : fprintf(fp, "%s %" PRId64 "\n", spaces, int_value);
430 0 : else if (field_type == SWQ_FLOAT)
431 0 : fprintf(fp, "%s %.15g\n", spaces, float_value);
432 0 : else if (field_type == SWQ_GEOMETRY)
433 : {
434 0 : if (geometry_value == nullptr)
435 0 : fprintf(fp, "%s (null)\n", spaces);
436 : else
437 : {
438 0 : char *pszWKT = nullptr;
439 0 : geometry_value->exportToWkt(&pszWKT);
440 0 : fprintf(fp, "%s %s\n", spaces, pszWKT);
441 0 : CPLFree(pszWKT);
442 : }
443 : }
444 : else
445 0 : fprintf(fp, "%s %s\n", spaces, string_value);
446 0 : return;
447 : }
448 :
449 0 : CPLAssert(eNodeType == SNT_OPERATION);
450 :
451 0 : const swq_operation *op_def = swq_op_registrar::GetOperator(nOperation);
452 0 : if (op_def)
453 0 : fprintf(fp, "%s%s\n", spaces, op_def->pszName);
454 : else
455 0 : fprintf(fp, "%s%s\n", spaces, string_value);
456 :
457 0 : for (int i = 0; i < nSubExprCount; i++)
458 0 : papoSubExpr[i]->Dump(fp, depth + 1);
459 : }
460 :
461 : /************************************************************************/
462 : /* QuoteIfNecessary() */
463 : /* */
464 : /* Add quoting if necessary to unparse a string. */
465 : /************************************************************************/
466 :
467 417 : CPLString swq_expr_node::QuoteIfNecessary(const CPLString &osExpr, char chQuote)
468 :
469 : {
470 417 : if (osExpr[0] == '_')
471 0 : return Quote(osExpr, chQuote);
472 417 : if (osExpr == "*")
473 3 : return osExpr;
474 :
475 2743 : for (int i = 0; i < static_cast<int>(osExpr.size()); i++)
476 : {
477 2337 : char ch = osExpr[i];
478 2337 : if ((!(isalnum(static_cast<unsigned char>(ch)) || ch == '_')) ||
479 : ch == '.')
480 : {
481 8 : return Quote(osExpr, chQuote);
482 : }
483 : }
484 :
485 406 : if (swq_is_reserved_keyword(osExpr))
486 : {
487 1 : return Quote(osExpr, chQuote);
488 : }
489 :
490 405 : return osExpr;
491 : }
492 :
493 : /************************************************************************/
494 : /* Quote() */
495 : /* */
496 : /* Add quoting necessary to unparse a string. */
497 : /************************************************************************/
498 :
499 125 : CPLString swq_expr_node::Quote(const CPLString &osTarget, char chQuote)
500 :
501 : {
502 125 : CPLString osNew;
503 :
504 125 : osNew += chQuote;
505 :
506 1243 : for (int i = 0; i < static_cast<int>(osTarget.size()); i++)
507 : {
508 1118 : if (osTarget[i] == chQuote)
509 : {
510 0 : osNew += chQuote;
511 0 : osNew += chQuote;
512 : }
513 : else
514 1118 : osNew += osTarget[i];
515 : }
516 125 : osNew += chQuote;
517 :
518 125 : return osNew;
519 : }
520 :
521 : /************************************************************************/
522 : /* Unparse() */
523 : /************************************************************************/
524 :
525 3201 : char *swq_expr_node::Unparse(swq_field_list *field_list, char chColumnQuote)
526 :
527 : {
528 6402 : CPLString osExpr;
529 :
530 : /* -------------------------------------------------------------------- */
531 : /* Handle constants. */
532 : /* -------------------------------------------------------------------- */
533 3201 : if (eNodeType == SNT_CONSTANT)
534 : {
535 1668 : if (is_null)
536 37 : return CPLStrdup("NULL");
537 :
538 1631 : if (field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 ||
539 150 : field_type == SWQ_BOOLEAN)
540 1481 : osExpr.Printf("%" PRId64, int_value);
541 150 : else if (field_type == SWQ_FLOAT)
542 : {
543 34 : osExpr.Printf("%.15g", float_value);
544 : // Make sure this is interpreted as a floating point value
545 : // and not as an integer later.
546 34 : if (strchr(osExpr, '.') == nullptr &&
547 66 : strchr(osExpr, 'e') == nullptr &&
548 32 : strchr(osExpr, 'E') == nullptr)
549 32 : osExpr += '.';
550 : }
551 : else
552 : {
553 116 : osExpr = Quote(string_value);
554 : }
555 :
556 1631 : return CPLStrdup(osExpr);
557 : }
558 :
559 : /* -------------------------------------------------------------------- */
560 : /* Handle columns. */
561 : /* -------------------------------------------------------------------- */
562 1533 : if (eNodeType == SNT_COLUMN)
563 : {
564 389 : if (field_list == nullptr)
565 : {
566 9 : if (table_name)
567 : osExpr.Printf(
568 : "%s.%s",
569 4 : QuoteIfNecessary(table_name, chColumnQuote).c_str(),
570 6 : QuoteIfNecessary(string_value, chColumnQuote).c_str());
571 : else
572 : osExpr.Printf(
573 : "%s",
574 7 : QuoteIfNecessary(string_value, chColumnQuote).c_str());
575 : }
576 380 : else if (field_index != -1 && table_index < field_list->table_count &&
577 380 : table_index > 0)
578 : {
579 : // We deliberately browse through the list starting from the end
580 : // This is for the case where the FID column exists both as
581 : // FID and then real_fid_name. We want real_fid_name to be used
582 26 : for (int i = field_list->count - 1; i >= 0; i--)
583 : {
584 26 : if (field_list->table_ids[i] == table_index &&
585 6 : field_list->ids[i] == field_index)
586 : {
587 : osExpr.Printf(
588 : "%s.%s",
589 8 : QuoteIfNecessary(
590 4 : field_list->table_defs[table_index].table_name,
591 : chColumnQuote)
592 : .c_str(),
593 8 : QuoteIfNecessary(field_list->names[i], chColumnQuote)
594 8 : .c_str());
595 4 : break;
596 : }
597 4 : }
598 : }
599 376 : else if (field_index != -1)
600 : {
601 : // We deliberately browse through the list starting from the end
602 : // This is for the case where the FID column exists both as
603 : // FID and then real_fid_name. We want real_fid_name to be used
604 2736 : for (int i = field_list->count - 1; i >= 0; i--)
605 : {
606 2736 : if (field_list->table_ids[i] == table_index &&
607 2718 : field_list->ids[i] == field_index)
608 : {
609 752 : osExpr.Printf("%s", QuoteIfNecessary(field_list->names[i],
610 : chColumnQuote)
611 376 : .c_str());
612 376 : break;
613 : }
614 : }
615 : }
616 :
617 389 : if (osExpr.empty())
618 : {
619 0 : return CPLStrdup(CPLSPrintf("%c%c", chColumnQuote, chColumnQuote));
620 : }
621 :
622 : // The string is just alphanum and not a reserved SQL keyword,
623 : // no needs to quote and escape.
624 389 : return CPLStrdup(osExpr.c_str());
625 : }
626 :
627 : /* -------------------------------------------------------------------- */
628 : /* Operation - start by unparsing all the subexpressions. */
629 : /* -------------------------------------------------------------------- */
630 2288 : std::vector<char *> apszSubExpr;
631 1144 : apszSubExpr.reserve(nSubExprCount);
632 3352 : for (int i = 0; i < nSubExprCount; i++)
633 2208 : apszSubExpr.push_back(
634 2208 : papoSubExpr[i]->Unparse(field_list, chColumnQuote));
635 :
636 1144 : osExpr = UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
637 :
638 : /* -------------------------------------------------------------------- */
639 : /* cleanup subexpressions. */
640 : /* -------------------------------------------------------------------- */
641 3352 : for (int i = 0; i < nSubExprCount; i++)
642 2208 : CPLFree(apszSubExpr[i]);
643 :
644 1144 : return CPLStrdup(osExpr.c_str());
645 : }
646 :
647 : /************************************************************************/
648 : /* UnparseOperationFromUnparsedSubExpr() */
649 : /************************************************************************/
650 :
651 1263 : CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char **apszSubExpr)
652 : {
653 1263 : CPLString osExpr;
654 :
655 : /* -------------------------------------------------------------------- */
656 : /* Put things together in a fashion depending on the operator. */
657 : /* -------------------------------------------------------------------- */
658 1263 : const swq_operation *poOp = swq_op_registrar::GetOperator(nOperation);
659 :
660 1263 : if (poOp == nullptr && nOperation != SWQ_CUSTOM_FUNC)
661 : {
662 0 : CPLAssert(false);
663 : return osExpr;
664 : }
665 :
666 7099 : const auto AddSubExpr = [this, apszSubExpr, &osExpr](int idx)
667 : {
668 2408 : if (papoSubExpr[idx]->eNodeType == SNT_COLUMN ||
669 1845 : papoSubExpr[idx]->eNodeType == SNT_CONSTANT)
670 : {
671 2189 : osExpr += apszSubExpr[idx];
672 : }
673 : else
674 : {
675 219 : osExpr += '(';
676 219 : osExpr += apszSubExpr[idx];
677 219 : osExpr += ')';
678 : }
679 3671 : };
680 :
681 1263 : switch (nOperation)
682 : {
683 : // Binary infix operators.
684 1049 : case SWQ_OR:
685 : case SWQ_AND:
686 : case SWQ_EQ:
687 : case SWQ_NE:
688 : case SWQ_GT:
689 : case SWQ_LT:
690 : case SWQ_GE:
691 : case SWQ_LE:
692 : case SWQ_LIKE:
693 : case SWQ_ILIKE:
694 : case SWQ_ADD:
695 : case SWQ_SUBTRACT:
696 : case SWQ_MULTIPLY:
697 : case SWQ_DIVIDE:
698 : case SWQ_MODULUS:
699 1049 : CPLAssert(nSubExprCount >= 2);
700 1049 : AddSubExpr(0);
701 1049 : osExpr += " ";
702 1049 : osExpr += poOp->pszName;
703 1049 : osExpr += " ";
704 1049 : AddSubExpr(1);
705 1049 : if ((nOperation == SWQ_LIKE || nOperation == SWQ_ILIKE) &&
706 11 : nSubExprCount == 3)
707 : {
708 1 : osExpr += " ESCAPE ";
709 1 : AddSubExpr(2);
710 : }
711 1049 : break;
712 :
713 81 : case SWQ_NOT:
714 81 : CPLAssert(nSubExprCount == 1);
715 81 : osExpr = "NOT ";
716 81 : AddSubExpr(0);
717 81 : break;
718 :
719 36 : case SWQ_ISNULL:
720 36 : CPLAssert(nSubExprCount == 1);
721 36 : AddSubExpr(0);
722 36 : osExpr += " IS NULL";
723 36 : break;
724 :
725 42 : case SWQ_IN:
726 42 : AddSubExpr(0);
727 42 : osExpr += " IN(";
728 112 : for (int i = 1; i < nSubExprCount; i++)
729 : {
730 70 : if (i > 1)
731 28 : osExpr += ",";
732 70 : AddSubExpr(i);
733 : }
734 42 : osExpr += ")";
735 42 : break;
736 :
737 2 : case SWQ_BETWEEN:
738 2 : CPLAssert(nSubExprCount == 3);
739 2 : AddSubExpr(0);
740 2 : osExpr += ' ';
741 2 : osExpr += poOp->pszName;
742 2 : osExpr += ' ';
743 2 : AddSubExpr(1);
744 2 : osExpr += " AND ";
745 2 : AddSubExpr(2);
746 2 : break;
747 :
748 36 : case SWQ_CAST:
749 36 : osExpr = "CAST(";
750 112 : for (int i = 0; i < nSubExprCount; i++)
751 : {
752 76 : if (i == 1)
753 36 : osExpr += " AS ";
754 40 : else if (i > 2)
755 1 : osExpr += ", ";
756 :
757 76 : const int nLen = static_cast<int>(strlen(apszSubExpr[i]));
758 76 : if ((i == 1 && (apszSubExpr[i][0] == '\'' && nLen > 2 &&
759 76 : apszSubExpr[i][nLen - 1] == '\'')) ||
760 3 : (i == 2 && EQUAL(apszSubExpr[1], "'GEOMETRY")))
761 : {
762 38 : apszSubExpr[i][nLen - 1] = '\0';
763 38 : osExpr += apszSubExpr[i] + 1;
764 : }
765 : else
766 38 : AddSubExpr(i);
767 :
768 76 : if (i == 1 && nSubExprCount > 2)
769 3 : osExpr += "(";
770 73 : else if (i > 1 && i == nSubExprCount - 1)
771 3 : osExpr += ")";
772 : }
773 36 : osExpr += ")";
774 36 : break;
775 :
776 17 : default: // function style.
777 17 : if (nOperation != SWQ_CUSTOM_FUNC)
778 1 : osExpr.Printf("%s(", poOp->pszName);
779 : else
780 16 : osExpr.Printf("%s(", string_value);
781 53 : for (int i = 0; i < nSubExprCount; i++)
782 : {
783 36 : if (i > 0)
784 19 : osExpr += ",";
785 36 : AddSubExpr(i);
786 : }
787 17 : osExpr += ")";
788 17 : break;
789 : }
790 :
791 2526 : return osExpr;
792 : }
793 :
794 : /************************************************************************/
795 : /* Clone() */
796 : /************************************************************************/
797 :
798 82 : swq_expr_node *swq_expr_node::Clone()
799 : {
800 82 : return new swq_expr_node(*this);
801 : }
802 :
803 : /************************************************************************/
804 : /* Evaluate() */
805 : /************************************************************************/
806 :
807 65729 : swq_expr_node *swq_expr_node::Evaluate(swq_field_fetcher pfnFetcher,
808 : void *pRecord,
809 : const swq_evaluation_context &sContext)
810 :
811 : {
812 65729 : return Evaluate(pfnFetcher, pRecord, sContext, 0);
813 : }
814 :
815 121341 : swq_expr_node *swq_expr_node::Evaluate(swq_field_fetcher pfnFetcher,
816 : void *pRecord,
817 : const swq_evaluation_context &sContext,
818 : int nRecLevel)
819 :
820 : {
821 121341 : swq_expr_node *poRetNode = nullptr;
822 121341 : if (nRecLevel == 32)
823 : {
824 0 : CPLError(CE_Failure, CPLE_AppDefined,
825 : "Too many recursion levels in expression");
826 0 : return nullptr;
827 : }
828 :
829 : /* -------------------------------------------------------------------- */
830 : /* Duplicate ourselves if we are already a constant. */
831 : /* -------------------------------------------------------------------- */
832 121341 : if (eNodeType == SNT_CONSTANT)
833 : {
834 71 : return Clone();
835 : }
836 :
837 : /* -------------------------------------------------------------------- */
838 : /* If this is a field value from a record, fetch and return it. */
839 : /* -------------------------------------------------------------------- */
840 121270 : if (eNodeType == SNT_COLUMN)
841 : {
842 40444 : return pfnFetcher(this, pRecord);
843 : }
844 :
845 : /* -------------------------------------------------------------------- */
846 : /* This is an operation, collect the arguments keeping track of */
847 : /* which we will need to free. */
848 : /* -------------------------------------------------------------------- */
849 161652 : std::vector<swq_expr_node *> apoValues;
850 80826 : std::vector<int> anValueNeedsFree;
851 80826 : bool bError = false;
852 80826 : apoValues.reserve(nSubExprCount);
853 241756 : for (int i = 0; i < nSubExprCount && !bError; i++)
854 : {
855 160930 : if (papoSubExpr[i]->eNodeType == SNT_CONSTANT)
856 : {
857 : // avoid duplication.
858 105318 : apoValues.push_back(papoSubExpr[i]);
859 105318 : anValueNeedsFree.push_back(FALSE);
860 : }
861 : else
862 : {
863 55612 : swq_expr_node *poSubExprVal = papoSubExpr[i]->Evaluate(
864 55612 : pfnFetcher, pRecord, sContext, nRecLevel + 1);
865 55612 : if (poSubExprVal == nullptr)
866 0 : bError = true;
867 : else
868 : {
869 55612 : apoValues.push_back(poSubExprVal);
870 55612 : anValueNeedsFree.push_back(TRUE);
871 : }
872 : }
873 : }
874 :
875 : /* -------------------------------------------------------------------- */
876 : /* Fetch the operator definition and function. */
877 : /* -------------------------------------------------------------------- */
878 80826 : if (!bError)
879 : {
880 80826 : const swq_operation *poOp = swq_op_registrar::GetOperator(nOperation);
881 80826 : if (poOp == nullptr)
882 : {
883 0 : if (nOperation == SWQ_CUSTOM_FUNC)
884 0 : CPLError(
885 : CE_Failure, CPLE_AppDefined,
886 : "Evaluate(): Unable to find definition for operator %s.",
887 : string_value);
888 : else
889 0 : CPLError(
890 : CE_Failure, CPLE_AppDefined,
891 : "Evaluate(): Unable to find definition for operator %d.",
892 0 : nOperation);
893 0 : poRetNode = nullptr;
894 : }
895 : else
896 80826 : poRetNode = poOp->pfnEvaluator(this, &(apoValues[0]), sContext);
897 : }
898 :
899 : /* -------------------------------------------------------------------- */
900 : /* Cleanup */
901 : /* -------------------------------------------------------------------- */
902 241756 : for (int i = 0; i < static_cast<int>(apoValues.size()); i++)
903 : {
904 160930 : if (anValueNeedsFree[i])
905 55612 : delete apoValues[i];
906 : }
907 :
908 : // cppcheck-suppress returnDanglingLifetime
909 80826 : return poRetNode;
910 : }
911 :
912 : /************************************************************************/
913 : /* ReplaceBetweenByGEAndLERecurse() */
914 : /************************************************************************/
915 :
916 6090 : void swq_expr_node::ReplaceBetweenByGEAndLERecurse()
917 : {
918 6090 : if (eNodeType != SNT_OPERATION)
919 3853 : return;
920 :
921 2237 : if (nOperation != SWQ_BETWEEN)
922 : {
923 6582 : for (int i = 0; i < nSubExprCount; i++)
924 4348 : papoSubExpr[i]->ReplaceBetweenByGEAndLERecurse();
925 2234 : return;
926 : }
927 :
928 3 : if (nSubExprCount != 3)
929 0 : return;
930 :
931 3 : swq_expr_node *poExpr0 = papoSubExpr[0];
932 3 : swq_expr_node *poExpr1 = papoSubExpr[1];
933 3 : swq_expr_node *poExpr2 = papoSubExpr[2];
934 :
935 3 : nSubExprCount = 2;
936 3 : nOperation = SWQ_AND;
937 3 : papoSubExpr[0] = new swq_expr_node(SWQ_GE);
938 3 : papoSubExpr[0]->PushSubExpression(poExpr0);
939 3 : papoSubExpr[0]->PushSubExpression(poExpr1);
940 3 : papoSubExpr[1] = new swq_expr_node(SWQ_LE);
941 3 : papoSubExpr[1]->PushSubExpression(poExpr0->Clone());
942 3 : papoSubExpr[1]->PushSubExpression(poExpr2);
943 : }
944 :
945 : /************************************************************************/
946 : /* ReplaceInByOrRecurse() */
947 : /************************************************************************/
948 :
949 310 : void swq_expr_node::ReplaceInByOrRecurse()
950 : {
951 310 : if (eNodeType != SNT_OPERATION)
952 180 : return;
953 :
954 130 : if (nOperation != SWQ_IN)
955 : {
956 404 : for (int i = 0; i < nSubExprCount; i++)
957 276 : papoSubExpr[i]->ReplaceInByOrRecurse();
958 128 : return;
959 : }
960 :
961 2 : nOperation = SWQ_OR;
962 2 : swq_expr_node *poExprLeft = papoSubExpr[0]->Clone();
963 6 : for (int i = 1; i < nSubExprCount; ++i)
964 : {
965 4 : papoSubExpr[i - 1] = new swq_expr_node(SWQ_EQ);
966 4 : papoSubExpr[i - 1]->PushSubExpression(poExprLeft->Clone());
967 4 : papoSubExpr[i - 1]->PushSubExpression(papoSubExpr[i]);
968 : }
969 2 : delete poExprLeft;
970 2 : --nSubExprCount;
971 :
972 2 : RebalanceAndOr();
973 : }
974 :
975 : /************************************************************************/
976 : /* RebalanceAndOr() */
977 : /************************************************************************/
978 :
979 10921 : void swq_expr_node::RebalanceAndOr()
980 : {
981 21842 : std::queue<swq_expr_node *> nodes;
982 10921 : nodes.push(this);
983 44800 : while (!nodes.empty())
984 : {
985 33879 : swq_expr_node *node = nodes.front();
986 33879 : nodes.pop();
987 33879 : if (node->eNodeType == SNT_OPERATION)
988 : {
989 11793 : const swq_op eOp = node->nOperation;
990 11793 : if ((eOp == SWQ_OR || eOp == SWQ_AND) && node->nSubExprCount > 2)
991 : {
992 320 : std::vector<swq_expr_node *> exprs;
993 4817 : for (int i = 0; i < node->nSubExprCount; i++)
994 : {
995 4657 : node->papoSubExpr[i]->RebalanceAndOr();
996 4657 : exprs.push_back(node->papoSubExpr[i]);
997 : }
998 160 : node->nSubExprCount = 0;
999 160 : CPLFree(node->papoSubExpr);
1000 160 : node->papoSubExpr = nullptr;
1001 :
1002 376 : while (exprs.size() > 2)
1003 : {
1004 432 : std::vector<swq_expr_node *> new_exprs;
1005 4716 : for (size_t i = 0; i < exprs.size(); i++)
1006 : {
1007 4500 : if (i + 1 < exprs.size())
1008 : {
1009 4337 : auto cur_expr = new swq_expr_node(eOp);
1010 4337 : cur_expr->field_type = SWQ_BOOLEAN;
1011 4337 : cur_expr->PushSubExpression(exprs[i]);
1012 4337 : cur_expr->PushSubExpression(exprs[i + 1]);
1013 4337 : i++;
1014 4337 : new_exprs.push_back(cur_expr);
1015 : }
1016 : else
1017 : {
1018 163 : new_exprs.push_back(exprs[i]);
1019 : }
1020 : }
1021 216 : exprs = std::move(new_exprs);
1022 : }
1023 160 : CPLAssert(exprs.size() == 2);
1024 160 : node->PushSubExpression(exprs[0]);
1025 320 : node->PushSubExpression(exprs[1]);
1026 : }
1027 : else
1028 : {
1029 34591 : for (int i = 0; i < node->nSubExprCount; i++)
1030 : {
1031 22958 : nodes.push(node->papoSubExpr[i]);
1032 : }
1033 : }
1034 : }
1035 : }
1036 10921 : }
1037 :
1038 : /************************************************************************/
1039 : /* PushNotOperationDownToStack() */
1040 : /************************************************************************/
1041 :
1042 : // Do things like:
1043 : // NOT(A AND B) ==> (NOT A) OR (NOT B)
1044 : // NOT(A OR B) ==> (NOT A) AND (NOT B)
1045 : // NOT(NOT A) ==> A
1046 : // NOT(A == B) ==> A <> B
1047 : // NOT(A != B) ==> A == B
1048 : // NOT(A >= B) ==> A < B
1049 : // NOT(A > B) ==> A <= B
1050 : // NOT(A <= B) ==> A > B
1051 : // NOT(A < B) ==> A >= B
1052 846 : void swq_expr_node::PushNotOperationDownToStack()
1053 : {
1054 846 : if (eNodeType != SNT_OPERATION)
1055 474 : return;
1056 :
1057 372 : if (nOperation == SWQ_NOT && papoSubExpr[0]->eNodeType == SNT_OPERATION)
1058 : {
1059 42 : if (papoSubExpr[0]->nOperation == SWQ_NOT)
1060 : {
1061 2 : auto poChild = papoSubExpr[0]->papoSubExpr[0];
1062 2 : poChild->PushNotOperationDownToStack();
1063 2 : papoSubExpr[0]->papoSubExpr[0] = nullptr;
1064 2 : *this = std::move(*poChild);
1065 2 : delete poChild;
1066 2 : return;
1067 : }
1068 :
1069 40 : else if (papoSubExpr[0]->nOperation == SWQ_AND)
1070 : {
1071 3 : for (int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
1072 : {
1073 2 : auto notOp = new swq_expr_node(SWQ_NOT);
1074 2 : notOp->PushSubExpression(papoSubExpr[0]->papoSubExpr[i]);
1075 2 : notOp->PushNotOperationDownToStack();
1076 2 : papoSubExpr[0]->papoSubExpr[i] = notOp;
1077 : }
1078 1 : papoSubExpr[0]->nOperation = SWQ_OR;
1079 1 : auto poChild = papoSubExpr[0];
1080 1 : papoSubExpr[0] = nullptr;
1081 1 : *this = std::move(*poChild);
1082 1 : delete poChild;
1083 1 : return;
1084 : }
1085 :
1086 39 : else if (papoSubExpr[0]->nOperation == SWQ_OR)
1087 : {
1088 9 : for (int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
1089 : {
1090 6 : auto notOp = new swq_expr_node(SWQ_NOT);
1091 6 : notOp->PushSubExpression(papoSubExpr[0]->papoSubExpr[i]);
1092 6 : notOp->PushNotOperationDownToStack();
1093 6 : papoSubExpr[0]->papoSubExpr[i] = notOp;
1094 : }
1095 3 : papoSubExpr[0]->nOperation = SWQ_AND;
1096 3 : auto poChild = papoSubExpr[0];
1097 3 : papoSubExpr[0] = nullptr;
1098 3 : *this = std::move(*poChild);
1099 3 : delete poChild;
1100 3 : return;
1101 : }
1102 :
1103 36 : else if (papoSubExpr[0]->nOperation == SWQ_EQ)
1104 : {
1105 3 : auto poChild = papoSubExpr[0];
1106 3 : papoSubExpr[0] = nullptr;
1107 3 : poChild->nOperation = SWQ_NE;
1108 3 : *this = std::move(*poChild);
1109 3 : delete poChild;
1110 3 : return;
1111 : }
1112 33 : else if (papoSubExpr[0]->nOperation == SWQ_NE)
1113 : {
1114 1 : auto poChild = papoSubExpr[0];
1115 1 : papoSubExpr[0] = nullptr;
1116 1 : poChild->nOperation = SWQ_EQ;
1117 1 : *this = std::move(*poChild);
1118 1 : delete poChild;
1119 1 : return;
1120 : }
1121 32 : else if (papoSubExpr[0]->nOperation == SWQ_GT)
1122 : {
1123 1 : auto poChild = papoSubExpr[0];
1124 1 : papoSubExpr[0] = nullptr;
1125 1 : poChild->nOperation = SWQ_LE;
1126 1 : *this = std::move(*poChild);
1127 1 : delete poChild;
1128 1 : return;
1129 : }
1130 31 : else if (papoSubExpr[0]->nOperation == SWQ_GE)
1131 : {
1132 1 : auto poChild = papoSubExpr[0];
1133 1 : papoSubExpr[0] = nullptr;
1134 1 : poChild->nOperation = SWQ_LT;
1135 1 : *this = std::move(*poChild);
1136 1 : delete poChild;
1137 1 : return;
1138 : }
1139 30 : else if (papoSubExpr[0]->nOperation == SWQ_LT)
1140 : {
1141 1 : auto poChild = papoSubExpr[0];
1142 1 : papoSubExpr[0] = nullptr;
1143 1 : poChild->nOperation = SWQ_GE;
1144 1 : *this = std::move(*poChild);
1145 1 : delete poChild;
1146 1 : return;
1147 : }
1148 29 : else if (papoSubExpr[0]->nOperation == SWQ_LE)
1149 : {
1150 1 : auto poChild = papoSubExpr[0];
1151 1 : papoSubExpr[0] = nullptr;
1152 1 : poChild->nOperation = SWQ_GT;
1153 1 : *this = std::move(*poChild);
1154 1 : delete poChild;
1155 1 : return;
1156 : }
1157 : }
1158 :
1159 987 : for (int i = 0; i < nSubExprCount; i++)
1160 629 : papoSubExpr[i]->PushNotOperationDownToStack();
1161 : }
1162 :
1163 : /************************************************************************/
1164 : /* HasReachedMaxDepth() */
1165 : /************************************************************************/
1166 :
1167 22396 : bool swq_expr_node::HasReachedMaxDepth() const
1168 : {
1169 22396 : return nDepth == 128;
1170 : }
1171 :
1172 : #endif // #ifndef DOXYGEN_SKIP
|