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 646 : swq_expr_node::swq_expr_node()
40 :
41 : {
42 646 : Initialize();
43 646 : }
44 :
45 : /************************************************************************/
46 : /* swq_expr_node(int) */
47 : /************************************************************************/
48 :
49 1078694 : swq_expr_node::swq_expr_node( int nValueIn )
50 :
51 : {
52 1078694 : Initialize();
53 :
54 1078694 : int_value = nValueIn;
55 1078694 : }
56 :
57 : /************************************************************************/
58 : /* swq_expr_node(double) */
59 : /************************************************************************/
60 :
61 5496 : swq_expr_node::swq_expr_node( double dfValueIn )
62 :
63 : {
64 5496 : Initialize();
65 :
66 5496 : field_type = SWQ_FLOAT;
67 5496 : float_value = dfValueIn;
68 5496 : }
69 :
70 : /************************************************************************/
71 : /* swq_expr_node(const char*) */
72 : /************************************************************************/
73 :
74 756736 : swq_expr_node::swq_expr_node( const char *pszValueIn )
75 :
76 : {
77 756736 : Initialize();
78 :
79 756736 : field_type = SWQ_STRING;
80 756736 : string_value = CPLStrdup( pszValueIn ? pszValueIn : "" );
81 756736 : is_null = pszValueIn == NULL;
82 756736 : }
83 :
84 : /************************************************************************/
85 : /* swq_expr_node(swq_op) */
86 : /************************************************************************/
87 :
88 2784 : swq_expr_node::swq_expr_node( swq_op eOp )
89 :
90 : {
91 2784 : Initialize();
92 :
93 2784 : eNodeType = SNT_OPERATION;
94 :
95 2784 : nOperation = (int) eOp;
96 2784 : nSubExprCount = 0;
97 2784 : papoSubExpr = NULL;
98 2784 : }
99 :
100 : /************************************************************************/
101 : /* Initialize() */
102 : /************************************************************************/
103 :
104 1844356 : void swq_expr_node::Initialize()
105 :
106 : {
107 1844356 : eNodeType = SNT_CONSTANT;
108 1844356 : field_type = SWQ_INTEGER;
109 1844356 : int_value = 0;
110 :
111 1844356 : is_null = FALSE;
112 1844356 : string_value = NULL;
113 1844356 : papoSubExpr = NULL;
114 1844356 : nSubExprCount = 0;
115 1844356 : }
116 :
117 : /************************************************************************/
118 : /* ~swq_expr_node() */
119 : /************************************************************************/
120 :
121 1844356 : swq_expr_node::~swq_expr_node()
122 :
123 : {
124 1844356 : CPLFree( string_value );
125 :
126 : int i;
127 1849512 : for( i = 0; i < nSubExprCount; i++ )
128 5156 : delete papoSubExpr[i];
129 1844356 : CPLFree( papoSubExpr );
130 1844356 : }
131 :
132 : /************************************************************************/
133 : /* PushSubExpression() */
134 : /************************************************************************/
135 :
136 5408 : void swq_expr_node::PushSubExpression( swq_expr_node *child )
137 :
138 : {
139 5408 : nSubExprCount++;
140 : papoSubExpr = (swq_expr_node **)
141 5408 : CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
142 :
143 5408 : papoSubExpr[nSubExprCount-1] = child;
144 5408 : }
145 :
146 : /************************************************************************/
147 : /* ReverseSubExpressions() */
148 : /************************************************************************/
149 :
150 214 : void swq_expr_node::ReverseSubExpressions()
151 :
152 : {
153 : int i;
154 382 : for( i = 0; i < nSubExprCount / 2; i++ )
155 : {
156 : swq_expr_node *temp;
157 :
158 168 : temp = papoSubExpr[i];
159 168 : papoSubExpr[i] = papoSubExpr[nSubExprCount - i - 1];
160 168 : papoSubExpr[nSubExprCount - i - 1] = temp;
161 : }
162 214 : }
163 :
164 : /************************************************************************/
165 : /* Check() */
166 : /* */
167 : /* Check argument types, etc. */
168 : /************************************************************************/
169 :
170 6484 : 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 6484 : 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 688 : &wrk_field_type, &wrk_table_index );
186 :
187 688 : if( wrk_field_index >= 0 )
188 : {
189 20 : eNodeType = SNT_COLUMN;
190 20 : field_index = -1;
191 20 : table_index = -1;
192 : }
193 : }
194 :
195 : /* -------------------------------------------------------------------- */
196 : /* Otherwise we take constants literally. */
197 : /* -------------------------------------------------------------------- */
198 6484 : if( eNodeType == SNT_CONSTANT )
199 2544 : 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 3940 : if( eNodeType == SNT_COLUMN && field_index == -1 )
206 : {
207 : field_index =
208 : swq_identify_field( string_value, poFieldList,
209 1460 : &field_type, &table_index );
210 :
211 1460 : if( field_index < 0 )
212 : {
213 : CPLError( CE_Failure, CPLE_AppDefined,
214 : "'%s' not recognised as an available field.",
215 6 : string_value );
216 :
217 6 : return SWQ_ERROR;
218 :
219 : }
220 : }
221 :
222 3934 : if( eNodeType == SNT_COLUMN )
223 1454 : return field_type;
224 :
225 : /* -------------------------------------------------------------------- */
226 : /* We are dealing with an operation - fetch the definition. */
227 : /* -------------------------------------------------------------------- */
228 : const swq_operation *poOp =
229 2480 : swq_op_registrar::GetOperator((swq_op)nOperation);
230 :
231 2480 : 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 7526 : for( i = 0; i < nSubExprCount; i++ )
245 : {
246 5054 : if( papoSubExpr[i]->Check(poFieldList) == SWQ_ERROR )
247 8 : return SWQ_ERROR;
248 : }
249 :
250 : /* -------------------------------------------------------------------- */
251 : /* Check this node. */
252 : /* -------------------------------------------------------------------- */
253 2472 : field_type = poOp->pfnChecker( this );
254 :
255 2472 : 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 150 : void swq_expr_node::Quote( CPLString &osTarget, char chQuote )
307 :
308 : {
309 150 : CPLString osNew;
310 : int i;
311 :
312 150 : osNew += chQuote;
313 :
314 552 : for( i = 0; i < (int) osTarget.size(); i++ )
315 : {
316 402 : if( osTarget[i] == chQuote )
317 : {
318 0 : osNew += chQuote;
319 0 : osNew += chQuote;
320 : }
321 : else
322 402 : osNew += osTarget[i];
323 : }
324 150 : osNew += chQuote;
325 :
326 150 : osTarget = osNew;
327 150 : }
328 :
329 : /************************************************************************/
330 : /* Unparse() */
331 : /************************************************************************/
332 :
333 1924 : char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
334 :
335 : {
336 1924 : CPLString osExpr;
337 :
338 : /* -------------------------------------------------------------------- */
339 : /* Handle constants. */
340 : /* -------------------------------------------------------------------- */
341 1924 : if( eNodeType == SNT_CONSTANT )
342 : {
343 806 : if (is_null)
344 2 : return CPLStrdup("NULL");
345 :
346 1170 : if( field_type == SWQ_INTEGER || field_type == SWQ_BOOLEAN )
347 366 : osExpr.Printf( "%d", int_value );
348 438 : else if( field_type == SWQ_FLOAT )
349 : {
350 290 : osExpr.Printf( "%.15g", float_value );
351 : /* Make sure this is interpreted as a floating point value */
352 : /* and not as an integer later */
353 290 : if (strchr(osExpr, '.') == NULL && strchr(osExpr, 'e') == NULL &&
354 : strchr(osExpr, 'E') == NULL)
355 288 : osExpr += '.';
356 : }
357 : else
358 : {
359 148 : osExpr = string_value;
360 148 : Quote( osExpr );
361 : }
362 :
363 804 : return CPLStrdup(osExpr);
364 : }
365 :
366 : /* -------------------------------------------------------------------- */
367 : /* Handle columns. */
368 : /* -------------------------------------------------------------------- */
369 1118 : if( eNodeType == SNT_COLUMN )
370 : {
371 348 : if( field_index != -1
372 : && table_index < field_list->table_count
373 : && table_index > 0 )
374 : osExpr.Printf( "%s.%s",
375 0 : field_list->table_defs[table_index].table_name,
376 0 : field_list->names[field_index] );
377 348 : else if( field_index != -1 )
378 348 : osExpr.Printf( "%s", field_list->names[field_index] );
379 :
380 :
381 1832 : for( int i = 0; i < (int) osExpr.size(); i++ )
382 : {
383 1486 : char ch = osExpr[i];
384 1486 : if (!(isalnum((int)ch) || ch == '_'))
385 : {
386 2 : Quote( osExpr, chColumnQuote );
387 2 : return CPLStrdup(osExpr.c_str());
388 : }
389 : }
390 :
391 346 : if (swq_is_reserved_keyword(osExpr))
392 : {
393 0 : Quote( osExpr, chColumnQuote );
394 0 : return CPLStrdup(osExpr.c_str());
395 : }
396 :
397 : /* The string is just alphanum and not a reserved SQL keyword, no needs to quote and escape */
398 346 : return CPLStrdup(osExpr.c_str());
399 : }
400 :
401 : /* -------------------------------------------------------------------- */
402 : /* Operation - start by unparsing all the subexpressions. */
403 : /* -------------------------------------------------------------------- */
404 770 : std::vector<char*> apszSubExpr;
405 : int i;
406 :
407 2352 : for( i = 0; i < nSubExprCount; i++ )
408 1582 : apszSubExpr.push_back( papoSubExpr[i]->Unparse(field_list, chColumnQuote) );
409 :
410 : /* -------------------------------------------------------------------- */
411 : /* Put things together in a fashion depending on the operator. */
412 : /* -------------------------------------------------------------------- */
413 : const swq_operation *poOp =
414 770 : swq_op_registrar::GetOperator( (swq_op) nOperation );
415 :
416 770 : if( poOp == NULL )
417 : {
418 0 : CPLAssert( FALSE );
419 0 : return CPLStrdup("");
420 : }
421 :
422 770 : switch( nOperation )
423 : {
424 : // binary infix operators.
425 : case SWQ_OR:
426 : case SWQ_AND:
427 : case SWQ_EQ:
428 : case SWQ_NE:
429 : case SWQ_GT:
430 : case SWQ_LT:
431 : case SWQ_GE:
432 : case SWQ_LE:
433 : case SWQ_LIKE:
434 : case SWQ_ADD:
435 : case SWQ_SUBTRACT:
436 : case SWQ_MULTIPLY:
437 : case SWQ_DIVIDE:
438 : case SWQ_MODULUS:
439 688 : CPLAssert( nSubExprCount >= 2 );
440 1534 : if (papoSubExpr[0]->eNodeType == SNT_COLUMN ||
441 366 : papoSubExpr[0]->eNodeType == SNT_CONSTANT)
442 : {
443 480 : osExpr += apszSubExpr[0];
444 : }
445 : else
446 : {
447 208 : osExpr += "(";
448 208 : osExpr += apszSubExpr[0];
449 208 : osExpr += ")";
450 : }
451 688 : osExpr += " ";
452 688 : osExpr += poOp->osName;
453 688 : osExpr += " ";
454 1856 : if (papoSubExpr[1]->eNodeType == SNT_COLUMN ||
455 688 : papoSubExpr[1]->eNodeType == SNT_CONSTANT)
456 : {
457 480 : osExpr += apszSubExpr[1];
458 : }
459 : else
460 : {
461 208 : osExpr += "(";
462 208 : osExpr += apszSubExpr[1];
463 208 : osExpr += ")";
464 : }
465 688 : if( nOperation == SWQ_LIKE && nSubExprCount == 3 )
466 2 : osExpr += CPLSPrintf( " ESCAPE (%s)", apszSubExpr[2] );
467 688 : break;
468 :
469 : case SWQ_NOT:
470 12 : CPLAssert( nSubExprCount == 1 );
471 12 : osExpr.Printf( "NOT (%s)", apszSubExpr[0] );
472 12 : break;
473 :
474 : case SWQ_ISNULL:
475 8 : CPLAssert( nSubExprCount == 1 );
476 8 : osExpr.Printf( "%s IS NULL", apszSubExpr[0] );
477 8 : break;
478 :
479 : case SWQ_IN:
480 28 : osExpr.Printf( "%s IN (", apszSubExpr[0] );
481 82 : for( i = 1; i < nSubExprCount; i++ )
482 : {
483 54 : if( i > 1 )
484 26 : osExpr += ",";
485 54 : osExpr += "(";
486 54 : osExpr += apszSubExpr[i];
487 54 : osExpr += ")";
488 : }
489 28 : osExpr += ")";
490 28 : break;
491 :
492 : case SWQ_BETWEEN:
493 34 : CPLAssert( nSubExprCount == 3 );
494 : osExpr.Printf( "%s %s (%s) AND (%s)",
495 : apszSubExpr[0],
496 : poOp->osName.c_str(),
497 : apszSubExpr[1],
498 34 : apszSubExpr[2] );
499 34 : break;
500 :
501 : default: // function style.
502 0 : osExpr.Printf( "%s(", poOp->osName.c_str() );
503 0 : for( i = 0; i < nSubExprCount; i++ )
504 : {
505 0 : if( i > 0 )
506 0 : osExpr += ",";
507 0 : osExpr += "(";
508 0 : osExpr += apszSubExpr[i];
509 0 : osExpr += ")";
510 : }
511 0 : osExpr += ")";
512 : break;
513 : }
514 :
515 : /* -------------------------------------------------------------------- */
516 : /* cleanup subexpressions. */
517 : /* -------------------------------------------------------------------- */
518 2352 : for( i = 0; i < nSubExprCount; i++ )
519 1582 : CPLFree( apszSubExpr[i] );
520 :
521 770 : return CPLStrdup( osExpr.c_str() );
522 : }
523 :
524 : /************************************************************************/
525 : /* Evaluate() */
526 : /************************************************************************/
527 :
528 1832242 : swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
529 : void *pRecord )
530 :
531 : {
532 1832242 : swq_expr_node *poRetNode = NULL;
533 :
534 : /* -------------------------------------------------------------------- */
535 : /* Duplicate ourselves if we are already a constant. */
536 : /* -------------------------------------------------------------------- */
537 1832242 : if( eNodeType == SNT_CONSTANT )
538 : {
539 38 : poRetNode = new swq_expr_node();
540 :
541 38 : poRetNode->eNodeType = SNT_CONSTANT;
542 38 : poRetNode->field_type = field_type;
543 38 : poRetNode->int_value = int_value;
544 38 : poRetNode->float_value = float_value;
545 :
546 38 : if( string_value )
547 18 : poRetNode->string_value = CPLStrdup(string_value);
548 : else
549 20 : poRetNode->string_value = NULL;
550 :
551 38 : poRetNode->is_null = is_null;
552 :
553 38 : return poRetNode;
554 : }
555 :
556 : /* -------------------------------------------------------------------- */
557 : /* If this is a field value from a record, fetch and return it. */
558 : /* -------------------------------------------------------------------- */
559 1832204 : if( eNodeType == SNT_COLUMN )
560 : {
561 913688 : return pfnFetcher( this, pRecord );
562 : }
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* This is an operation, collect the arguments keeping track of */
566 : /* which we will need to free. */
567 : /* -------------------------------------------------------------------- */
568 918516 : std::vector<swq_expr_node*> apoValues;
569 918516 : std::vector<int> anValueNeedsFree;
570 918516 : int i, bError = FALSE;
571 :
572 2756098 : for( i = 0; i < nSubExprCount && !bError; i++ )
573 : {
574 1837582 : if( papoSubExpr[i]->eNodeType == SNT_CONSTANT )
575 : {
576 : // avoid duplication.
577 918926 : apoValues.push_back( papoSubExpr[i] );
578 918926 : anValueNeedsFree.push_back( FALSE );
579 : }
580 : else
581 : {
582 918656 : apoValues.push_back(papoSubExpr[i]->Evaluate(pfnFetcher,pRecord));
583 918656 : anValueNeedsFree.push_back( TRUE );
584 : }
585 : }
586 :
587 : /* -------------------------------------------------------------------- */
588 : /* Fetch the operator definition and function. */
589 : /* -------------------------------------------------------------------- */
590 918516 : if( !bError )
591 : {
592 : const swq_operation *poOp =
593 918516 : swq_op_registrar::GetOperator( (swq_op) nOperation );
594 :
595 918516 : poRetNode = poOp->pfnEvaluator( this, &(apoValues[0]) );
596 : }
597 :
598 : /* -------------------------------------------------------------------- */
599 : /* Cleanup */
600 : /* -------------------------------------------------------------------- */
601 2756098 : for( i = 0; i < (int) apoValues.size(); i++ )
602 : {
603 1837582 : if( anValueNeedsFree[i] )
604 918656 : delete apoValues[i];
605 : }
606 :
607 918516 : return poRetNode;
608 : }
|