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