Line data Source code
1 : /******************************************************************************
2 : *
3 : * Component: OGDI Driver Support Library
4 : * Purpose: Generic SQL WHERE Expression Evaluator Declarations.
5 : * Author: Frank Warmerdam <warmerdam@pobox.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (C) 2001 Information Interoperability Institute (3i)
9 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
10 : * Permission to use, copy, modify and distribute this software and
11 : * its documentation for any purpose and without fee is hereby granted,
12 : * provided that the above copyright notice appear in all copies, that
13 : * both the copyright notice and this permission notice appear in
14 : * supporting documentation, and that the name of 3i not be used
15 : * in advertising or publicity pertaining to distribution of the software
16 : * without specific, written prior permission. 3i makes no
17 : * representations about the suitability of this software for any purpose.
18 : * It is provided "as is" without express or implied warranty.
19 : ****************************************************************************/
20 :
21 : #ifndef SWQ_H_INCLUDED_
22 : #define SWQ_H_INCLUDED_
23 :
24 : #ifndef DOXYGEN_SKIP
25 :
26 : #include "cpl_conv.h"
27 : #include "cpl_string.h"
28 : #include "ogr_core.h"
29 :
30 : #include <list>
31 : #include <map>
32 : #include <vector>
33 : #include <set>
34 :
35 : #if defined(_WIN32) && !defined(strcasecmp)
36 : #define strcasecmp stricmp
37 : #endif
38 :
39 : // Used for swq_summary.oSetDistinctValues and oVectorDistinctValues
40 : #define SZ_OGR_NULL "__OGR_NULL__"
41 :
42 : typedef enum
43 : {
44 : SWQ_OR,
45 : SWQ_AND,
46 : SWQ_NOT,
47 : SWQ_EQ,
48 : SWQ_NE,
49 : SWQ_GE,
50 : SWQ_LE,
51 : SWQ_LT,
52 : SWQ_GT,
53 : SWQ_LIKE,
54 : SWQ_ILIKE,
55 : SWQ_ISNULL,
56 : SWQ_IN,
57 : SWQ_BETWEEN,
58 : SWQ_ADD,
59 : SWQ_SUBTRACT,
60 : SWQ_MULTIPLY,
61 : SWQ_DIVIDE,
62 : SWQ_MODULUS,
63 : SWQ_CONCAT,
64 : SWQ_SUBSTR,
65 : SWQ_HSTORE_GET_VALUE,
66 : SWQ_AVG,
67 : SWQ_MIN,
68 : SWQ_MAX,
69 : SWQ_COUNT,
70 : SWQ_SUM,
71 : SWQ_CAST,
72 : SWQ_CUSTOM_FUNC, /* only if parsing done in bAcceptCustomFuncs mode */
73 : SWQ_ARGUMENT_LIST /* temporary value only set during parsing and replaced by
74 : something else at the end */
75 : } swq_op;
76 :
77 : typedef enum
78 : {
79 : SWQ_INTEGER,
80 : SWQ_INTEGER64,
81 : SWQ_FLOAT,
82 : SWQ_STRING,
83 : SWQ_BOOLEAN, // integer
84 : SWQ_DATE, // string
85 : SWQ_TIME, // string
86 : SWQ_TIMESTAMP, // string
87 : SWQ_GEOMETRY,
88 : SWQ_NULL,
89 : SWQ_OTHER,
90 : SWQ_ERROR
91 : } swq_field_type;
92 :
93 : #define SWQ_IS_INTEGER(x) ((x) == SWQ_INTEGER || (x) == SWQ_INTEGER64)
94 :
95 : typedef enum
96 : {
97 : SNT_CONSTANT,
98 : SNT_COLUMN,
99 : SNT_OPERATION
100 : } swq_node_type;
101 :
102 : class swq_field_list;
103 : class swq_expr_node;
104 : class swq_select;
105 : class OGRGeometry;
106 :
107 : struct CPL_UNSTABLE_API swq_evaluation_context
108 : {
109 : bool bUTF8Strings = false;
110 : };
111 :
112 : typedef swq_expr_node *(*swq_field_fetcher)(swq_expr_node *op,
113 : void *record_handle);
114 : typedef swq_expr_node *(*swq_op_evaluator)(
115 : swq_expr_node *op, swq_expr_node **sub_field_values,
116 : const swq_evaluation_context &sContext);
117 : typedef swq_field_type (*swq_op_checker)(
118 : swq_expr_node *op, int bAllowMismatchTypeOnFieldComparison);
119 :
120 : class swq_custom_func_registrar;
121 :
122 2181 : class CPL_UNSTABLE_API swq_expr_node
123 : {
124 : swq_expr_node *Evaluate(swq_field_fetcher pfnFetcher, void *record,
125 : const swq_evaluation_context &sContext,
126 : int nRecLevel);
127 : void reset();
128 :
129 : public:
130 : swq_expr_node();
131 : swq_expr_node(const swq_expr_node &);
132 : swq_expr_node(swq_expr_node &&);
133 :
134 : swq_expr_node &operator=(const swq_expr_node &);
135 : swq_expr_node &operator=(swq_expr_node &&);
136 :
137 : bool operator==(const swq_expr_node &) const;
138 :
139 : explicit swq_expr_node(const char *);
140 : explicit swq_expr_node(int);
141 : explicit swq_expr_node(GIntBig);
142 : explicit swq_expr_node(double);
143 : explicit swq_expr_node(OGRGeometry *);
144 : explicit swq_expr_node(swq_op);
145 :
146 : ~swq_expr_node();
147 :
148 : void MarkAsTimestamp();
149 : CPLString UnparseOperationFromUnparsedSubExpr(char **apszSubExpr);
150 : char *Unparse(swq_field_list *, char chColumnQuote);
151 : void Dump(FILE *fp, int depth);
152 : swq_field_type Check(swq_field_list *, int bAllowFieldsInSecondaryTables,
153 : int bAllowMismatchTypeOnFieldComparison,
154 : swq_custom_func_registrar *poCustomFuncRegistrar,
155 : int depth = 0);
156 : swq_expr_node *Evaluate(swq_field_fetcher pfnFetcher, void *record,
157 : const swq_evaluation_context &sContext);
158 : swq_expr_node *Clone();
159 :
160 : void ReplaceBetweenByGEAndLERecurse();
161 : void PushNotOperationDownToStack();
162 :
163 : swq_node_type eNodeType = SNT_CONSTANT;
164 : swq_field_type field_type = SWQ_INTEGER;
165 :
166 : /* only for SNT_OPERATION */
167 : void PushSubExpression(swq_expr_node *);
168 : void ReverseSubExpressions();
169 : swq_op nOperation = SWQ_OR;
170 : int nSubExprCount = 0;
171 : swq_expr_node **papoSubExpr = nullptr;
172 :
173 : /* only for SNT_COLUMN */
174 : int field_index = 0;
175 : int table_index = 0;
176 : char *table_name = nullptr;
177 :
178 : /* only for SNT_CONSTANT */
179 : int is_null = false;
180 : GIntBig int_value = 0;
181 : double float_value = 0.0;
182 : OGRGeometry *geometry_value = nullptr;
183 :
184 : /* shared by SNT_COLUMN, SNT_CONSTANT and also possibly SNT_OPERATION when
185 : */
186 : /* nOperation == SWQ_CUSTOM_FUNC */
187 : char *string_value = nullptr; /* column name when SNT_COLUMN */
188 :
189 : static CPLString QuoteIfNecessary(const CPLString &, char chQuote = '\'');
190 : static CPLString Quote(const CPLString &, char chQuote = '\'');
191 : };
192 :
193 : typedef struct
194 : {
195 : const char *pszName;
196 : swq_op eOperation;
197 : swq_op_evaluator pfnEvaluator;
198 : swq_op_checker pfnChecker;
199 : } swq_operation;
200 :
201 : class CPL_UNSTABLE_API swq_op_registrar
202 : {
203 : public:
204 : static const swq_operation *GetOperator(const char *);
205 : static const swq_operation *GetOperator(swq_op eOperation);
206 : };
207 :
208 : class CPL_UNSTABLE_API swq_custom_func_registrar
209 : {
210 : public:
211 1 : virtual ~swq_custom_func_registrar()
212 1 : {
213 1 : }
214 :
215 : virtual const swq_operation *GetOperator(const char *) = 0;
216 : };
217 :
218 : typedef struct
219 : {
220 : char *data_source;
221 : char *table_name;
222 : char *table_alias;
223 : } swq_table_def;
224 :
225 : class CPL_UNSTABLE_API swq_field_list
226 : {
227 : public:
228 : int count;
229 : char **names;
230 : swq_field_type *types;
231 : int *table_ids;
232 : int *ids;
233 :
234 : int table_count;
235 : swq_table_def *table_defs;
236 : };
237 :
238 : class CPL_UNSTABLE_API swq_parse_context
239 : {
240 : public:
241 7384 : swq_parse_context()
242 7384 : : nStartToken(0), pszInput(nullptr), pszNext(nullptr),
243 : pszLastValid(nullptr), bAcceptCustomFuncs(FALSE), poRoot(nullptr),
244 7384 : poCurSelect(nullptr)
245 : {
246 7384 : }
247 :
248 : int nStartToken;
249 : const char *pszInput;
250 : const char *pszNext;
251 : const char *pszLastValid;
252 : int bAcceptCustomFuncs;
253 :
254 : swq_expr_node *poRoot;
255 :
256 : swq_select *poCurSelect;
257 : };
258 :
259 : /* Compile an SQL WHERE clause into an internal form. The field_list is
260 : ** the list of fields in the target 'table', used to render where into
261 : ** field numbers instead of names.
262 : */
263 : int CPL_UNSTABLE_API swqparse(swq_parse_context *context);
264 : int CPL_UNSTABLE_API swqlex(swq_expr_node **ppNode, swq_parse_context *context);
265 : void CPL_UNSTABLE_API swqerror(swq_parse_context *context, const char *msg);
266 :
267 : int CPL_UNSTABLE_API swq_identify_field(const char *table_name,
268 : const char *token,
269 : swq_field_list *field_list,
270 : swq_field_type *this_type,
271 : int *table_id);
272 :
273 : CPLErr CPL_UNSTABLE_API
274 : swq_expr_compile(const char *where_clause, int field_count, char **field_list,
275 : swq_field_type *field_types, int bCheck,
276 : swq_custom_func_registrar *poCustomFuncRegistrar,
277 : swq_expr_node **expr_root);
278 :
279 : CPLErr CPL_UNSTABLE_API
280 : swq_expr_compile2(const char *where_clause, swq_field_list *field_list,
281 : int bCheck, swq_custom_func_registrar *poCustomFuncRegistrar,
282 : swq_expr_node **expr_root);
283 :
284 : /*
285 : ** Evaluation related.
286 : */
287 : int CPL_UNSTABLE_API swq_test_like(const char *input, const char *pattern);
288 :
289 : swq_expr_node CPL_UNSTABLE_API *
290 : SWQGeneralEvaluator(swq_expr_node *, swq_expr_node **,
291 : const swq_evaluation_context &sContext);
292 : swq_field_type CPL_UNSTABLE_API
293 : SWQGeneralChecker(swq_expr_node *node, int bAllowMismatchTypeOnFieldComparison);
294 : swq_expr_node CPL_UNSTABLE_API *
295 : SWQCastEvaluator(swq_expr_node *, swq_expr_node **,
296 : const swq_evaluation_context &sContext);
297 : swq_field_type CPL_UNSTABLE_API
298 : SWQCastChecker(swq_expr_node *node, int bAllowMismatchTypeOnFieldComparison);
299 : const char CPL_UNSTABLE_API *SWQFieldTypeToString(swq_field_type field_type);
300 :
301 : /****************************************************************************/
302 :
303 : #define SWQP_ALLOW_UNDEFINED_COL_FUNCS 0x01
304 :
305 : #define SWQM_SUMMARY_RECORD 1
306 : #define SWQM_RECORDSET 2
307 : #define SWQM_DISTINCT_LIST 3
308 :
309 : typedef enum
310 : {
311 : SWQCF_NONE = 0,
312 : SWQCF_AVG = SWQ_AVG,
313 : SWQCF_MIN = SWQ_MIN,
314 : SWQCF_MAX = SWQ_MAX,
315 : SWQCF_COUNT = SWQ_COUNT,
316 : SWQCF_SUM = SWQ_SUM,
317 : SWQCF_CUSTOM
318 : } swq_col_func;
319 :
320 : typedef struct
321 : {
322 : swq_col_func col_func;
323 : char *table_name;
324 : char *field_name;
325 : char *field_alias;
326 : int table_index;
327 : int field_index;
328 : swq_field_type field_type;
329 : swq_field_type target_type;
330 : OGRFieldSubType target_subtype;
331 : int field_length;
332 : int field_precision;
333 : int distinct_flag;
334 : OGRwkbGeometryType eGeomType;
335 : int nSRID;
336 : swq_expr_node *expr;
337 : } swq_col_def;
338 :
339 : class CPL_UNSTABLE_API swq_summary
340 : {
341 : public:
342 : struct Comparator
343 : {
344 : bool bSortAsc;
345 : swq_field_type eType;
346 :
347 101 : Comparator() : bSortAsc(true), eType(SWQ_STRING)
348 : {
349 101 : }
350 :
351 : bool operator()(const CPLString &, const CPLString &) const;
352 : };
353 :
354 : GIntBig count = 0;
355 :
356 : std::vector<CPLString> oVectorDistinctValues{};
357 : std::set<CPLString, Comparator> oSetDistinctValues{};
358 : double sum = 0.0;
359 : double min = 0.0;
360 : double max = 0.0;
361 : CPLString osMin{};
362 : CPLString osMax{};
363 : };
364 :
365 : typedef struct
366 : {
367 : char *table_name;
368 : char *field_name;
369 : int table_index;
370 : int field_index;
371 : int ascending_flag;
372 : } swq_order_def;
373 :
374 : typedef struct
375 : {
376 : int secondary_table;
377 : swq_expr_node *poExpr;
378 : } swq_join_def;
379 :
380 : class CPL_UNSTABLE_API swq_select_parse_options
381 : {
382 : public:
383 : swq_custom_func_registrar *poCustomFuncRegistrar;
384 : int bAllowFieldsInSecondaryTablesInWhere;
385 : int bAddSecondaryTablesGeometryFields;
386 : int bAlwaysPrefixWithTableName;
387 : int bAllowDistinctOnGeometryField;
388 : int bAllowDistinctOnMultipleFields;
389 :
390 60 : swq_select_parse_options()
391 60 : : poCustomFuncRegistrar(nullptr),
392 : bAllowFieldsInSecondaryTablesInWhere(FALSE),
393 : bAddSecondaryTablesGeometryFields(FALSE),
394 : bAlwaysPrefixWithTableName(FALSE),
395 : bAllowDistinctOnGeometryField(FALSE),
396 60 : bAllowDistinctOnMultipleFields(FALSE)
397 : {
398 60 : }
399 : };
400 :
401 2769 : class CPL_UNSTABLE_API swq_select
402 : {
403 : void postpreparse();
404 :
405 : CPL_DISALLOW_COPY_ASSIGN(swq_select)
406 :
407 : public:
408 : swq_select();
409 : ~swq_select();
410 :
411 : int query_mode = 0;
412 :
413 : char *raw_select = nullptr;
414 :
415 : int PushField(swq_expr_node *poExpr, const char *pszAlias = nullptr,
416 : int distinct_flag = FALSE);
417 :
418 : int PushExcludeField(swq_expr_node *poExpr);
419 :
420 122369 : int result_columns() const
421 : {
422 122369 : return static_cast<int>(column_defs.size());
423 : }
424 :
425 : std::vector<swq_col_def> column_defs{};
426 : std::vector<swq_summary> column_summary{};
427 :
428 : int PushTableDef(const char *pszDataSource, const char *pszTableName,
429 : const char *pszAlias);
430 : int table_count = 0;
431 : swq_table_def *table_defs = nullptr;
432 :
433 : void PushJoin(int iSecondaryTable, swq_expr_node *poExpr);
434 : int join_count = 0;
435 : swq_join_def *join_defs = nullptr;
436 :
437 : swq_expr_node *where_expr = nullptr;
438 :
439 : void PushOrderBy(const char *pszTableName, const char *pszFieldName,
440 : int bAscending);
441 : int order_specs = 0;
442 : swq_order_def *order_defs = nullptr;
443 :
444 : void SetLimit(GIntBig nLimit);
445 : GIntBig limit = -1;
446 :
447 : void SetOffset(GIntBig nOffset);
448 : GIntBig offset = 0;
449 :
450 : swq_select *poOtherSelect = nullptr;
451 : void PushUnionAll(swq_select *poOtherSelectIn);
452 :
453 : CPLErr preparse(const char *select_statement,
454 : int bAcceptCustomFuncs = FALSE);
455 : CPLErr expand_wildcard(swq_field_list *field_list,
456 : int bAlwaysPrefixWithTableName);
457 : CPLErr parse(swq_field_list *field_list,
458 : swq_select_parse_options *poParseOptions);
459 :
460 : char *Unparse();
461 :
462 : bool bExcludedGeometry = false;
463 :
464 : private:
465 : bool IsFieldExcluded(int src_index, const char *table, const char *field);
466 :
467 : // map of EXCLUDE columns keyed according to the index of the
468 : // asterisk with which it should be associated. key of -1 is
469 : // used for column lists that have not yet been associated with
470 : // an asterisk.
471 : std::map<int, std::list<swq_col_def>> m_exclude_fields{};
472 : };
473 :
474 : const char CPL_UNSTABLE_API *swq_select_summarize(swq_select *select_info,
475 : int dest_column,
476 : const char *value);
477 :
478 : int CPL_UNSTABLE_API swq_is_reserved_keyword(const char *pszStr);
479 :
480 : char CPL_UNSTABLE_API *OGRHStoreGetValue(const char *pszHStore,
481 : const char *pszSearchedKey);
482 :
483 : #ifdef GDAL_COMPILATION
484 : void swq_fixup(swq_parse_context *psParseContext);
485 : swq_expr_node *swq_create_and_or_or(swq_op op, swq_expr_node *left,
486 : swq_expr_node *right);
487 : int swq_test_like(const char *input, const char *pattern, char chEscape,
488 : bool insensitive, bool bUTF8Strings);
489 : #endif
490 :
491 : #endif /* #ifndef DOXYGEN_SKIP */
492 :
493 : #endif /* def SWQ_H_INCLUDED_ */
|