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
40typedef 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
73typedef 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
90typedef enum {
91 SNT_CONSTANT,
92 SNT_COLUMN,
93 SNT_OPERATION
94} swq_node_type;
95
96class swq_field_list;
97class swq_expr_node;
98class swq_select;
99class OGRGeometry;
100
101typedef swq_expr_node *(*swq_field_fetcher)( swq_expr_node *op,
102 void *record_handle );
103typedef swq_expr_node *(*swq_op_evaluator)(swq_expr_node *op,
104 swq_expr_node **sub_field_values );
105typedef swq_field_type (*swq_op_checker)( swq_expr_node *op,
106 int bAllowMismatchTypeOnFieldComparison );
107
108class swq_custom_func_registrar;
109
110class 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 );
115public:
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
170typedef struct {
171 const char* pszName;
172 swq_op eOperation;
173 swq_op_evaluator pfnEvaluator;
174 swq_op_checker pfnChecker;
175} swq_operation;
176
177class CPL_UNSTABLE_API swq_op_registrar {
178public:
179 static const swq_operation *GetOperator( const char * );
180 static const swq_operation *GetOperator( swq_op eOperation );
181};
182
183class 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
190typedef struct {
191 char *data_source;
192 char *table_name;
193 char *table_alias;
194} swq_table_def;
195
196class CPL_UNSTABLE_API swq_field_list {
197public:
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
208class CPL_UNSTABLE_API swq_parse_context {
209public:
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*/
229int CPL_UNSTABLE_API swqparse( swq_parse_context *context );
230int CPL_UNSTABLE_API swqlex( swq_expr_node **ppNode, swq_parse_context *context );
231void CPL_UNSTABLE_API swqerror( swq_parse_context *context, const char *msg );
232
233int 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
237CPLErr 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
245CPLErr 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*/
254int CPL_UNSTABLE_API swq_test_like( const char *input, const char *pattern );
255
256swq_expr_node CPL_UNSTABLE_API *SWQGeneralEvaluator( swq_expr_node *, swq_expr_node **);
257swq_field_type CPL_UNSTABLE_API SWQGeneralChecker( swq_expr_node *node, int bAllowMismatchTypeOnFieldComparison );
258swq_expr_node CPL_UNSTABLE_API *SWQCastEvaluator( swq_expr_node *, swq_expr_node **);
259swq_field_type CPL_UNSTABLE_API SWQCastChecker( swq_expr_node *node, int bAllowMismatchTypeOnFieldComparison );
260const 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
270typedef 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
280typedef 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
298class CPL_UNSTABLE_API swq_summary {
299public:
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
321typedef 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
329typedef struct {
330 int secondary_table;
331 swq_expr_node *poExpr;
332} swq_join_def;
333
334class CPL_UNSTABLE_API swq_select_parse_options
335{
336public:
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
352class CPL_UNSTABLE_API swq_select
353{
354 void postpreparse();
355
356 CPL_DISALLOW_COPY_ASSIGN(swq_select)
357
358public:
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
408CPLErr CPL_UNSTABLE_API swq_select_parse( swq_select *select_info,
409 swq_field_list *field_list,
410 int parse_flags );
411
412const char CPL_UNSTABLE_API *swq_select_summarize( swq_select *select_info,
413 int dest_column,
414 const char *value );
415
416int CPL_UNSTABLE_API swq_is_reserved_keyword(const char* pszStr);
417
418char CPL_UNSTABLE_API *OGRHStoreGetValue(const char* pszHStore,
419 const char* pszSearchedKey);
420
421#ifdef GDAL_COMPILATION
422void swq_fixup(swq_parse_context* psParseContext);
423swq_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_ */
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:697
OGRwkbGeometryType
List of well known binary geometry types.
Definition ogr_core.h:369