1 : /******************************************************************************
2 : *
3 : * Component: OGR SQL Engine
4 : * Purpose: Implementation of SWQGeneralEvaluator and SWQGeneralChecker
5 : * functions used to represent functions during evaluation and
6 : * parsing.
7 : * Author: Frank Warmerdam <warmerdam@pobox.com>
8 : *
9 : ******************************************************************************
10 : * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_conv.h"
32 : #include "swq.h"
33 :
34 : /************************************************************************/
35 : /* swq_test_like() */
36 : /* */
37 : /* Does input match pattern? */
38 : /************************************************************************/
39 :
40 240 : int swq_test_like( const char *input, const char *pattern, char chEscape )
41 :
42 : {
43 240 : if( input == NULL || pattern == NULL )
44 0 : return 0;
45 :
46 950 : while( *input != '\0' )
47 : {
48 700 : if( *pattern == '\0' )
49 0 : return 0;
50 :
51 700 : else if( *pattern == chEscape )
52 : {
53 20 : pattern++;
54 20 : if( *pattern == '\0' )
55 0 : return 0;
56 20 : if( tolower(*pattern) != tolower(*input) )
57 0 : return 0;
58 : else
59 : {
60 20 : input++;
61 20 : pattern++;
62 : }
63 : }
64 :
65 680 : else if( *pattern == '_' )
66 : {
67 0 : input++;
68 0 : pattern++;
69 : }
70 680 : else if( *pattern == '%' )
71 : {
72 : int eat;
73 :
74 24 : if( pattern[1] == '\0' )
75 4 : return 1;
76 :
77 : /* try eating varying amounts of the input till we get a positive*/
78 174 : for( eat = 0; input[eat] != '\0'; eat++ )
79 : {
80 156 : if( swq_test_like(input+eat,pattern+1, chEscape) )
81 2 : return 1;
82 : }
83 :
84 18 : return 0;
85 : }
86 : else
87 : {
88 656 : if( tolower(*pattern) != tolower(*input) )
89 206 : return 0;
90 : else
91 : {
92 450 : input++;
93 450 : pattern++;
94 : }
95 : }
96 : }
97 :
98 10 : if( *pattern != '\0' && strcmp(pattern,"%") != 0 )
99 2 : return 0;
100 : else
101 8 : return 1;
102 : }
103 :
104 : /************************************************************************/
105 : /* SWQGeneralEvaluator() */
106 : /************************************************************************/
107 :
108 918264 : swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
109 : swq_expr_node **sub_node_values )
110 :
111 : {
112 918264 : swq_expr_node *poRet = NULL;
113 :
114 : /* -------------------------------------------------------------------- */
115 : /* Floating point operations. */
116 : /* -------------------------------------------------------------------- */
117 1836410 : if( sub_node_values[0]->field_type == SWQ_FLOAT
118 : || (node->nSubExprCount > 1
119 912176 : && sub_node_values[1]->field_type == SWQ_FLOAT) )
120 :
121 : {
122 5970 : poRet = new swq_expr_node(0);
123 5970 : poRet->field_type = node->field_type;
124 :
125 5970 : if( sub_node_values[0]->field_type == SWQ_INTEGER )
126 30 : sub_node_values[0]->float_value = sub_node_values[0]->int_value;
127 11940 : if( node->nSubExprCount > 1 &&
128 5970 : sub_node_values[1]->field_type == SWQ_INTEGER )
129 42 : sub_node_values[1]->float_value = sub_node_values[1]->int_value;
130 :
131 5970 : switch( (swq_op) node->nOperation )
132 : {
133 : case SWQ_EQ:
134 2048 : poRet->int_value = sub_node_values[0]->float_value
135 2048 : == sub_node_values[1]->float_value;
136 2048 : break;
137 :
138 : case SWQ_NE:
139 2396 : poRet->int_value = sub_node_values[0]->float_value
140 2396 : != sub_node_values[1]->float_value;
141 2396 : break;
142 :
143 : case SWQ_GT:
144 390 : poRet->int_value = sub_node_values[0]->float_value
145 390 : > sub_node_values[1]->float_value;
146 390 : break;
147 :
148 : case SWQ_LT:
149 330 : poRet->int_value = sub_node_values[0]->float_value
150 330 : < sub_node_values[1]->float_value;
151 330 : break;
152 :
153 : case SWQ_GE:
154 180 : poRet->int_value = sub_node_values[0]->float_value
155 180 : >= sub_node_values[1]->float_value;
156 180 : break;
157 :
158 : case SWQ_LE:
159 180 : poRet->int_value = sub_node_values[0]->float_value
160 180 : <= sub_node_values[1]->float_value;
161 180 : break;
162 :
163 : case SWQ_IN:
164 : {
165 : int i;
166 212 : poRet->int_value = 0;
167 510 : for( i = 1; i < node->nSubExprCount; i++ )
168 : {
169 716 : if( sub_node_values[0]->float_value
170 358 : == sub_node_values[i]->float_value )
171 : {
172 60 : poRet->int_value = 1;
173 60 : break;
174 : }
175 : }
176 : }
177 212 : break;
178 :
179 : case SWQ_BETWEEN:
180 140 : poRet->int_value = sub_node_values[0]->float_value
181 140 : >= sub_node_values[1]->float_value &&
182 116 : sub_node_values[0]->float_value
183 396 : <= sub_node_values[2]->float_value;
184 140 : break;
185 :
186 : case SWQ_ISNULL:
187 0 : poRet->int_value = sub_node_values[0]->is_null;
188 0 : break;
189 :
190 : case SWQ_ADD:
191 6 : poRet->float_value = sub_node_values[0]->float_value
192 6 : + sub_node_values[1]->float_value;
193 6 : break;
194 :
195 : case SWQ_SUBTRACT:
196 6 : poRet->float_value = sub_node_values[0]->float_value
197 6 : - sub_node_values[1]->float_value;
198 6 : break;
199 :
200 : case SWQ_MULTIPLY:
201 6 : poRet->float_value = sub_node_values[0]->float_value
202 6 : * sub_node_values[1]->float_value;
203 6 : break;
204 :
205 : case SWQ_DIVIDE:
206 30 : if( sub_node_values[1]->float_value == 0 )
207 0 : poRet->float_value = INT_MAX;
208 : else
209 30 : poRet->float_value = sub_node_values[0]->float_value
210 30 : / sub_node_values[1]->float_value;
211 30 : break;
212 :
213 : case SWQ_MODULUS:
214 : {
215 46 : int nRight = (int) sub_node_values[1]->float_value;
216 46 : poRet->field_type = SWQ_INTEGER;
217 46 : if (nRight == 0)
218 0 : poRet->int_value = INT_MAX;
219 : else
220 46 : poRet->int_value = ((int) sub_node_values[0]->float_value)
221 46 : % nRight;
222 46 : break;
223 : }
224 :
225 : default:
226 0 : CPLAssert( FALSE );
227 0 : delete poRet;
228 0 : poRet = NULL;
229 : break;
230 : }
231 : }
232 : /* -------------------------------------------------------------------- */
233 : /* integer/boolean operations. */
234 : /* -------------------------------------------------------------------- */
235 1826938 : else if( sub_node_values[0]->field_type == SWQ_INTEGER
236 753410 : || sub_node_values[0]->field_type == SWQ_BOOLEAN )
237 : {
238 161234 : poRet = new swq_expr_node(0);
239 161234 : poRet->field_type = node->field_type;
240 :
241 161234 : switch( (swq_op) node->nOperation )
242 : {
243 : case SWQ_AND:
244 2238 : poRet->int_value = sub_node_values[0]->int_value
245 2238 : && sub_node_values[1]->int_value;
246 2238 : break;
247 :
248 : case SWQ_OR:
249 6 : poRet->int_value = sub_node_values[0]->int_value
250 6 : || sub_node_values[1]->int_value;
251 6 : break;
252 :
253 : case SWQ_NOT:
254 106 : poRet->int_value = !sub_node_values[0]->int_value;
255 106 : break;
256 :
257 : case SWQ_EQ:
258 80798 : poRet->int_value = sub_node_values[0]->int_value
259 80798 : == sub_node_values[1]->int_value;
260 80798 : break;
261 :
262 : case SWQ_NE:
263 77472 : poRet->int_value = sub_node_values[0]->int_value
264 77472 : != sub_node_values[1]->int_value;
265 77472 : break;
266 :
267 : case SWQ_GT:
268 62 : poRet->int_value = sub_node_values[0]->int_value
269 62 : > sub_node_values[1]->int_value;
270 62 : break;
271 :
272 : case SWQ_LT:
273 200 : poRet->int_value = sub_node_values[0]->int_value
274 200 : < sub_node_values[1]->int_value;
275 200 : break;
276 :
277 : case SWQ_GE:
278 60 : poRet->int_value = sub_node_values[0]->int_value
279 60 : >= sub_node_values[1]->int_value;
280 60 : break;
281 :
282 : case SWQ_LE:
283 60 : poRet->int_value = sub_node_values[0]->int_value
284 60 : <= sub_node_values[1]->int_value;
285 60 : break;
286 :
287 : case SWQ_IN:
288 : {
289 : int i;
290 42 : poRet->int_value = 0;
291 82 : for( i = 1; i < node->nSubExprCount; i++ )
292 : {
293 124 : if( sub_node_values[0]->int_value
294 62 : == sub_node_values[i]->int_value )
295 : {
296 22 : poRet->int_value = 1;
297 22 : break;
298 : }
299 : }
300 : }
301 42 : break;
302 :
303 : case SWQ_BETWEEN:
304 100 : poRet->int_value = sub_node_values[0]->int_value
305 100 : >= sub_node_values[1]->int_value &&
306 80 : sub_node_values[0]->int_value
307 280 : <= sub_node_values[2]->int_value;
308 100 : break;
309 :
310 : case SWQ_ISNULL:
311 8 : poRet->int_value = sub_node_values[0]->is_null;
312 8 : break;
313 :
314 : case SWQ_ADD:
315 28 : poRet->int_value = sub_node_values[0]->int_value
316 28 : + sub_node_values[1]->int_value;
317 28 : break;
318 :
319 : case SWQ_SUBTRACT:
320 24 : poRet->int_value = sub_node_values[0]->int_value
321 24 : - sub_node_values[1]->int_value;
322 24 : break;
323 :
324 : case SWQ_MULTIPLY:
325 18 : poRet->int_value = sub_node_values[0]->int_value
326 18 : * sub_node_values[1]->int_value;
327 18 : break;
328 :
329 : case SWQ_DIVIDE:
330 10 : if( sub_node_values[1]->int_value == 0 )
331 0 : poRet->int_value = INT_MAX;
332 : else
333 10 : poRet->int_value = sub_node_values[0]->int_value
334 10 : / sub_node_values[1]->int_value;
335 10 : break;
336 :
337 : case SWQ_MODULUS:
338 2 : if( sub_node_values[1]->int_value == 0 )
339 0 : poRet->int_value = INT_MAX;
340 : else
341 2 : poRet->int_value = sub_node_values[0]->int_value
342 2 : % sub_node_values[1]->int_value;
343 2 : break;
344 :
345 : default:
346 0 : CPLAssert( FALSE );
347 0 : delete poRet;
348 0 : poRet = NULL;
349 : break;
350 : }
351 : }
352 :
353 : /* -------------------------------------------------------------------- */
354 : /* String operations. */
355 : /* -------------------------------------------------------------------- */
356 : else
357 : {
358 751060 : poRet = new swq_expr_node(0);
359 751060 : poRet->field_type = node->field_type;
360 :
361 751060 : switch( (swq_op) node->nOperation )
362 : {
363 : case SWQ_EQ:
364 : poRet->int_value =
365 250588 : strcasecmp(sub_node_values[0]->string_value,
366 501176 : sub_node_values[1]->string_value) == 0;
367 250588 : break;
368 :
369 : case SWQ_NE:
370 : poRet->int_value =
371 499786 : strcasecmp(sub_node_values[0]->string_value,
372 999572 : sub_node_values[1]->string_value) != 0;
373 499786 : break;
374 :
375 : case SWQ_GT:
376 : poRet->int_value =
377 96 : strcasecmp(sub_node_values[0]->string_value,
378 192 : sub_node_values[1]->string_value) > 0;
379 96 : break;
380 :
381 : case SWQ_LT:
382 : poRet->int_value =
383 100 : strcasecmp(sub_node_values[0]->string_value,
384 200 : sub_node_values[1]->string_value) < 0;
385 100 : break;
386 :
387 : case SWQ_GE:
388 : poRet->int_value =
389 60 : strcasecmp(sub_node_values[0]->string_value,
390 120 : sub_node_values[1]->string_value) >= 0;
391 60 : break;
392 :
393 : case SWQ_LE:
394 : poRet->int_value =
395 60 : strcasecmp(sub_node_values[0]->string_value,
396 120 : sub_node_values[1]->string_value) <= 0;
397 60 : break;
398 :
399 : case SWQ_IN:
400 : {
401 : int i;
402 78 : poRet->int_value = 0;
403 182 : for( i = 1; i < node->nSubExprCount; i++ )
404 : {
405 130 : if( strcasecmp(sub_node_values[0]->string_value,
406 130 : sub_node_values[i]->string_value) == 0 )
407 : {
408 26 : poRet->int_value = 1;
409 26 : break;
410 : }
411 : }
412 : }
413 78 : break;
414 :
415 : case SWQ_BETWEEN:
416 : poRet->int_value =
417 100 : strcasecmp(sub_node_values[0]->string_value,
418 100 : sub_node_values[1]->string_value) >= 0 &&
419 80 : strcasecmp(sub_node_values[0]->string_value,
420 280 : sub_node_values[2]->string_value) <= 0;
421 100 : break;
422 :
423 : case SWQ_LIKE:
424 : {
425 84 : char chEscape = '\0';
426 84 : if( node->nSubExprCount == 3 )
427 20 : chEscape = sub_node_values[2]->string_value[0];
428 84 : poRet->int_value = swq_test_like(sub_node_values[0]->string_value,
429 84 : sub_node_values[1]->string_value,
430 252 : chEscape);
431 84 : break;
432 : }
433 :
434 : case SWQ_ISNULL:
435 34 : poRet->int_value = sub_node_values[0]->is_null;
436 34 : break;
437 :
438 : case SWQ_CONCAT:
439 : case SWQ_ADD:
440 : {
441 46 : CPLString osResult = sub_node_values[0]->string_value;
442 : int i;
443 :
444 96 : for( i = 1; i < node->nSubExprCount; i++ )
445 50 : osResult += sub_node_values[i]->string_value;
446 :
447 46 : poRet->string_value = CPLStrdup(osResult);
448 46 : poRet->is_null = sub_node_values[0]->is_null;
449 46 : break;
450 : }
451 :
452 : case SWQ_SUBSTR:
453 : {
454 : int nOffset, nSize;
455 28 : const char *pszSrcStr = sub_node_values[0]->string_value;
456 :
457 28 : if( sub_node_values[1]->field_type == SWQ_INTEGER )
458 28 : nOffset = sub_node_values[1]->int_value;
459 0 : else if( sub_node_values[1]->field_type == SWQ_FLOAT )
460 0 : nOffset = (int) sub_node_values[1]->float_value;
461 : else
462 0 : nOffset = 0;
463 :
464 28 : if( node->nSubExprCount < 3 )
465 4 : nSize = 100000;
466 24 : else if( sub_node_values[2]->field_type == SWQ_INTEGER )
467 24 : nSize = sub_node_values[2]->int_value;
468 0 : else if( sub_node_values[2]->field_type == SWQ_FLOAT )
469 0 : nSize = (int) sub_node_values[2]->float_value;
470 : else
471 0 : nSize = 0;
472 :
473 28 : int nSrcStrLen = (int)strlen(pszSrcStr);
474 :
475 :
476 : /* In SQL, the first character is at offset 1 */
477 : /* And 0 is considered as 1 */
478 28 : if (nOffset > 0)
479 24 : nOffset --;
480 : /* Some implementations allow negative offsets, to start */
481 : /* from the end of the string */
482 4 : else if( nOffset < 0 )
483 : {
484 4 : if( nSrcStrLen + nOffset >= 0 )
485 4 : nOffset = nSrcStrLen + nOffset;
486 : else
487 0 : nOffset = 0;
488 : }
489 :
490 28 : if( nSize < 0 || nOffset > nSrcStrLen )
491 : {
492 0 : nOffset = 0;
493 0 : nSize = 0;
494 : }
495 28 : else if( nOffset + nSize > nSrcStrLen )
496 4 : nSize = nSrcStrLen - nOffset;
497 :
498 28 : CPLString osResult = pszSrcStr + nOffset;
499 28 : if( (int)osResult.size() > nSize )
500 0 : osResult.resize( nSize );
501 :
502 28 : poRet->string_value = CPLStrdup(osResult);
503 28 : poRet->is_null = sub_node_values[0]->is_null;
504 28 : break;
505 : }
506 :
507 : default:
508 0 : CPLAssert( FALSE );
509 0 : delete poRet;
510 0 : poRet = NULL;
511 : break;
512 : }
513 : }
514 :
515 918264 : return poRet;
516 : }
517 :
518 : /************************************************************************/
519 : /* SWQAutoPromoteIntegerToFloat() */
520 : /************************************************************************/
521 :
522 1848 : static void SWQAutoPromoteIntegerToFloat( swq_expr_node *poNode )
523 :
524 : {
525 1848 : if( poNode->nSubExprCount < 2 )
526 0 : return;
527 :
528 1848 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
529 : int i;
530 :
531 : // We allow mixes of integer and float, and string and dates.
532 : // When encountered, we promote integers to floats, and strings to
533 : // dates. We do that now.
534 3818 : for( i = 1; i < poNode->nSubExprCount; i++ )
535 : {
536 2900 : if( eArgType == SWQ_INTEGER
537 930 : && poNode->papoSubExpr[i]->field_type == SWQ_FLOAT )
538 44 : eArgType = SWQ_FLOAT;
539 : }
540 :
541 5666 : for( i = 0; i < poNode->nSubExprCount; i++ )
542 : {
543 3818 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
544 :
545 3818 : if( eArgType == SWQ_FLOAT
546 : && poSubNode->field_type == SWQ_INTEGER )
547 : {
548 266 : if( poSubNode->eNodeType == SNT_CONSTANT )
549 : {
550 256 : poSubNode->float_value = poSubNode->int_value;
551 256 : poSubNode->field_type = SWQ_FLOAT;
552 : }
553 : }
554 : }
555 : }
556 :
557 : /************************************************************************/
558 : /* SWQAutoPromoteStringToDateTime() */
559 : /************************************************************************/
560 :
561 1780 : static void SWQAutoPromoteStringToDateTime( swq_expr_node *poNode )
562 :
563 : {
564 1780 : if( poNode->nSubExprCount < 2 )
565 0 : return;
566 :
567 1780 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
568 : int i;
569 :
570 : // We allow mixes of integer and float, and string and dates.
571 : // When encountered, we promote integers to floats, and strings to
572 : // dates. We do that now.
573 3682 : for( i = 1; i < poNode->nSubExprCount; i++ )
574 : {
575 1902 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
576 :
577 1902 : if( eArgType == SWQ_STRING
578 : && (poSubNode->field_type == SWQ_DATE
579 : || poSubNode->field_type == SWQ_TIME
580 : || poSubNode->field_type == SWQ_TIMESTAMP) )
581 0 : eArgType = SWQ_TIMESTAMP;
582 : }
583 :
584 5462 : for( i = 0; i < poNode->nSubExprCount; i++ )
585 : {
586 3682 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
587 :
588 3682 : if( eArgType == SWQ_TIMESTAMP
589 : && (poSubNode->field_type == SWQ_STRING
590 : || poSubNode->field_type == SWQ_DATE
591 : || poSubNode->field_type == SWQ_TIME) )
592 : {
593 18 : if( poSubNode->eNodeType == SNT_CONSTANT )
594 : {
595 18 : poSubNode->field_type = SWQ_TIMESTAMP;
596 : }
597 : }
598 : }
599 : }
600 :
601 : /************************************************************************/
602 : /* SWQAutoConvertStringToNumeric() */
603 : /* */
604 : /* Convert string constants to integer or float constants */
605 : /* when there is a mix of arguments of type numeric and string */
606 : /************************************************************************/
607 :
608 1780 : static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
609 :
610 : {
611 1780 : if( poNode->nSubExprCount < 2 )
612 0 : return;
613 :
614 1780 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
615 : int i;
616 :
617 3676 : for( i = 1; i < poNode->nSubExprCount; i++ )
618 : {
619 1902 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
620 :
621 : /* identify the mixture of the argument type */
622 1902 : if( (eArgType == SWQ_STRING
623 : && (poSubNode->field_type == SWQ_INTEGER
624 : || poSubNode->field_type == SWQ_FLOAT)) ||
625 : (eArgType == SWQ_INTEGER
626 : && poSubNode->field_type == SWQ_STRING) )
627 : {
628 6 : eArgType = SWQ_FLOAT;
629 6 : break;
630 : }
631 : }
632 :
633 5462 : for( i = 0; i < poNode->nSubExprCount; i++ )
634 : {
635 3682 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
636 :
637 3682 : if( eArgType == SWQ_FLOAT
638 : && poSubNode->field_type == SWQ_STRING )
639 : {
640 24 : if( poSubNode->eNodeType == SNT_CONSTANT )
641 : {
642 : /* apply the string to numeric conversion */
643 20 : char* endPtr = NULL;
644 20 : poSubNode->float_value = CPLStrtod(poSubNode->string_value, &endPtr);
645 20 : if ( !(endPtr == NULL || *endPtr == '\0') )
646 : {
647 : CPLError(CE_Warning, CPLE_NotSupported,
648 : "Conversion failed when converting the string value '%s' to data type float.",
649 0 : poSubNode->string_value);
650 0 : continue;
651 : }
652 :
653 20 : poSubNode->float_value = atof(poSubNode->string_value);
654 : /* we should also fill the integer value in this case */
655 20 : poSubNode->int_value = (int)poSubNode->float_value;
656 20 : poSubNode->field_type = SWQ_FLOAT;
657 : }
658 : }
659 : }
660 : }
661 :
662 : /************************************************************************/
663 : /* SWQGeneralChecker() */
664 : /* */
665 : /* Check the general purpose functions have appropriate types, */
666 : /* and count and indicate the function return type under the */
667 : /* circumstances. */
668 : /************************************************************************/
669 :
670 2422 : swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
671 :
672 : {
673 2422 : swq_field_type eRetType = SWQ_ERROR;
674 2422 : swq_field_type eArgType = SWQ_OTHER;
675 2422 : int nArgCount = -1;
676 :
677 2422 : switch( (swq_op) poNode->nOperation )
678 : {
679 : case SWQ_AND:
680 : case SWQ_OR:
681 : case SWQ_NOT:
682 512 : eRetType = SWQ_BOOLEAN;
683 512 : break;
684 :
685 : case SWQ_EQ:
686 : case SWQ_NE:
687 : case SWQ_GT:
688 : case SWQ_LT:
689 : case SWQ_GE:
690 : case SWQ_LE:
691 : case SWQ_IN:
692 : case SWQ_BETWEEN:
693 1780 : eRetType = SWQ_BOOLEAN;
694 1780 : SWQAutoConvertStringToNumeric( poNode );
695 1780 : SWQAutoPromoteIntegerToFloat( poNode );
696 1780 : SWQAutoPromoteStringToDateTime( poNode );
697 1780 : eArgType = poNode->papoSubExpr[0]->field_type;
698 1780 : break;
699 :
700 : case SWQ_ISNULL:
701 16 : eRetType = SWQ_BOOLEAN;
702 16 : break;
703 :
704 : case SWQ_LIKE:
705 22 : eRetType = SWQ_BOOLEAN;
706 22 : eArgType = SWQ_STRING;
707 22 : break;
708 :
709 : case SWQ_MODULUS:
710 12 : eRetType = SWQ_INTEGER;
711 12 : eArgType = SWQ_INTEGER;
712 12 : break;
713 :
714 : case SWQ_ADD:
715 22 : SWQAutoPromoteIntegerToFloat( poNode );
716 22 : if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
717 4 : eRetType = eArgType = SWQ_STRING;
718 18 : else if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
719 6 : eRetType = eArgType = SWQ_FLOAT;
720 : else
721 12 : eRetType = eArgType = SWQ_INTEGER;
722 22 : break;
723 :
724 : case SWQ_SUBTRACT:
725 : case SWQ_MULTIPLY:
726 : case SWQ_DIVIDE:
727 46 : SWQAutoPromoteIntegerToFloat( poNode );
728 46 : if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
729 24 : eRetType = eArgType = SWQ_FLOAT;
730 : else
731 22 : eRetType = eArgType = SWQ_INTEGER;
732 46 : break;
733 :
734 : case SWQ_CONCAT:
735 6 : eRetType = SWQ_STRING;
736 6 : eArgType = SWQ_STRING;
737 6 : break;
738 :
739 : case SWQ_SUBSTR:
740 6 : eRetType = SWQ_STRING;
741 6 : if( poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2 )
742 : {
743 : CPLError( CE_Failure, CPLE_AppDefined,
744 : "Expected 2 or 3 arguments to SUBSTR(), but got %d.",
745 0 : poNode->nSubExprCount );
746 0 : return SWQ_ERROR;
747 : }
748 16 : if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
749 6 : || poNode->papoSubExpr[1]->field_type != SWQ_INTEGER
750 : || (poNode->nSubExprCount > 2
751 4 : && poNode->papoSubExpr[2]->field_type != SWQ_INTEGER) )
752 : {
753 : CPLError( CE_Failure, CPLE_AppDefined,
754 0 : "Wrong argument type for SUBSTR(), expected SUBSTR(string,int,int) or SUBSTR(string,int)." );
755 0 : return SWQ_ERROR;
756 : }
757 6 : break;
758 :
759 : default:
760 : {
761 : const swq_operation *poOp =
762 0 : swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
763 :
764 : CPLError( CE_Failure, CPLE_AppDefined,
765 : "SWQGeneralChecker() called on unsupported operation %s.",
766 0 : poOp->osName.c_str());
767 0 : return SWQ_ERROR;
768 : }
769 : }
770 : /* -------------------------------------------------------------------- */
771 : /* Check argument types. */
772 : /* -------------------------------------------------------------------- */
773 2422 : if( eArgType != SWQ_OTHER )
774 : {
775 : int i;
776 :
777 1882 : if( eArgType == SWQ_INTEGER )
778 880 : eArgType = SWQ_FLOAT;
779 :
780 5764 : for( i = 0; i < poNode->nSubExprCount; i++ )
781 : {
782 3892 : swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
783 3892 : if( eThisArgType == SWQ_INTEGER )
784 1772 : eThisArgType = SWQ_FLOAT;
785 :
786 3892 : if( eArgType != eThisArgType )
787 : {
788 : const swq_operation *poOp =
789 10 : swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
790 :
791 : CPLError( CE_Failure, CPLE_AppDefined,
792 : "Type mismatch or improper type of arguments to %s operator.",
793 10 : poOp->osName.c_str() );
794 10 : return SWQ_ERROR;
795 : }
796 : }
797 : }
798 :
799 : /* -------------------------------------------------------------------- */
800 : /* Validate the arg count if requested. */
801 : /* -------------------------------------------------------------------- */
802 2412 : if( nArgCount != -1
803 : && nArgCount != poNode->nSubExprCount )
804 : {
805 : const swq_operation *poOp =
806 0 : swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
807 :
808 : CPLError( CE_Failure, CPLE_AppDefined,
809 : "Expected %d arguments to %s, but got %d arguments.",
810 : nArgCount,
811 : poOp->osName.c_str(),
812 0 : poNode->nSubExprCount );
813 0 : return SWQ_ERROR;
814 : }
815 :
816 2412 : return eRetType;
817 : }
818 :
819 : /************************************************************************/
820 : /* SWQCastEvaluator() */
821 : /************************************************************************/
822 :
823 252 : swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
824 : swq_expr_node **sub_node_values )
825 :
826 : {
827 252 : swq_expr_node *poRetNode = NULL;
828 252 : swq_expr_node *poSrcNode = sub_node_values[0];
829 :
830 252 : switch( node->field_type )
831 : {
832 : case SWQ_INTEGER:
833 : {
834 2 : poRetNode = new swq_expr_node( 0 );
835 2 : poRetNode->is_null = poSrcNode->is_null;
836 :
837 2 : switch( poSrcNode->field_type )
838 : {
839 : case SWQ_INTEGER:
840 : case SWQ_BOOLEAN:
841 0 : poRetNode->int_value = poSrcNode->int_value;
842 0 : break;
843 :
844 : case SWQ_FLOAT:
845 0 : poRetNode->int_value = (int) poSrcNode->float_value;
846 0 : break;
847 :
848 : default:
849 2 : poRetNode->int_value = atoi(poSrcNode->string_value);
850 : break;
851 : }
852 : }
853 2 : break;
854 :
855 : case SWQ_FLOAT:
856 : {
857 242 : poRetNode = new swq_expr_node( 0.0 );
858 242 : poRetNode->is_null = poSrcNode->is_null;
859 :
860 242 : switch( poSrcNode->field_type )
861 : {
862 : case SWQ_INTEGER:
863 : case SWQ_BOOLEAN:
864 4 : poRetNode->float_value = poSrcNode->int_value;
865 4 : break;
866 :
867 : case SWQ_FLOAT:
868 0 : poRetNode->float_value = poSrcNode->float_value;
869 0 : break;
870 :
871 : default:
872 238 : poRetNode->float_value = atof(poSrcNode->string_value);
873 : break;
874 : }
875 : }
876 242 : break;
877 :
878 : // everything else is a string.
879 : default:
880 : {
881 8 : CPLString osRet;
882 :
883 8 : switch( poSrcNode->field_type )
884 : {
885 : case SWQ_INTEGER:
886 : case SWQ_BOOLEAN:
887 4 : osRet.Printf( "%d", poSrcNode->int_value );
888 4 : break;
889 :
890 : case SWQ_FLOAT:
891 4 : osRet.Printf( "%.15g", poSrcNode->float_value );
892 4 : break;
893 :
894 : default:
895 0 : osRet = poSrcNode->string_value;
896 : break;
897 : }
898 :
899 8 : if( node->nSubExprCount > 2 )
900 : {
901 : int nWidth;
902 :
903 8 : nWidth = sub_node_values[2]->int_value;
904 8 : if( nWidth > 0 && (int) strlen(osRet) > nWidth )
905 0 : osRet.resize(nWidth);
906 : }
907 :
908 8 : poRetNode = new swq_expr_node( osRet.c_str() );
909 8 : poRetNode->is_null = poSrcNode->is_null;
910 : }
911 : }
912 :
913 252 : return poRetNode;
914 : }
915 :
916 : /************************************************************************/
917 : /* SWQCastChecker() */
918 : /************************************************************************/
919 :
920 48 : swq_field_type SWQCastChecker( swq_expr_node *poNode )
921 :
922 : {
923 48 : swq_field_type eType = SWQ_ERROR;
924 48 : const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
925 :
926 48 : if( EQUAL(pszTypeName,"character") )
927 4 : eType = SWQ_STRING;
928 44 : else if( strcasecmp(pszTypeName,"integer") == 0 )
929 2 : eType = SWQ_INTEGER;
930 42 : else if( strcasecmp(pszTypeName,"float") == 0 )
931 40 : eType = SWQ_FLOAT;
932 2 : else if( strcasecmp(pszTypeName,"numeric") == 0 )
933 2 : eType = SWQ_FLOAT;
934 0 : else if( strcasecmp(pszTypeName,"timestamp") == 0 )
935 0 : eType = SWQ_TIMESTAMP;
936 0 : else if( strcasecmp(pszTypeName,"date") == 0 )
937 0 : eType = SWQ_DATE;
938 0 : else if( strcasecmp(pszTypeName,"time") == 0 )
939 0 : eType = SWQ_TIME;
940 : else
941 : {
942 : CPLError( CE_Failure, CPLE_AppDefined,
943 : "Unrecognized typename %s in CAST operator.",
944 0 : pszTypeName );
945 : }
946 :
947 48 : poNode->field_type = eType;
948 :
949 48 : return eType;
950 : }
|