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 467 : swq_expr_node::swq_expr_node()
40 :
41 : {
42 467 : Initialize();
43 467 : }
44 :
45 : /************************************************************************/
46 : /* swq_expr_node(int) */
47 : /************************************************************************/
48 :
49 679144 : swq_expr_node::swq_expr_node( int nValueIn )
50 :
51 : {
52 679144 : Initialize();
53 :
54 679144 : int_value = nValueIn;
55 679144 : }
56 :
57 : /************************************************************************/
58 : /* swq_expr_node(double) */
59 : /************************************************************************/
60 :
61 3206 : swq_expr_node::swq_expr_node( double dfValueIn )
62 :
63 : {
64 3206 : Initialize();
65 :
66 3206 : field_type = SWQ_FLOAT;
67 3206 : float_value = dfValueIn;
68 3206 : }
69 :
70 : /************************************************************************/
71 : /* swq_expr_node(const char*) */
72 : /************************************************************************/
73 :
74 379271 : swq_expr_node::swq_expr_node( const char *pszValueIn )
75 :
76 : {
77 379271 : Initialize();
78 :
79 379271 : field_type = SWQ_STRING;
80 379271 : string_value = CPLStrdup( pszValueIn ? pszValueIn : "" );
81 379271 : is_null = pszValueIn == NULL;
82 379271 : }
83 :
84 : /************************************************************************/
85 : /* swq_expr_node(swq_op) */
86 : /************************************************************************/
87 :
88 1990 : swq_expr_node::swq_expr_node( swq_op eOp )
89 :
90 : {
91 1990 : Initialize();
92 :
93 1990 : eNodeType = SNT_OPERATION;
94 :
95 1990 : nOperation = (int) eOp;
96 1990 : nSubExprCount = 0;
97 1990 : papoSubExpr = NULL;
98 1990 : }
99 :
100 : /************************************************************************/
101 : /* Initialize() */
102 : /************************************************************************/
103 :
104 1064078 : void swq_expr_node::Initialize()
105 :
106 : {
107 1064078 : eNodeType = SNT_CONSTANT;
108 1064078 : field_type = SWQ_INTEGER;
109 1064078 : int_value = 0;
110 :
111 1064078 : is_null = FALSE;
112 1064078 : string_value = NULL;
113 1064078 : papoSubExpr = NULL;
114 1064078 : nSubExprCount = 0;
115 1064078 : }
116 :
117 : /************************************************************************/
118 : /* ~swq_expr_node() */
119 : /************************************************************************/
120 :
121 1064078 : swq_expr_node::~swq_expr_node()
122 :
123 : {
124 1064078 : CPLFree( string_value );
125 :
126 : int i;
127 1067820 : for( i = 0; i < nSubExprCount; i++ )
128 3742 : delete papoSubExpr[i];
129 1064078 : CPLFree( papoSubExpr );
130 1064078 : }
131 :
132 : /************************************************************************/
133 : /* PushSubExpression() */
134 : /************************************************************************/
135 :
136 3876 : void swq_expr_node::PushSubExpression( swq_expr_node *child )
137 :
138 : {
139 3876 : nSubExprCount++;
140 : papoSubExpr = (swq_expr_node **)
141 3876 : CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
142 :
143 3876 : papoSubExpr[nSubExprCount-1] = child;
144 3876 : }
145 :
146 : /************************************************************************/
147 : /* ReverseSubExpressions() */
148 : /************************************************************************/
149 :
150 119 : void swq_expr_node::ReverseSubExpressions()
151 :
152 : {
153 : int i;
154 215 : for( i = 0; i < nSubExprCount / 2; i++ )
155 : {
156 : swq_expr_node *temp;
157 :
158 96 : temp = papoSubExpr[i];
159 96 : papoSubExpr[i] = papoSubExpr[nSubExprCount - i - 1];
160 96 : papoSubExpr[nSubExprCount - i - 1] = temp;
161 : }
162 119 : }
163 :
164 : /************************************************************************/
165 : /* Check() */
166 : /* */
167 : /* Check argument types, etc. */
168 : /************************************************************************/
169 :
170 4848 : 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 4848 : 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 457 : &wrk_field_type, &wrk_table_index );
186 :
187 457 : if( wrk_field_index >= 0 )
188 : {
189 18 : eNodeType = SNT_COLUMN;
190 18 : field_index = -1;
191 18 : table_index = -1;
192 : }
193 : }
194 :
195 : /* -------------------------------------------------------------------- */
196 : /* Otherwise we take constants literally. */
197 : /* -------------------------------------------------------------------- */
198 4848 : if( eNodeType == SNT_CONSTANT )
199 1969 : 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 2879 : if( eNodeType == SNT_COLUMN && field_index == -1 )
206 : {
207 : field_index =
208 : swq_identify_field( string_value, poFieldList,
209 1060 : &field_type, &table_index );
210 :
211 1060 : 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 2876 : if( eNodeType == SNT_COLUMN )
223 1057 : return field_type;
224 :
225 : /* -------------------------------------------------------------------- */
226 : /* We are dealing with an operation - fetch the definition. */
227 : /* -------------------------------------------------------------------- */
228 : const swq_operation *poOp =
229 1819 : swq_op_registrar::GetOperator((swq_op)nOperation);
230 :
231 1819 : 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 5484 : for( i = 0; i < nSubExprCount; i++ )
245 : {
246 3669 : if( papoSubExpr[i]->Check(poFieldList) == SWQ_ERROR )
247 4 : return SWQ_ERROR;
248 : }
249 :
250 : /* -------------------------------------------------------------------- */
251 : /* Check this node. */
252 : /* -------------------------------------------------------------------- */
253 1815 : field_type = poOp->pfnChecker( this );
254 :
255 1815 : 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 91 : void swq_expr_node::Quote( CPLString &osTarget, char chQuote )
307 :
308 : {
309 91 : CPLString osNew;
310 : int i;
311 :
312 91 : osNew += chQuote;
313 :
314 363 : for( i = 0; i < (int) osTarget.size(); i++ )
315 : {
316 272 : if( osTarget[i] == chQuote )
317 : {
318 0 : osNew += chQuote;
319 0 : osNew += chQuote;
320 : }
321 : else
322 272 : osNew += osTarget[i];
323 : }
324 91 : osNew += chQuote;
325 :
326 91 : osTarget = osNew;
327 91 : }
328 :
329 : /************************************************************************/
330 : /* Unparse() */
331 : /************************************************************************/
332 :
333 1317 : char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
334 :
335 : {
336 1317 : CPLString osExpr;
337 :
338 : /* -------------------------------------------------------------------- */
339 : /* Handle constants. */
340 : /* -------------------------------------------------------------------- */
341 1317 : if( eNodeType == SNT_CONSTANT )
342 : {
343 615 : if (is_null)
344 6 : return CPLStrdup("NULL");
345 :
346 982 : if( field_type == SWQ_INTEGER || field_type == SWQ_BOOLEAN )
347 373 : osExpr.Printf( "%d", int_value );
348 236 : else if( field_type == SWQ_FLOAT )
349 : {
350 146 : osExpr.Printf( "%.15g", float_value );
351 : /* Make sure this is interpreted as a floating point value */
352 : /* and not as an integer later */
353 146 : if (strchr(osExpr, '.') == NULL && strchr(osExpr, 'e') == NULL &&
354 : strchr(osExpr, 'E') == NULL)
355 145 : osExpr += '.';
356 : }
357 : else
358 : {
359 90 : osExpr = string_value;
360 90 : Quote( osExpr );
361 : }
362 :
363 609 : return CPLStrdup(osExpr);
364 : }
365 :
366 : /* -------------------------------------------------------------------- */
367 : /* Handle columns. */
368 : /* -------------------------------------------------------------------- */
369 702 : if( eNodeType == SNT_COLUMN )
370 : {
371 190 : 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 190 : else if( field_index != -1 )
378 190 : osExpr.Printf( "%s", field_list->names[field_index] );
379 :
380 :
381 1024 : for( int i = 0; i < (int) osExpr.size(); i++ )
382 : {
383 835 : char ch = osExpr[i];
384 835 : if (!(isalnum((int)ch) || ch == '_'))
385 : {
386 1 : Quote( osExpr, chColumnQuote );
387 1 : return CPLStrdup(osExpr.c_str());
388 : }
389 : }
390 :
391 189 : 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 189 : return CPLStrdup(osExpr.c_str());
399 : }
400 :
401 : /* -------------------------------------------------------------------- */
402 : /* Operation - start by unparsing all the subexpressions. */
403 : /* -------------------------------------------------------------------- */
404 512 : std::vector<char*> apszSubExpr;
405 : int i;
406 :
407 1552 : for( i = 0; i < nSubExprCount; i++ )
408 1040 : 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 512 : swq_op_registrar::GetOperator( (swq_op) nOperation );
415 :
416 512 : if( poOp == NULL )
417 : {
418 0 : CPLAssert( FALSE );
419 0 : return CPLStrdup("");
420 : }
421 :
422 512 : 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 459 : CPLAssert( nSubExprCount >= 2 );
440 1093 : if (papoSubExpr[0]->eNodeType == SNT_COLUMN ||
441 283 : papoSubExpr[0]->eNodeType == SNT_CONSTANT)
442 : {
443 351 : osExpr += apszSubExpr[0];
444 : }
445 : else
446 : {
447 108 : osExpr += "(";
448 108 : osExpr += apszSubExpr[0];
449 108 : osExpr += ")";
450 : }
451 459 : osExpr += " ";
452 459 : osExpr += poOp->osName;
453 459 : osExpr += " ";
454 1263 : if (papoSubExpr[1]->eNodeType == SNT_COLUMN ||
455 459 : papoSubExpr[1]->eNodeType == SNT_CONSTANT)
456 : {
457 345 : osExpr += apszSubExpr[1];
458 : }
459 : else
460 : {
461 114 : osExpr += "(";
462 114 : osExpr += apszSubExpr[1];
463 114 : osExpr += ")";
464 : }
465 459 : if( nOperation == SWQ_LIKE && nSubExprCount == 3 )
466 1 : osExpr += CPLSPrintf( " ESCAPE (%s)", apszSubExpr[2] );
467 459 : break;
468 :
469 : case SWQ_NOT:
470 9 : CPLAssert( nSubExprCount == 1 );
471 9 : osExpr.Printf( "NOT (%s)", apszSubExpr[0] );
472 9 : break;
473 :
474 : case SWQ_ISNULL:
475 7 : CPLAssert( nSubExprCount == 1 );
476 7 : osExpr.Printf( "%s IS NULL", apszSubExpr[0] );
477 7 : break;
478 :
479 : case SWQ_IN:
480 14 : osExpr.Printf( "%s IN (", apszSubExpr[0] );
481 41 : for( i = 1; i < nSubExprCount; i++ )
482 : {
483 27 : if( i > 1 )
484 13 : osExpr += ",";
485 27 : osExpr += "(";
486 27 : osExpr += apszSubExpr[i];
487 27 : osExpr += ")";
488 : }
489 14 : osExpr += ")";
490 14 : break;
491 :
492 : case SWQ_BETWEEN:
493 17 : CPLAssert( nSubExprCount == 3 );
494 : osExpr.Printf( "%s %s (%s) AND (%s)",
495 : apszSubExpr[0],
496 : poOp->osName.c_str(),
497 : apszSubExpr[1],
498 17 : apszSubExpr[2] );
499 17 : break;
500 :
501 : case SWQ_CAST:
502 5 : osExpr = "CAST(";
503 16 : for( i = 0; i < nSubExprCount; i++ )
504 : {
505 11 : if( i == 1 )
506 5 : osExpr += " AS ";
507 6 : else if( i > 2 )
508 0 : osExpr += ", ";
509 :
510 11 : int nLen = (int)strlen(apszSubExpr[i]);
511 21 : if( i != 1 ||
512 10 : !(apszSubExpr[i][0] == '\'' && nLen > 2 && apszSubExpr[i][nLen-1] == '\'') )
513 6 : osExpr += apszSubExpr[i];
514 : else
515 : {
516 5 : apszSubExpr[i][nLen-1] = '\0';
517 5 : osExpr += apszSubExpr[i] + 1;
518 : }
519 :
520 12 : if( i == 1 && nSubExprCount > 2)
521 1 : osExpr += "(";
522 10 : else if (i > 1 && i == nSubExprCount - 1)
523 1 : osExpr += ")";
524 : }
525 5 : osExpr += ")";
526 5 : break;
527 :
528 : default: // function style.
529 1 : osExpr.Printf( "%s(", poOp->osName.c_str() );
530 3 : for( i = 0; i < nSubExprCount; i++ )
531 : {
532 2 : if( i > 0 )
533 1 : osExpr += ",";
534 2 : osExpr += "(";
535 2 : osExpr += apszSubExpr[i];
536 2 : osExpr += ")";
537 : }
538 1 : osExpr += ")";
539 : break;
540 : }
541 :
542 : /* -------------------------------------------------------------------- */
543 : /* cleanup subexpressions. */
544 : /* -------------------------------------------------------------------- */
545 1552 : for( i = 0; i < nSubExprCount; i++ )
546 1040 : CPLFree( apszSubExpr[i] );
547 :
548 512 : return CPLStrdup( osExpr.c_str() );
549 : }
550 :
551 : /************************************************************************/
552 : /* Evaluate() */
553 : /************************************************************************/
554 :
555 1055908 : swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
556 : void *pRecord )
557 :
558 : {
559 1055908 : swq_expr_node *poRetNode = NULL;
560 :
561 : /* -------------------------------------------------------------------- */
562 : /* Duplicate ourselves if we are already a constant. */
563 : /* -------------------------------------------------------------------- */
564 1055908 : if( eNodeType == SNT_CONSTANT )
565 : {
566 19 : poRetNode = new swq_expr_node();
567 :
568 19 : poRetNode->eNodeType = SNT_CONSTANT;
569 19 : poRetNode->field_type = field_type;
570 19 : poRetNode->int_value = int_value;
571 19 : poRetNode->float_value = float_value;
572 :
573 19 : if( string_value )
574 9 : poRetNode->string_value = CPLStrdup(string_value);
575 : else
576 10 : poRetNode->string_value = NULL;
577 :
578 19 : poRetNode->is_null = is_null;
579 :
580 19 : return poRetNode;
581 : }
582 :
583 : /* -------------------------------------------------------------------- */
584 : /* If this is a field value from a record, fetch and return it. */
585 : /* -------------------------------------------------------------------- */
586 1055889 : if( eNodeType == SNT_COLUMN )
587 : {
588 458563 : return pfnFetcher( this, pRecord );
589 : }
590 :
591 : /* -------------------------------------------------------------------- */
592 : /* This is an operation, collect the arguments keeping track of */
593 : /* which we will need to free. */
594 : /* -------------------------------------------------------------------- */
595 597326 : std::vector<swq_expr_node*> apoValues;
596 597326 : std::vector<int> anValueNeedsFree;
597 597326 : int i, bError = FALSE;
598 :
599 1792115 : for( i = 0; i < nSubExprCount && !bError; i++ )
600 : {
601 1194789 : if( papoSubExpr[i]->eNodeType == SNT_CONSTANT )
602 : {
603 : // avoid duplication.
604 733139 : apoValues.push_back( papoSubExpr[i] );
605 733139 : anValueNeedsFree.push_back( FALSE );
606 : }
607 : else
608 : {
609 461650 : apoValues.push_back(papoSubExpr[i]->Evaluate(pfnFetcher,pRecord));
610 461650 : anValueNeedsFree.push_back( TRUE );
611 : }
612 : }
613 :
614 : /* -------------------------------------------------------------------- */
615 : /* Fetch the operator definition and function. */
616 : /* -------------------------------------------------------------------- */
617 597326 : if( !bError )
618 : {
619 : const swq_operation *poOp =
620 597326 : swq_op_registrar::GetOperator( (swq_op) nOperation );
621 :
622 597326 : poRetNode = poOp->pfnEvaluator( this, &(apoValues[0]) );
623 : }
624 :
625 : /* -------------------------------------------------------------------- */
626 : /* Cleanup */
627 : /* -------------------------------------------------------------------- */
628 1792115 : for( i = 0; i < (int) apoValues.size(); i++ )
629 : {
630 1194789 : if( anValueNeedsFree[i] )
631 461650 : delete apoValues[i];
632 : }
633 :
634 597326 : return poRetNode;
635 : }
|