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