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

Generated for GDAL by doxygen 1.9.4.