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 : * Permission to use, copy, modify and distribute this software and
10 : * its documentation for any purpose and without fee is hereby granted,
11 : * provided that the above copyright notice appear in all copies, that
12 : * both the copyright notice and this permission notice appear in
13 : * supporting documentation, and that the name of 3i not be used
14 : * in advertising or publicity pertaining to distribution of the software
15 : * without specific, written prior permission. 3i makes no
16 : * representations about the suitability of this software for any purpose.
17 : * It is provided "as is" without express or implied warranty.
18 : ****************************************************************************/
19 :
20 : #ifndef _SWQ_H_INCLUDED_
21 : #define _SWQ_H_INCLUDED_
22 :
23 : #include "cpl_conv.h"
24 : #include "cpl_string.h"
25 :
26 : #if defined(_WIN32) && !defined(_WIN32_WCE)
27 : # define strcasecmp stricmp
28 : #elif defined(_WIN32_WCE)
29 : # define strcasecmp _stricmp
30 : #endif
31 :
32 : typedef enum {
33 : SWQ_OR,
34 : SWQ_AND,
35 : SWQ_NOT,
36 : SWQ_EQ,
37 : SWQ_NE,
38 : SWQ_GE,
39 : SWQ_LE,
40 : SWQ_LT,
41 : SWQ_GT,
42 : SWQ_LIKE,
43 : SWQ_ISNULL,
44 : SWQ_IN,
45 : SWQ_BETWEEN,
46 : SWQ_ADD,
47 : SWQ_SUBTRACT,
48 : SWQ_MULTIPLY,
49 : SWQ_DIVIDE,
50 : SWQ_MODULUS,
51 : SWQ_CONCAT,
52 : SWQ_SUBSTR,
53 : SWQ_AVG,
54 : SWQ_MIN,
55 : SWQ_MAX,
56 : SWQ_COUNT,
57 : SWQ_SUM,
58 : SWQ_CAST,
59 : SWQ_FUNC_DEFINED,
60 : SWQ_UNKNOWN
61 : } swq_op;
62 :
63 : typedef enum {
64 : SWQ_INTEGER,
65 : SWQ_FLOAT,
66 : SWQ_STRING,
67 : SWQ_BOOLEAN, // integer
68 : SWQ_DATE, // string
69 : SWQ_TIME, // string
70 : SWQ_TIMESTAMP,// string
71 : SWQ_NULL,
72 : SWQ_OTHER,
73 : SWQ_ERROR
74 : } swq_field_type;
75 :
76 : typedef enum {
77 : SNT_CONSTANT,
78 : SNT_COLUMN,
79 : SNT_OPERATION
80 : } swq_node_type;
81 :
82 :
83 : class swq_field_list;
84 : class swq_expr_node;
85 : class swq_select;
86 :
87 : typedef swq_expr_node *(*swq_field_fetcher)( swq_expr_node *op,
88 : void *record_handle );
89 : typedef swq_expr_node *(*swq_op_evaluator)(swq_expr_node *op,
90 : swq_expr_node **sub_field_values );
91 : typedef swq_field_type (*swq_op_checker)( swq_expr_node *op );
92 :
93 : class swq_expr_node {
94 : static void Quote( CPLString &, char chQuote = '\'' );
95 : public:
96 : swq_expr_node();
97 :
98 : swq_expr_node( const char * );
99 : swq_expr_node( int );
100 : swq_expr_node( double );
101 : swq_expr_node( swq_op );
102 :
103 : ~swq_expr_node();
104 :
105 : void Initialize();
106 : char *Unparse( swq_field_list *, char chColumnQuote );
107 : void Dump( FILE *fp, int depth );
108 : swq_field_type Check( swq_field_list * );
109 : swq_expr_node* Evaluate( swq_field_fetcher pfnFetcher,
110 : void *record );
111 :
112 : swq_node_type eNodeType;
113 : swq_field_type field_type;
114 :
115 : /* only for SNT_OPERATION */
116 : void PushSubExpression( swq_expr_node * );
117 : void ReverseSubExpressions();
118 : int nOperation;
119 : int nSubExprCount;
120 : swq_expr_node **papoSubExpr;
121 :
122 : /* only for SNT_COLUMN */
123 : int field_index;
124 : int table_index;
125 :
126 : /* only for SNT_CONSTANT */
127 : int is_null;
128 : char *string_value;
129 : int int_value;
130 : double float_value;
131 : };
132 :
133 : class swq_operation {
134 : public:
135 1534 : swq_operation() {}
136 1534 : ~swq_operation() {}
137 :
138 : swq_op eOperation;
139 : CPLString osName;
140 : swq_op_evaluator pfnEvaluator;
141 : swq_op_checker pfnChecker;
142 : };
143 :
144 : class swq_op_registrar {
145 : public:
146 : static const swq_operation *GetOperator( const char * );
147 : static const swq_operation *GetOperator( swq_op eOperation );
148 : static void Initialize();
149 : static void DeInitialize();
150 : static void AddOperator( const char *pszName, swq_op eOpCode,
151 : swq_op_evaluator pfnEvaluator = NULL,
152 : swq_op_checker pfnChecker = NULL );
153 : };
154 :
155 : typedef struct {
156 : char *data_source;
157 : char *table_name;
158 : char *table_alias;
159 : } swq_table_def;
160 :
161 : class swq_field_list {
162 : public:
163 : int count;
164 : char **names;
165 : swq_field_type *types;
166 : int *table_ids;
167 : int *ids;
168 :
169 : int table_count;
170 : swq_table_def *table_defs;
171 : };
172 :
173 : class swq_parse_context {
174 : public:
175 1884 : swq_parse_context() : nStartToken(0), poRoot(NULL), poSelect(NULL) {}
176 :
177 : int nStartToken;
178 : const char *pszInput;
179 : const char *pszNext;
180 :
181 : swq_expr_node *poRoot;
182 :
183 : swq_select *poSelect;
184 : };
185 :
186 : /* Compile an SQL WHERE clause into an internal form. The field_list is
187 : ** the list of fields in the target 'table', used to render where into
188 : ** field numbers instead of names.
189 : */
190 : int swqparse( swq_parse_context *context );
191 : int swqlex( swq_expr_node **ppNode, swq_parse_context *context );
192 :
193 : int swq_identify_field( const char *token, swq_field_list *field_list,
194 : swq_field_type *this_type, int *table_id );
195 :
196 : CPLErr swq_expr_compile( const char *where_clause,
197 : int field_count,
198 : char **field_list,
199 : swq_field_type *field_types,
200 : swq_expr_node **expr_root );
201 :
202 : CPLErr swq_expr_compile2( const char *where_clause,
203 : swq_field_list *field_list,
204 : swq_expr_node **expr_root );
205 :
206 : /*
207 : ** Evaluation related.
208 : */
209 : int swq_test_like( const char *input, const char *pattern );
210 :
211 : swq_expr_node *SWQGeneralEvaluator( swq_expr_node *, swq_expr_node **);
212 : swq_field_type SWQGeneralChecker( swq_expr_node *node );
213 : swq_expr_node *SWQCastEvaluator( swq_expr_node *, swq_expr_node **);
214 : swq_field_type SWQCastChecker( swq_expr_node *node );
215 :
216 : /****************************************************************************/
217 :
218 : #define SWQP_ALLOW_UNDEFINED_COL_FUNCS 0x01
219 :
220 : #define SWQM_SUMMARY_RECORD 1
221 : #define SWQM_RECORDSET 2
222 : #define SWQM_DISTINCT_LIST 3
223 :
224 : typedef enum {
225 : SWQCF_NONE = 0,
226 : SWQCF_AVG = SWQ_AVG,
227 : SWQCF_MIN = SWQ_MIN,
228 : SWQCF_MAX = SWQ_MAX,
229 : SWQCF_COUNT = SWQ_COUNT,
230 : SWQCF_SUM = SWQ_SUM,
231 : SWQCF_CUSTOM
232 : } swq_col_func;
233 :
234 : typedef struct {
235 : swq_col_func col_func;
236 : char *field_name;
237 : char *field_alias;
238 : int table_index;
239 : int field_index;
240 : swq_field_type field_type;
241 : swq_field_type target_type;
242 : int field_length;
243 : int field_precision;
244 : int distinct_flag;
245 : swq_expr_node *expr;
246 : } swq_col_def;
247 :
248 : typedef struct {
249 : int count;
250 :
251 : char **distinct_list; /* items of the list can be NULL */
252 : double sum;
253 : double min;
254 : double max;
255 : } swq_summary;
256 :
257 : typedef struct {
258 : char *field_name;
259 : int table_index;
260 : int field_index;
261 : int ascending_flag;
262 : } swq_order_def;
263 :
264 : typedef struct {
265 : int secondary_table;
266 :
267 : char *primary_field_name;
268 : int primary_field;
269 :
270 : swq_op op;
271 :
272 : char *secondary_field_name;
273 : int secondary_field;
274 : } swq_join_def;
275 :
276 : class swq_select
277 : {
278 : public:
279 : swq_select();
280 : ~swq_select();
281 :
282 : int query_mode;
283 :
284 : char *raw_select;
285 :
286 : int PushField( swq_expr_node *poExpr, const char *pszAlias=NULL,
287 : int distinct_flag = FALSE );
288 : int result_columns;
289 : swq_col_def *column_defs;
290 : swq_summary *column_summary;
291 :
292 : int PushTableDef( const char *pszDataSource,
293 : const char *pszTableName,
294 : const char *pszAlias );
295 : int table_count;
296 : swq_table_def *table_defs;
297 :
298 : void PushJoin( int iSecondaryTable,
299 : const char *pszPrimaryField,
300 : const char *pszSecondaryField );
301 : int join_count;
302 : swq_join_def *join_defs;
303 :
304 : swq_expr_node *where_expr;
305 :
306 : void PushOrderBy( const char *pszFieldName, int bAscending );
307 : int order_specs;
308 : swq_order_def *order_defs;
309 :
310 : CPLErr preparse( const char *select_statement );
311 : CPLErr expand_wildcard( swq_field_list *field_list );
312 : CPLErr parse( swq_field_list *field_list, int parse_flags );
313 :
314 : void Dump( FILE * );
315 : };
316 :
317 : CPLErr swq_select_parse( swq_select *select_info,
318 : swq_field_list *field_list,
319 : int parse_flags );
320 :
321 : const char *swq_select_finish_summarize( swq_select *select_info );
322 : const char *swq_select_summarize( swq_select *select_info,
323 : int dest_column,
324 : const char *value );
325 :
326 : int swq_is_reserved_keyword(const char* pszStr);
327 :
328 : #endif /* def _SWQ_H_INCLUDED_ */
|