GDAL

ogr_swq.h
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
42typedef 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
77typedef 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
95typedef enum
96{
97 SNT_CONSTANT,
98 SNT_COLUMN,
99 SNT_OPERATION
100} swq_node_type;
101
102class swq_field_list;
103class swq_expr_node;
104class swq_select;
105class OGRGeometry;
106
107struct CPL_UNSTABLE_API swq_evaluation_context
108{
109 bool bUTF8Strings = false;
110};
111
112typedef swq_expr_node *(*swq_field_fetcher)(swq_expr_node *op,
113 void *record_handle);
114typedef swq_expr_node *(*swq_op_evaluator)(
115 swq_expr_node *op, swq_expr_node **sub_field_values,
116 const swq_evaluation_context &sContext);
117typedef swq_field_type (*swq_op_checker)(
118 swq_expr_node *op, int bAllowMismatchTypeOnFieldComparison);
119
120class swq_custom_func_registrar;
121
122class 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
193typedef struct
194{
195 const char *pszName;
196 swq_op eOperation;
197 swq_op_evaluator pfnEvaluator;
198 swq_op_checker pfnChecker;
199} swq_operation;
200
201class 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
208class CPL_UNSTABLE_API swq_custom_func_registrar
209{
210 public:
211 virtual ~swq_custom_func_registrar()
212 {
213 }
214
215 virtual const swq_operation *GetOperator(const char *) = 0;
216};
217
218typedef struct
219{
220 char *data_source;
221 char *table_name;
222 char *table_alias;
223} swq_table_def;
224
225class 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
238class CPL_UNSTABLE_API swq_parse_context
239{
240 public:
241 swq_parse_context()
242 : nStartToken(0), pszInput(nullptr), pszNext(nullptr),
243 pszLastValid(nullptr), bAcceptCustomFuncs(FALSE), poRoot(nullptr),
244 poCurSelect(nullptr)
245 {
246 }
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*/
263int CPL_UNSTABLE_API swqparse(swq_parse_context *context);
264int CPL_UNSTABLE_API swqlex(swq_expr_node **ppNode, swq_parse_context *context);
265void CPL_UNSTABLE_API swqerror(swq_parse_context *context, const char *msg);
266
267int 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
274swq_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
280swq_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*/
287int CPL_UNSTABLE_API swq_test_like(const char *input, const char *pattern);
288
289swq_expr_node CPL_UNSTABLE_API *
290SWQGeneralEvaluator(swq_expr_node *, swq_expr_node **,
291 const swq_evaluation_context &sContext);
292swq_field_type CPL_UNSTABLE_API
293SWQGeneralChecker(swq_expr_node *node, int bAllowMismatchTypeOnFieldComparison);
294swq_expr_node CPL_UNSTABLE_API *
295SWQCastEvaluator(swq_expr_node *, swq_expr_node **,
296 const swq_evaluation_context &sContext);
297swq_field_type CPL_UNSTABLE_API
298SWQCastChecker(swq_expr_node *node, int bAllowMismatchTypeOnFieldComparison);
299const 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
309typedef 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
320typedef 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
339class CPL_UNSTABLE_API swq_summary
340{
341 public:
342 struct Comparator
343 {
344 bool bSortAsc;
345 swq_field_type eType;
346
347 Comparator() : bSortAsc(true), eType(SWQ_STRING)
348 {
349 }
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
365typedef 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
374typedef struct
375{
376 int secondary_table;
377 swq_expr_node *poExpr;
378} swq_join_def;
379
380class 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 swq_select_parse_options()
391 : poCustomFuncRegistrar(nullptr),
392 bAllowFieldsInSecondaryTablesInWhere(FALSE),
393 bAddSecondaryTablesGeometryFields(FALSE),
394 bAlwaysPrefixWithTableName(FALSE),
395 bAllowDistinctOnGeometryField(FALSE),
396 bAllowDistinctOnMultipleFields(FALSE)
397 {
398 }
399};
400
401class 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 int result_columns() const
421 {
422 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
474const char CPL_UNSTABLE_API *swq_select_summarize(swq_select *select_info,
475 int dest_column,
476 const char *value);
477
478int CPL_UNSTABLE_API swq_is_reserved_keyword(const char *pszStr);
479
480char CPL_UNSTABLE_API *OGRHStoreGetValue(const char *pszHStore,
481 const char *pszSearchedKey);
482
483#ifdef GDAL_COMPILATION
484void swq_fixup(swq_parse_context *psParseContext);
485swq_expr_node *swq_create_and_or_or(swq_op op, swq_expr_node *left,
486 swq_expr_node *right);
487int 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_ */
CPLString
Convenient string class based on std::string.
Definition: cpl_string.h:320
OGRGeometry
Abstract base class for all geometry classes.
Definition: ogr_geometry.h:377
cpl_conv.h
Various convenience functions for CPL.
CPLErr
CPLErr
Error category.
Definition: cpl_error.h:53
CPL_DISALLOW_COPY_ASSIGN
#define CPL_DISALLOW_COPY_ASSIGN(ClassName)
Helper to remove the copy and assignment constructors so that the compiler will not generate the defa...
Definition: cpl_port.h:1042
GIntBig
long long GIntBig
Large signed integer type (generally 64-bit integer type).
Definition: cpl_port.h:215
cpl_string.h
Various convenience functions for working with strings and string lists.
ogr_core.h
Core portability services for cross-platform OGR code.
OGRFieldSubType
OGRFieldSubType
List of field subtypes.
Definition: ogr_core.h:821
OGRwkbGeometryType
OGRwkbGeometryType
List of well known binary geometry types.
Definition: ogr_core.h:416