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 120 : int swq_test_like( const char *input, const char *pattern, char chEscape )
41 :
42 : {
43 120 : if( input == NULL || pattern == NULL )
44 0 : return 0;
45 :
46 475 : while( *input != '\0' )
47 : {
48 350 : if( *pattern == '\0' )
49 0 : return 0;
50 :
51 350 : else if( *pattern == chEscape )
52 : {
53 10 : pattern++;
54 10 : if( *pattern == '\0' )
55 0 : return 0;
56 10 : if( tolower(*pattern) != tolower(*input) )
57 0 : return 0;
58 : else
59 : {
60 10 : input++;
61 10 : pattern++;
62 : }
63 : }
64 :
65 340 : else if( *pattern == '_' )
66 : {
67 0 : input++;
68 0 : pattern++;
69 : }
70 340 : else if( *pattern == '%' )
71 : {
72 : int eat;
73 :
74 12 : if( pattern[1] == '\0' )
75 2 : return 1;
76 :
77 : /* try eating varying amounts of the input till we get a positive*/
78 87 : for( eat = 0; input[eat] != '\0'; eat++ )
79 : {
80 78 : if( swq_test_like(input+eat,pattern+1, chEscape) )
81 1 : return 1;
82 : }
83 :
84 9 : return 0;
85 : }
86 : else
87 : {
88 328 : if( tolower(*pattern) != tolower(*input) )
89 103 : return 0;
90 : else
91 : {
92 225 : input++;
93 225 : pattern++;
94 : }
95 : }
96 : }
97 :
98 5 : if( *pattern != '\0' && strcmp(pattern,"%") != 0 )
99 1 : return 0;
100 : else
101 4 : return 1;
102 : }
103 :
104 : /************************************************************************/
105 : /* SWQGeneralEvaluator() */
106 : /************************************************************************/
107 :
108 455698 : swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
109 : swq_expr_node **sub_node_values )
110 :
111 : {
112 455698 : swq_expr_node *poRet = NULL;
113 :
114 : /* -------------------------------------------------------------------- */
115 : /* Floating point operations. */
116 : /* -------------------------------------------------------------------- */
117 911336 : if( sub_node_values[0]->field_type == SWQ_FLOAT
118 : || (node->nSubExprCount > 1
119 453169 : && sub_node_values[1]->field_type == SWQ_FLOAT) )
120 :
121 : {
122 2469 : poRet = new swq_expr_node(0);
123 2469 : poRet->field_type = node->field_type;
124 :
125 2469 : if( sub_node_values[0]->field_type == SWQ_INTEGER )
126 14 : sub_node_values[0]->float_value = sub_node_values[0]->int_value;
127 4938 : if( node->nSubExprCount > 1 &&
128 2469 : sub_node_values[1]->field_type == SWQ_INTEGER )
129 20 : sub_node_values[1]->float_value = sub_node_values[1]->int_value;
130 :
131 2469 : switch( (swq_op) node->nOperation )
132 : {
133 : case SWQ_EQ:
134 943 : poRet->int_value = sub_node_values[0]->float_value
135 943 : == sub_node_values[1]->float_value;
136 943 : break;
137 :
138 : case SWQ_NE:
139 1108 : poRet->int_value = sub_node_values[0]->float_value
140 1108 : != sub_node_values[1]->float_value;
141 1108 : break;
142 :
143 : case SWQ_GT:
144 145 : poRet->int_value = sub_node_values[0]->float_value
145 145 : > sub_node_values[1]->float_value;
146 145 : break;
147 :
148 : case SWQ_LT:
149 95 : poRet->int_value = sub_node_values[0]->float_value
150 95 : < sub_node_values[1]->float_value;
151 95 : break;
152 :
153 : case SWQ_GE:
154 20 : poRet->int_value = sub_node_values[0]->float_value
155 20 : >= sub_node_values[1]->float_value;
156 20 : break;
157 :
158 : case SWQ_LE:
159 20 : poRet->int_value = sub_node_values[0]->float_value
160 20 : <= sub_node_values[1]->float_value;
161 20 : break;
162 :
163 : case SWQ_IN:
164 : {
165 : int i;
166 86 : poRet->int_value = 0;
167 215 : for( i = 1; i < node->nSubExprCount; i++ )
168 : {
169 298 : if( sub_node_values[0]->float_value
170 149 : == sub_node_values[i]->float_value )
171 : {
172 20 : poRet->int_value = 1;
173 20 : break;
174 : }
175 : }
176 : }
177 86 : break;
178 :
179 : case SWQ_BETWEEN:
180 20 : poRet->int_value = sub_node_values[0]->float_value
181 20 : >= sub_node_values[1]->float_value &&
182 18 : sub_node_values[0]->float_value
183 58 : <= sub_node_values[2]->float_value;
184 20 : 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 0 : poRet->float_value = sub_node_values[0]->float_value
192 0 : + sub_node_values[1]->float_value;
193 0 : break;
194 :
195 : case SWQ_SUBTRACT:
196 0 : poRet->float_value = sub_node_values[0]->float_value
197 0 : - sub_node_values[1]->float_value;
198 0 : break;
199 :
200 : case SWQ_MULTIPLY:
201 0 : poRet->float_value = sub_node_values[0]->float_value
202 0 : * sub_node_values[1]->float_value;
203 0 : break;
204 :
205 : case SWQ_DIVIDE:
206 12 : if( sub_node_values[1]->float_value == 0 )
207 0 : poRet->float_value = INT_MAX;
208 : else
209 12 : poRet->float_value = sub_node_values[0]->float_value
210 12 : / sub_node_values[1]->float_value;
211 12 : break;
212 :
213 : case SWQ_MODULUS:
214 : {
215 20 : int nRight = (int) sub_node_values[1]->float_value;
216 20 : poRet->field_type = SWQ_INTEGER;
217 20 : if (nRight == 0)
218 0 : poRet->int_value = INT_MAX;
219 : else
220 20 : poRet->int_value = ((int) sub_node_values[0]->float_value)
221 20 : % nRight;
222 20 : 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 906652 : else if( sub_node_values[0]->field_type == SWQ_INTEGER
236 375234 : || sub_node_values[0]->field_type == SWQ_BOOLEAN )
237 : {
238 78189 : poRet = new swq_expr_node(0);
239 78189 : poRet->field_type = node->field_type;
240 :
241 78189 : switch( (swq_op) node->nOperation )
242 : {
243 : case SWQ_AND:
244 141 : poRet->int_value = sub_node_values[0]->int_value
245 141 : && sub_node_values[1]->int_value;
246 141 : break;
247 :
248 : case SWQ_OR:
249 0 : poRet->int_value = sub_node_values[0]->int_value
250 0 : || sub_node_values[1]->int_value;
251 0 : break;
252 :
253 : case SWQ_NOT:
254 53 : poRet->int_value = !sub_node_values[0]->int_value;
255 53 : break;
256 :
257 : case SWQ_EQ:
258 39164 : poRet->int_value = sub_node_values[0]->int_value
259 39164 : == sub_node_values[1]->int_value;
260 39164 : break;
261 :
262 : case SWQ_NE:
263 38706 : poRet->int_value = sub_node_values[0]->int_value
264 38706 : != sub_node_values[1]->int_value;
265 38706 : break;
266 :
267 : case SWQ_GT:
268 14 : poRet->int_value = sub_node_values[0]->int_value
269 14 : > sub_node_values[1]->int_value;
270 14 : break;
271 :
272 : case SWQ_LT:
273 70 : poRet->int_value = sub_node_values[0]->int_value
274 70 : < sub_node_values[1]->int_value;
275 70 : break;
276 :
277 : case SWQ_GE:
278 0 : poRet->int_value = sub_node_values[0]->int_value
279 0 : >= sub_node_values[1]->int_value;
280 0 : break;
281 :
282 : case SWQ_LE:
283 0 : poRet->int_value = sub_node_values[0]->int_value
284 0 : <= sub_node_values[1]->int_value;
285 0 : break;
286 :
287 : case SWQ_IN:
288 : {
289 : int i;
290 1 : poRet->int_value = 0;
291 1 : for( i = 1; i < node->nSubExprCount; i++ )
292 : {
293 2 : if( sub_node_values[0]->int_value
294 1 : == sub_node_values[i]->int_value )
295 : {
296 1 : poRet->int_value = 1;
297 1 : break;
298 : }
299 : }
300 : }
301 1 : break;
302 :
303 : case SWQ_BETWEEN:
304 0 : poRet->int_value = sub_node_values[0]->int_value
305 0 : >= sub_node_values[1]->int_value &&
306 0 : sub_node_values[0]->int_value
307 0 : <= sub_node_values[2]->int_value;
308 0 : break;
309 :
310 : case SWQ_ISNULL:
311 4 : poRet->int_value = sub_node_values[0]->is_null;
312 4 : break;
313 :
314 : case SWQ_ADD:
315 13 : poRet->int_value = sub_node_values[0]->int_value
316 13 : + sub_node_values[1]->int_value;
317 13 : break;
318 :
319 : case SWQ_SUBTRACT:
320 11 : poRet->int_value = sub_node_values[0]->int_value
321 11 : - sub_node_values[1]->int_value;
322 11 : break;
323 :
324 : case SWQ_MULTIPLY:
325 8 : poRet->int_value = sub_node_values[0]->int_value
326 8 : * sub_node_values[1]->int_value;
327 8 : break;
328 :
329 : case SWQ_DIVIDE:
330 4 : if( sub_node_values[1]->int_value == 0 )
331 0 : poRet->int_value = INT_MAX;
332 : else
333 4 : poRet->int_value = sub_node_values[0]->int_value
334 4 : / sub_node_values[1]->int_value;
335 4 : break;
336 :
337 : case SWQ_MODULUS:
338 0 : if( sub_node_values[1]->int_value == 0 )
339 0 : poRet->int_value = INT_MAX;
340 : else
341 0 : poRet->int_value = sub_node_values[0]->int_value
342 0 : % sub_node_values[1]->int_value;
343 0 : 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 375040 : poRet = new swq_expr_node(0);
359 375040 : poRet->field_type = node->field_type;
360 :
361 375040 : switch( (swq_op) node->nOperation )
362 : {
363 : case SWQ_EQ:
364 : poRet->int_value =
365 125156 : strcasecmp(sub_node_values[0]->string_value,
366 250312 : sub_node_values[1]->string_value) == 0;
367 125156 : break;
368 :
369 : case SWQ_NE:
370 : poRet->int_value =
371 249718 : strcasecmp(sub_node_values[0]->string_value,
372 499436 : sub_node_values[1]->string_value) != 0;
373 249718 : break;
374 :
375 : case SWQ_GT:
376 : poRet->int_value =
377 25 : strcasecmp(sub_node_values[0]->string_value,
378 50 : sub_node_values[1]->string_value) > 0;
379 25 : break;
380 :
381 : case SWQ_LT:
382 : poRet->int_value =
383 27 : strcasecmp(sub_node_values[0]->string_value,
384 54 : sub_node_values[1]->string_value) < 0;
385 27 : break;
386 :
387 : case SWQ_GE:
388 : poRet->int_value =
389 0 : strcasecmp(sub_node_values[0]->string_value,
390 0 : sub_node_values[1]->string_value) >= 0;
391 0 : break;
392 :
393 : case SWQ_LE:
394 : poRet->int_value =
395 0 : strcasecmp(sub_node_values[0]->string_value,
396 0 : sub_node_values[1]->string_value) <= 0;
397 0 : break;
398 :
399 : case SWQ_IN:
400 : {
401 : int i;
402 19 : poRet->int_value = 0;
403 51 : for( i = 1; i < node->nSubExprCount; i++ )
404 : {
405 35 : if( strcasecmp(sub_node_values[0]->string_value,
406 35 : sub_node_values[i]->string_value) == 0 )
407 : {
408 3 : poRet->int_value = 1;
409 3 : break;
410 : }
411 : }
412 : }
413 19 : break;
414 :
415 : case SWQ_BETWEEN:
416 : poRet->int_value =
417 0 : strcasecmp(sub_node_values[0]->string_value,
418 0 : sub_node_values[1]->string_value) >= 0 &&
419 0 : strcasecmp(sub_node_values[0]->string_value,
420 0 : sub_node_values[2]->string_value) <= 0;
421 0 : break;
422 :
423 : case SWQ_LIKE:
424 : {
425 42 : char chEscape = '\0';
426 42 : if( node->nSubExprCount == 3 )
427 10 : chEscape = sub_node_values[2]->string_value[0];
428 42 : poRet->int_value = swq_test_like(sub_node_values[0]->string_value,
429 42 : sub_node_values[1]->string_value,
430 126 : chEscape);
431 42 : break;
432 : }
433 :
434 : case SWQ_ISNULL:
435 17 : poRet->int_value = sub_node_values[0]->is_null;
436 17 : break;
437 :
438 : case SWQ_CONCAT:
439 : case SWQ_ADD:
440 : {
441 22 : CPLString osResult = sub_node_values[0]->string_value;
442 : int i;
443 :
444 46 : for( i = 1; i < node->nSubExprCount; i++ )
445 24 : osResult += sub_node_values[i]->string_value;
446 :
447 22 : poRet->string_value = CPLStrdup(osResult);
448 22 : poRet->is_null = sub_node_values[0]->is_null;
449 22 : break;
450 : }
451 :
452 : case SWQ_SUBSTR:
453 : {
454 : int nOffset, nSize;
455 14 : const char *pszSrcStr = sub_node_values[0]->string_value;
456 :
457 14 : if( sub_node_values[1]->field_type == SWQ_INTEGER )
458 14 : 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 14 : if( node->nSubExprCount < 3 )
465 2 : nSize = 100000;
466 12 : else if( sub_node_values[2]->field_type == SWQ_INTEGER )
467 12 : 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 14 : 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 14 : if (nOffset > 0)
479 12 : nOffset --;
480 : /* Some implementations allow negative offsets, to start */
481 : /* from the end of the string */
482 2 : else if( nOffset < 0 )
483 : {
484 2 : if( nSrcStrLen + nOffset >= 0 )
485 2 : nOffset = nSrcStrLen + nOffset;
486 : else
487 0 : nOffset = 0;
488 : }
489 :
490 14 : if( nSize < 0 || nOffset > nSrcStrLen )
491 : {
492 0 : nOffset = 0;
493 0 : nSize = 0;
494 : }
495 14 : else if( nOffset + nSize > nSrcStrLen )
496 2 : nSize = nSrcStrLen - nOffset;
497 :
498 14 : CPLString osResult = pszSrcStr + nOffset;
499 14 : if( (int)osResult.size() > nSize )
500 0 : osResult.resize( nSize );
501 :
502 14 : poRet->string_value = CPLStrdup(osResult);
503 14 : poRet->is_null = sub_node_values[0]->is_null;
504 14 : break;
505 : }
506 :
507 : default:
508 0 : CPLAssert( FALSE );
509 0 : delete poRet;
510 0 : poRet = NULL;
511 : break;
512 : }
513 : }
514 :
515 455698 : return poRet;
516 : }
517 :
518 : /************************************************************************/
519 : /* SWQAutoPromoteIntegerToFloat() */
520 : /************************************************************************/
521 :
522 433 : static void SWQAutoPromoteIntegerToFloat( swq_expr_node *poNode )
523 :
524 : {
525 433 : if( poNode->nSubExprCount < 2 )
526 0 : return;
527 :
528 433 : 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 885 : for( i = 1; i < poNode->nSubExprCount; i++ )
535 : {
536 592 : if( eArgType == SWQ_INTEGER
537 140 : && poNode->papoSubExpr[i]->field_type == SWQ_FLOAT )
538 6 : eArgType = SWQ_FLOAT;
539 : }
540 :
541 1318 : for( i = 0; i < poNode->nSubExprCount; i++ )
542 : {
543 885 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
544 :
545 885 : if( eArgType == SWQ_FLOAT
546 : && poSubNode->field_type == SWQ_INTEGER )
547 : {
548 148 : if( poSubNode->eNodeType == SNT_CONSTANT )
549 : {
550 143 : poSubNode->float_value = poSubNode->int_value;
551 143 : poSubNode->field_type = SWQ_FLOAT;
552 : }
553 : }
554 : }
555 : }
556 :
557 : /************************************************************************/
558 : /* SWQAutoPromoteStringToDateTime() */
559 : /************************************************************************/
560 :
561 415 : static void SWQAutoPromoteStringToDateTime( swq_expr_node *poNode )
562 :
563 : {
564 415 : if( poNode->nSubExprCount < 2 )
565 0 : return;
566 :
567 415 : 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 849 : for( i = 1; i < poNode->nSubExprCount; i++ )
574 : {
575 434 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
576 :
577 434 : 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 1264 : for( i = 0; i < poNode->nSubExprCount; i++ )
585 : {
586 849 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
587 :
588 849 : if( eArgType == SWQ_TIMESTAMP
589 : && (poSubNode->field_type == SWQ_STRING
590 : || poSubNode->field_type == SWQ_DATE
591 : || poSubNode->field_type == SWQ_TIME) )
592 : {
593 6 : if( poSubNode->eNodeType == SNT_CONSTANT )
594 : {
595 6 : 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 415 : static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
609 :
610 : {
611 415 : if( poNode->nSubExprCount < 2 )
612 0 : return;
613 :
614 415 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
615 : int i;
616 :
617 846 : for( i = 1; i < poNode->nSubExprCount; i++ )
618 : {
619 434 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
620 :
621 : /* identify the mixture of the argument type */
622 434 : 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 3 : eArgType = SWQ_FLOAT;
629 3 : break;
630 : }
631 : }
632 :
633 1264 : for( i = 0; i < poNode->nSubExprCount; i++ )
634 : {
635 849 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
636 :
637 849 : if( eArgType == SWQ_FLOAT
638 : && poSubNode->field_type == SWQ_STRING )
639 : {
640 12 : if( poSubNode->eNodeType == SNT_CONSTANT )
641 : {
642 : /* apply the string to numeric conversion */
643 10 : char* endPtr = NULL;
644 10 : poSubNode->float_value = CPLStrtod(poSubNode->string_value, &endPtr);
645 10 : 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 10 : poSubNode->float_value = atof(poSubNode->string_value);
654 : /* we should also fill the integer value in this case */
655 10 : poSubNode->int_value = (int)poSubNode->float_value;
656 10 : 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 517 : swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
671 :
672 : {
673 517 : swq_field_type eRetType = SWQ_ERROR;
674 517 : swq_field_type eArgType = SWQ_OTHER;
675 517 : int nArgCount = -1;
676 :
677 517 : switch( (swq_op) poNode->nOperation )
678 : {
679 : case SWQ_AND:
680 : case SWQ_OR:
681 : case SWQ_NOT:
682 56 : eRetType = SWQ_BOOLEAN;
683 56 : 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 415 : eRetType = SWQ_BOOLEAN;
694 415 : SWQAutoConvertStringToNumeric( poNode );
695 415 : SWQAutoPromoteIntegerToFloat( poNode );
696 415 : SWQAutoPromoteStringToDateTime( poNode );
697 415 : eArgType = poNode->papoSubExpr[0]->field_type;
698 415 : break;
699 :
700 : case SWQ_ISNULL:
701 9 : eRetType = SWQ_BOOLEAN;
702 9 : break;
703 :
704 : case SWQ_LIKE:
705 12 : eRetType = SWQ_BOOLEAN;
706 12 : eArgType = SWQ_STRING;
707 12 : break;
708 :
709 : case SWQ_MODULUS:
710 2 : eRetType = SWQ_INTEGER;
711 2 : eArgType = SWQ_INTEGER;
712 2 : break;
713 :
714 : case SWQ_ADD:
715 7 : SWQAutoPromoteIntegerToFloat( poNode );
716 7 : if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
717 2 : eRetType = eArgType = SWQ_STRING;
718 5 : else if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
719 0 : eRetType = eArgType = SWQ_FLOAT;
720 : else
721 5 : eRetType = eArgType = SWQ_INTEGER;
722 7 : break;
723 :
724 : case SWQ_SUBTRACT:
725 : case SWQ_MULTIPLY:
726 : case SWQ_DIVIDE:
727 11 : SWQAutoPromoteIntegerToFloat( poNode );
728 11 : if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
729 3 : eRetType = eArgType = SWQ_FLOAT;
730 : else
731 8 : eRetType = eArgType = SWQ_INTEGER;
732 11 : break;
733 :
734 : case SWQ_CONCAT:
735 2 : eRetType = SWQ_STRING;
736 2 : eArgType = SWQ_STRING;
737 2 : break;
738 :
739 : case SWQ_SUBSTR:
740 3 : eRetType = SWQ_STRING;
741 3 : 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 8 : if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
749 3 : || poNode->papoSubExpr[1]->field_type != SWQ_INTEGER
750 : || (poNode->nSubExprCount > 2
751 2 : && 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 3 : 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 517 : if( eArgType != SWQ_OTHER )
774 : {
775 : int i;
776 :
777 446 : if( eArgType == SWQ_INTEGER )
778 141 : eArgType = SWQ_FLOAT;
779 :
780 1355 : for( i = 0; i < poNode->nSubExprCount; i++ )
781 : {
782 914 : swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
783 914 : if( eThisArgType == SWQ_INTEGER )
784 278 : eThisArgType = SWQ_FLOAT;
785 :
786 914 : if( eArgType != eThisArgType )
787 : {
788 : const swq_operation *poOp =
789 5 : 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 5 : poOp->osName.c_str() );
794 5 : return SWQ_ERROR;
795 : }
796 : }
797 : }
798 :
799 : /* -------------------------------------------------------------------- */
800 : /* Validate the arg count if requested. */
801 : /* -------------------------------------------------------------------- */
802 512 : 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 512 : return eRetType;
817 : }
818 :
819 : /************************************************************************/
820 : /* SWQCastEvaluator() */
821 : /************************************************************************/
822 :
823 126 : swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
824 : swq_expr_node **sub_node_values )
825 :
826 : {
827 126 : swq_expr_node *poRetNode = NULL;
828 126 : swq_expr_node *poSrcNode = sub_node_values[0];
829 :
830 126 : switch( node->field_type )
831 : {
832 : case SWQ_INTEGER:
833 : {
834 1 : poRetNode = new swq_expr_node( 0 );
835 1 : poRetNode->is_null = poSrcNode->is_null;
836 :
837 1 : 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 1 : poRetNode->int_value = atoi(poSrcNode->string_value);
850 : break;
851 : }
852 : }
853 1 : break;
854 :
855 : case SWQ_FLOAT:
856 : {
857 121 : poRetNode = new swq_expr_node( 0.0 );
858 121 : poRetNode->is_null = poSrcNode->is_null;
859 :
860 121 : switch( poSrcNode->field_type )
861 : {
862 : case SWQ_INTEGER:
863 : case SWQ_BOOLEAN:
864 2 : poRetNode->float_value = poSrcNode->int_value;
865 2 : break;
866 :
867 : case SWQ_FLOAT:
868 0 : poRetNode->float_value = poSrcNode->float_value;
869 0 : break;
870 :
871 : default:
872 119 : poRetNode->float_value = atof(poSrcNode->string_value);
873 : break;
874 : }
875 : }
876 121 : break;
877 :
878 : // everything else is a string.
879 : default:
880 : {
881 4 : CPLString osRet;
882 :
883 4 : switch( poSrcNode->field_type )
884 : {
885 : case SWQ_INTEGER:
886 : case SWQ_BOOLEAN:
887 2 : osRet.Printf( "%d", poSrcNode->int_value );
888 2 : break;
889 :
890 : case SWQ_FLOAT:
891 2 : osRet.Printf( "%.15g", poSrcNode->float_value );
892 2 : break;
893 :
894 : default:
895 0 : osRet = poSrcNode->string_value;
896 : break;
897 : }
898 :
899 4 : if( node->nSubExprCount > 2 )
900 : {
901 : int nWidth;
902 :
903 4 : nWidth = sub_node_values[2]->int_value;
904 4 : if( nWidth > 0 && (int) strlen(osRet) > nWidth )
905 0 : osRet.resize(nWidth);
906 : }
907 :
908 4 : poRetNode = new swq_expr_node( osRet.c_str() );
909 4 : poRetNode->is_null = poSrcNode->is_null;
910 : }
911 : }
912 :
913 126 : return poRetNode;
914 : }
915 :
916 : /************************************************************************/
917 : /* SWQCastChecker() */
918 : /************************************************************************/
919 :
920 24 : swq_field_type SWQCastChecker( swq_expr_node *poNode )
921 :
922 : {
923 24 : swq_field_type eType = SWQ_ERROR;
924 24 : const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
925 :
926 24 : if( EQUAL(pszTypeName,"character") )
927 2 : eType = SWQ_STRING;
928 22 : else if( strcasecmp(pszTypeName,"integer") == 0 )
929 1 : eType = SWQ_INTEGER;
930 21 : else if( strcasecmp(pszTypeName,"float") == 0 )
931 20 : eType = SWQ_FLOAT;
932 1 : else if( strcasecmp(pszTypeName,"numeric") == 0 )
933 1 : 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 24 : poNode->field_type = eType;
948 :
949 24 : return eType;
950 : }
|