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