1 : /******************************************************************************
2 : *
3 : * Component: OGR SQL Engine
4 : * Purpose: Implementation of the swq_expr_node class used to represent a
5 : * node in an SQL expression.
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_conv.h"
31 : #include "cpl_multiproc.h"
32 : #include "swq.h"
33 : #include <vector>
34 :
35 : /************************************************************************/
36 : /* swq_expr_node() */
37 : /************************************************************************/
38 :
39 202 : swq_expr_node::swq_expr_node()
40 :
41 : {
42 202 : Initialize();
43 202 : }
44 :
45 : /************************************************************************/
46 : /* swq_expr_node(int) */
47 : /************************************************************************/
48 :
49 534223 : swq_expr_node::swq_expr_node( int nValueIn )
50 :
51 : {
52 534223 : Initialize();
53 :
54 534223 : int_value = nValueIn;
55 534223 : }
56 :
57 : /************************************************************************/
58 : /* swq_expr_node(double) */
59 : /************************************************************************/
60 :
61 2485 : swq_expr_node::swq_expr_node( double dfValueIn )
62 :
63 : {
64 2485 : Initialize();
65 :
66 2485 : field_type = SWQ_FLOAT;
67 2485 : float_value = dfValueIn;
68 2485 : }
69 :
70 : /************************************************************************/
71 : /* swq_expr_node(const char*) */
72 : /************************************************************************/
73 :
74 377527 : swq_expr_node::swq_expr_node( const char *pszValueIn )
75 :
76 : {
77 377527 : Initialize();
78 :
79 377527 : field_type = SWQ_STRING;
80 377527 : string_value = CPLStrdup( pszValueIn ? pszValueIn : "" );
81 377527 : is_null = pszValueIn == NULL;
82 377527 : }
83 :
84 : /************************************************************************/
85 : /* swq_expr_node(swq_op) */
86 : /************************************************************************/
87 :
88 678 : swq_expr_node::swq_expr_node( swq_op eOp )
89 :
90 : {
91 678 : Initialize();
92 :
93 678 : eNodeType = SNT_OPERATION;
94 :
95 678 : nOperation = (int) eOp;
96 678 : nSubExprCount = 0;
97 678 : papoSubExpr = NULL;
98 678 : }
99 :
100 : /************************************************************************/
101 : /* Initialize() */
102 : /************************************************************************/
103 :
104 915115 : void swq_expr_node::Initialize()
105 :
106 : {
107 915115 : eNodeType = SNT_CONSTANT;
108 915115 : field_type = SWQ_INTEGER;
109 915115 : int_value = 0;
110 :
111 915115 : is_null = FALSE;
112 915115 : string_value = NULL;
113 915115 : papoSubExpr = NULL;
114 915115 : nSubExprCount = 0;
115 915115 : }
116 :
117 : /************************************************************************/
118 : /* ~swq_expr_node() */
119 : /************************************************************************/
120 :
121 915115 : swq_expr_node::~swq_expr_node()
122 :
123 : {
124 915115 : CPLFree( string_value );
125 :
126 : int i;
127 916261 : for( i = 0; i < nSubExprCount; i++ )
128 1146 : delete papoSubExpr[i];
129 915115 : CPLFree( papoSubExpr );
130 915115 : }
131 :
132 : /************************************************************************/
133 : /* PushSubExpression() */
134 : /************************************************************************/
135 :
136 1252 : void swq_expr_node::PushSubExpression( swq_expr_node *child )
137 :
138 : {
139 1252 : nSubExprCount++;
140 : papoSubExpr = (swq_expr_node **)
141 1252 : CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
142 :
143 1252 : papoSubExpr[nSubExprCount-1] = child;
144 1252 : }
145 :
146 : /************************************************************************/
147 : /* ReverseSubExpressions() */
148 : /************************************************************************/
149 :
150 93 : void swq_expr_node::ReverseSubExpressions()
151 :
152 : {
153 : int i;
154 164 : for( i = 0; i < nSubExprCount / 2; i++ )
155 : {
156 : swq_expr_node *temp;
157 :
158 71 : temp = papoSubExpr[i];
159 71 : papoSubExpr[i] = papoSubExpr[nSubExprCount - i - 1];
160 71 : papoSubExpr[nSubExprCount - i - 1] = temp;
161 : }
162 93 : }
163 :
164 : /************************************************************************/
165 : /* Check() */
166 : /* */
167 : /* Check argument types, etc. */
168 : /************************************************************************/
169 :
170 1517 : swq_field_type swq_expr_node::Check( swq_field_list *poFieldList )
171 :
172 : {
173 : /* -------------------------------------------------------------------- */
174 : /* If something is a string constant, we must check if it is */
175 : /* actually a reference to a field in which case we will */
176 : /* convert it into a column type. */
177 : /* -------------------------------------------------------------------- */
178 1517 : if( eNodeType == SNT_CONSTANT && field_type == SWQ_STRING )
179 : {
180 : int wrk_field_index, wrk_table_index;
181 : swq_field_type wrk_field_type;
182 :
183 : wrk_field_index =
184 : swq_identify_field( string_value, poFieldList,
185 201 : &wrk_field_type, &wrk_table_index );
186 :
187 201 : if( wrk_field_index >= 0 )
188 : {
189 10 : eNodeType = SNT_COLUMN;
190 10 : field_index = -1;
191 10 : table_index = -1;
192 : }
193 : }
194 :
195 : /* -------------------------------------------------------------------- */
196 : /* Otherwise we take constants literally. */
197 : /* -------------------------------------------------------------------- */
198 1517 : if( eNodeType == SNT_CONSTANT )
199 515 : return field_type;
200 :
201 : /* -------------------------------------------------------------------- */
202 : /* If this is intended to be a field definition, but has not */
203 : /* yet been looked up, we do so now. */
204 : /* -------------------------------------------------------------------- */
205 1002 : if( eNodeType == SNT_COLUMN && field_index == -1 )
206 : {
207 : field_index =
208 : swq_identify_field( string_value, poFieldList,
209 456 : &field_type, &table_index );
210 :
211 456 : if( field_index < 0 )
212 : {
213 : CPLError( CE_Failure, CPLE_AppDefined,
214 : "'%s' not recognised as an available field.",
215 3 : string_value );
216 :
217 3 : return SWQ_ERROR;
218 :
219 : }
220 : }
221 :
222 999 : if( eNodeType == SNT_COLUMN )
223 453 : return field_type;
224 :
225 : /* -------------------------------------------------------------------- */
226 : /* We are dealing with an operation - fetch the definition. */
227 : /* -------------------------------------------------------------------- */
228 : const swq_operation *poOp =
229 546 : swq_op_registrar::GetOperator((swq_op)nOperation);
230 :
231 546 : if( poOp == NULL )
232 : {
233 : CPLError( CE_Failure, CPLE_AppDefined,
234 : "Check(): Unable to find definition for operator %d.",
235 0 : nOperation );
236 0 : return SWQ_ERROR;
237 : }
238 :
239 : /* -------------------------------------------------------------------- */
240 : /* Check subexpressions first. */
241 : /* -------------------------------------------------------------------- */
242 : int i;
243 :
244 1637 : for( i = 0; i < nSubExprCount; i++ )
245 : {
246 1095 : if( papoSubExpr[i]->Check(poFieldList) == SWQ_ERROR )
247 4 : return SWQ_ERROR;
248 : }
249 :
250 : /* -------------------------------------------------------------------- */
251 : /* Check this node. */
252 : /* -------------------------------------------------------------------- */
253 542 : field_type = poOp->pfnChecker( this );
254 :
255 542 : return field_type;
256 : }
257 :
258 : /************************************************************************/
259 : /* Dump() */
260 : /************************************************************************/
261 :
262 0 : void swq_expr_node::Dump( FILE * fp, int depth )
263 :
264 : {
265 : char spaces[60];
266 : int i;
267 :
268 0 : for( i = 0; i < depth*2 && i < (int) sizeof(spaces); i++ )
269 0 : spaces[i] = ' ';
270 0 : spaces[i] = '\0';
271 :
272 0 : if( eNodeType == SNT_COLUMN )
273 : {
274 0 : fprintf( fp, "%s Field %d\n", spaces, field_index );
275 0 : return;
276 : }
277 :
278 0 : if( eNodeType == SNT_CONSTANT )
279 : {
280 0 : if( field_type == SWQ_INTEGER || field_type == SWQ_BOOLEAN )
281 0 : fprintf( fp, "%s %d\n", spaces, int_value );
282 0 : else if( field_type == SWQ_FLOAT )
283 0 : fprintf( fp, "%s %.15g\n", spaces, float_value );
284 : else
285 0 : fprintf( fp, "%s %s\n", spaces, string_value );
286 0 : return;
287 : }
288 :
289 0 : CPLAssert( eNodeType == SNT_OPERATION );
290 :
291 : const swq_operation *op_def =
292 0 : swq_op_registrar::GetOperator( (swq_op) nOperation );
293 :
294 0 : fprintf( fp, "%s%s\n", spaces, op_def->osName.c_str() );
295 :
296 0 : for( i = 0; i < nSubExprCount; i++ )
297 0 : papoSubExpr[i]->Dump( fp, depth+1 );
298 : }
299 :
300 : /************************************************************************/
301 : /* Quote() */
302 : /* */
303 : /* Add quoting necessary to unparse a string. */
304 : /************************************************************************/
305 :
306 18 : void swq_expr_node::Quote( CPLString &osTarget, char chQuote )
307 :
308 : {
309 18 : CPLString osNew;
310 : int i;
311 :
312 18 : osNew += chQuote;
313 :
314 162 : for( i = 0; i < (int) osTarget.size(); i++ )
315 : {
316 144 : if( osTarget[i] == chQuote )
317 : {
318 0 : osNew += chQuote;
319 0 : osNew += chQuote;
320 : }
321 : else
322 144 : osNew += osTarget[i];
323 : }
324 18 : osNew += chQuote;
325 :
326 18 : osTarget = osNew;
327 18 : }
328 :
329 : /************************************************************************/
330 : /* Unparse() */
331 : /************************************************************************/
332 :
333 188 : char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
334 :
335 : {
336 188 : CPLString osExpr;
337 :
338 : /* -------------------------------------------------------------------- */
339 : /* Handle constants. */
340 : /* -------------------------------------------------------------------- */
341 188 : if( eNodeType == SNT_CONSTANT )
342 : {
343 64 : if (is_null)
344 1 : return CPLStrdup("NULL");
345 :
346 71 : if( field_type == SWQ_INTEGER || field_type == SWQ_BOOLEAN )
347 8 : osExpr.Printf( "%d", int_value );
348 55 : else if( field_type == SWQ_FLOAT )
349 38 : osExpr.Printf( "%.15g", float_value );
350 : else
351 : {
352 17 : osExpr = string_value;
353 17 : Quote( osExpr );
354 : }
355 :
356 63 : return CPLStrdup(osExpr);
357 : }
358 :
359 : /* -------------------------------------------------------------------- */
360 : /* Handle columns. */
361 : /* -------------------------------------------------------------------- */
362 124 : if( eNodeType == SNT_COLUMN )
363 : {
364 56 : if( field_index != -1
365 : && table_index < field_list->table_count
366 : && table_index > 0 )
367 : osExpr.Printf( "%s.%s",
368 0 : field_list->table_defs[table_index].table_name,
369 0 : field_list->names[field_index] );
370 56 : else if( field_index != -1 )
371 56 : osExpr.Printf( "%s", field_list->names[field_index] );
372 :
373 :
374 456 : for( int i = 0; i < (int) osExpr.size(); i++ )
375 : {
376 401 : char ch = osExpr[i];
377 401 : if (!(isalnum((int)ch) || ch == '_'))
378 : {
379 1 : Quote( osExpr, chColumnQuote );
380 1 : return CPLStrdup(osExpr.c_str());
381 : }
382 : }
383 :
384 55 : if (swq_is_reserved_keyword(osExpr))
385 : {
386 0 : Quote( osExpr, chColumnQuote );
387 0 : return CPLStrdup(osExpr.c_str());
388 : }
389 :
390 : /* The string is just alphanum and not a reserved SQL keyword, no needs to quote and escape */
391 55 : return CPLStrdup(osExpr.c_str());
392 : }
393 :
394 : /* -------------------------------------------------------------------- */
395 : /* Operation - start by unparsing all the subexpressions. */
396 : /* -------------------------------------------------------------------- */
397 68 : std::vector<char*> apszSubExpr;
398 : int i;
399 :
400 204 : for( i = 0; i < nSubExprCount; i++ )
401 136 : apszSubExpr.push_back( papoSubExpr[i]->Unparse(field_list, chColumnQuote) );
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* Put things together in a fashion depending on the operator. */
405 : /* -------------------------------------------------------------------- */
406 : const swq_operation *poOp =
407 68 : swq_op_registrar::GetOperator( (swq_op) nOperation );
408 :
409 68 : if( poOp == NULL )
410 : {
411 0 : CPLAssert( FALSE );
412 0 : return CPLStrdup("");
413 : }
414 :
415 68 : switch( nOperation )
416 : {
417 : // binary infix operators.
418 : case SWQ_OR:
419 : case SWQ_AND:
420 : case SWQ_EQ:
421 : case SWQ_NE:
422 : case SWQ_GT:
423 : case SWQ_LT:
424 : case SWQ_GE:
425 : case SWQ_LE:
426 : case SWQ_LIKE:
427 : case SWQ_ADD:
428 : case SWQ_SUBTRACT:
429 : case SWQ_MULTIPLY:
430 : case SWQ_DIVIDE:
431 : case SWQ_MODULUS:
432 48 : CPLAssert( nSubExprCount >= 2 );
433 96 : if (papoSubExpr[0]->eNodeType == SNT_COLUMN ||
434 5 : papoSubExpr[0]->eNodeType == SNT_CONSTANT)
435 : {
436 43 : osExpr += apszSubExpr[0];
437 : }
438 : else
439 : {
440 5 : osExpr += "(";
441 5 : osExpr += apszSubExpr[0];
442 5 : osExpr += ")";
443 : }
444 48 : osExpr += " ";
445 48 : osExpr += poOp->osName;
446 48 : osExpr += " ";
447 139 : if (papoSubExpr[1]->eNodeType == SNT_COLUMN ||
448 48 : papoSubExpr[1]->eNodeType == SNT_CONSTANT)
449 : {
450 43 : osExpr += apszSubExpr[1];
451 : }
452 : else
453 : {
454 5 : osExpr += "(";
455 5 : osExpr += apszSubExpr[1];
456 5 : osExpr += ")";
457 : }
458 48 : if( nOperation == SWQ_LIKE && nSubExprCount == 3 )
459 1 : osExpr += CPLSPrintf( " ESCAPE (%s)", apszSubExpr[2] );
460 48 : break;
461 :
462 : case SWQ_NOT:
463 6 : CPLAssert( nSubExprCount == 1 );
464 6 : osExpr.Printf( "NOT (%s)", apszSubExpr[0] );
465 6 : break;
466 :
467 : case SWQ_ISNULL:
468 4 : CPLAssert( nSubExprCount == 1 );
469 4 : osExpr.Printf( "%s IS NULL", apszSubExpr[0] );
470 4 : break;
471 :
472 : case SWQ_IN:
473 8 : osExpr.Printf( "%s IN (", apszSubExpr[0] );
474 23 : for( i = 1; i < nSubExprCount; i++ )
475 : {
476 15 : if( i > 1 )
477 7 : osExpr += ",";
478 15 : osExpr += "(";
479 15 : osExpr += apszSubExpr[i];
480 15 : osExpr += ")";
481 : }
482 8 : osExpr += ")";
483 8 : break;
484 :
485 : case SWQ_BETWEEN:
486 2 : CPLAssert( nSubExprCount == 3 );
487 : osExpr.Printf( "%s %s (%s) AND (%s)",
488 : apszSubExpr[0],
489 : poOp->osName.c_str(),
490 : apszSubExpr[1],
491 2 : apszSubExpr[2] );
492 2 : break;
493 :
494 : default: // function style.
495 0 : osExpr.Printf( "%s(", poOp->osName.c_str() );
496 0 : for( i = 0; i < nSubExprCount; i++ )
497 : {
498 0 : if( i > 0 )
499 0 : osExpr += ",";
500 0 : osExpr += "(";
501 0 : osExpr += apszSubExpr[i];
502 0 : osExpr += ")";
503 : }
504 0 : osExpr += ")";
505 : break;
506 : }
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* cleanup subexpressions. */
510 : /* -------------------------------------------------------------------- */
511 204 : for( i = 0; i < nSubExprCount; i++ )
512 136 : CPLFree( apszSubExpr[i] );
513 :
514 68 : return CPLStrdup( osExpr.c_str() );
515 : }
516 :
517 : /************************************************************************/
518 : /* Evaluate() */
519 : /************************************************************************/
520 :
521 911254 : swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
522 : void *pRecord )
523 :
524 : {
525 911254 : swq_expr_node *poRetNode = NULL;
526 :
527 : /* -------------------------------------------------------------------- */
528 : /* Duplicate ourselves if we are already a constant. */
529 : /* -------------------------------------------------------------------- */
530 911254 : if( eNodeType == SNT_CONSTANT )
531 : {
532 19 : poRetNode = new swq_expr_node();
533 :
534 19 : poRetNode->eNodeType = SNT_CONSTANT;
535 19 : poRetNode->field_type = field_type;
536 19 : poRetNode->int_value = int_value;
537 19 : poRetNode->float_value = float_value;
538 :
539 19 : if( string_value )
540 9 : poRetNode->string_value = CPLStrdup(string_value);
541 : else
542 10 : poRetNode->string_value = NULL;
543 :
544 19 : poRetNode->is_null = is_null;
545 :
546 19 : return poRetNode;
547 : }
548 :
549 : /* -------------------------------------------------------------------- */
550 : /* If this is a field value from a record, fetch and return it. */
551 : /* -------------------------------------------------------------------- */
552 911235 : if( eNodeType == SNT_COLUMN )
553 : {
554 455411 : return pfnFetcher( this, pRecord );
555 : }
556 :
557 : /* -------------------------------------------------------------------- */
558 : /* This is an operation, collect the arguments keeping track of */
559 : /* which we will need to free. */
560 : /* -------------------------------------------------------------------- */
561 455824 : std::vector<swq_expr_node*> apoValues;
562 455824 : std::vector<int> anValueNeedsFree;
563 455824 : int i, bError = FALSE;
564 :
565 1367537 : for( i = 0; i < nSubExprCount && !bError; i++ )
566 : {
567 911713 : if( papoSubExpr[i]->eNodeType == SNT_CONSTANT )
568 : {
569 : // avoid duplication.
570 455780 : apoValues.push_back( papoSubExpr[i] );
571 455780 : anValueNeedsFree.push_back( FALSE );
572 : }
573 : else
574 : {
575 455933 : apoValues.push_back(papoSubExpr[i]->Evaluate(pfnFetcher,pRecord));
576 455933 : anValueNeedsFree.push_back( TRUE );
577 : }
578 : }
579 :
580 : /* -------------------------------------------------------------------- */
581 : /* Fetch the operator definition and function. */
582 : /* -------------------------------------------------------------------- */
583 455824 : if( !bError )
584 : {
585 : const swq_operation *poOp =
586 455824 : swq_op_registrar::GetOperator( (swq_op) nOperation );
587 :
588 455824 : poRetNode = poOp->pfnEvaluator( this, &(apoValues[0]) );
589 : }
590 :
591 : /* -------------------------------------------------------------------- */
592 : /* Cleanup */
593 : /* -------------------------------------------------------------------- */
594 1367537 : for( i = 0; i < (int) apoValues.size(); i++ )
595 : {
596 911713 : if( anValueNeedsFree[i] )
597 455933 : delete apoValues[i];
598 : }
599 :
600 455824 : return poRetNode;
601 : }
|