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