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 597165 : swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
109 : swq_expr_node **sub_node_values )
110 :
111 : {
112 597165 : swq_expr_node *poRet = NULL;
113 :
114 : /* -------------------------------------------------------------------- */
115 : /* Floating point operations. */
116 : /* -------------------------------------------------------------------- */
117 1194065 : if( sub_node_values[0]->field_type == SWQ_FLOAT
118 : || (node->nSubExprCount > 1
119 593569 : && sub_node_values[1]->field_type == SWQ_FLOAT) )
120 :
121 : {
122 3406 : poRet = new swq_expr_node(0);
123 3406 : poRet->field_type = node->field_type;
124 :
125 3406 : if( sub_node_values[0]->field_type == SWQ_INTEGER )
126 29 : sub_node_values[0]->float_value = sub_node_values[0]->int_value;
127 6812 : if( node->nSubExprCount > 1 &&
128 3406 : sub_node_values[1]->field_type == SWQ_INTEGER )
129 21 : sub_node_values[1]->float_value = sub_node_values[1]->int_value;
130 :
131 3406 : if( node->nOperation != SWQ_ISNULL )
132 : {
133 10249 : for( int i = 0; i < node->nSubExprCount; i++ )
134 : {
135 6918 : if( sub_node_values[i]->is_null )
136 : {
137 75 : if( poRet->field_type == SWQ_BOOLEAN )
138 : {
139 61 : poRet->int_value = FALSE;
140 61 : return poRet;
141 : }
142 14 : else if( poRet->field_type == SWQ_FLOAT )
143 : {
144 7 : poRet->float_value = 0;
145 7 : poRet->is_null = 1;
146 7 : return poRet;
147 : }
148 7 : else if( poRet->field_type == SWQ_INTEGER ||
149 : node->nOperation == SWQ_MODULUS )
150 : {
151 7 : poRet->field_type = SWQ_INTEGER;
152 7 : poRet->int_value = 0;
153 7 : poRet->is_null = 1;
154 7 : return poRet;
155 : }
156 : }
157 : }
158 : }
159 :
160 3331 : switch( (swq_op) node->nOperation )
161 : {
162 : case SWQ_EQ:
163 1268 : poRet->int_value = sub_node_values[0]->float_value
164 1268 : == sub_node_values[1]->float_value;
165 1268 : break;
166 :
167 : case SWQ_NE:
168 1242 : poRet->int_value = sub_node_values[0]->float_value
169 1242 : != sub_node_values[1]->float_value;
170 1242 : break;
171 :
172 : case SWQ_GT:
173 221 : poRet->int_value = sub_node_values[0]->float_value
174 221 : > sub_node_values[1]->float_value;
175 221 : break;
176 :
177 : case SWQ_LT:
178 181 : poRet->int_value = sub_node_values[0]->float_value
179 181 : < sub_node_values[1]->float_value;
180 181 : break;
181 :
182 : case SWQ_GE:
183 98 : poRet->int_value = sub_node_values[0]->float_value
184 98 : >= sub_node_values[1]->float_value;
185 98 : break;
186 :
187 : case SWQ_LE:
188 98 : poRet->int_value = sub_node_values[0]->float_value
189 98 : <= sub_node_values[1]->float_value;
190 98 : break;
191 :
192 : case SWQ_IN:
193 : {
194 : int i;
195 106 : poRet->int_value = 0;
196 255 : for( i = 1; i < node->nSubExprCount; i++ )
197 : {
198 358 : if( sub_node_values[0]->float_value
199 179 : == sub_node_values[i]->float_value )
200 : {
201 30 : poRet->int_value = 1;
202 30 : break;
203 : }
204 : }
205 : }
206 106 : break;
207 :
208 : case SWQ_BETWEEN:
209 70 : poRet->int_value = sub_node_values[0]->float_value
210 70 : >= sub_node_values[1]->float_value &&
211 58 : sub_node_values[0]->float_value
212 198 : <= sub_node_values[2]->float_value;
213 70 : break;
214 :
215 : case SWQ_ISNULL:
216 0 : poRet->int_value = sub_node_values[0]->is_null;
217 0 : break;
218 :
219 : case SWQ_ADD:
220 3 : poRet->float_value = sub_node_values[0]->float_value
221 3 : + sub_node_values[1]->float_value;
222 3 : break;
223 :
224 : case SWQ_SUBTRACT:
225 3 : poRet->float_value = sub_node_values[0]->float_value
226 3 : - sub_node_values[1]->float_value;
227 3 : break;
228 :
229 : case SWQ_MULTIPLY:
230 3 : poRet->float_value = sub_node_values[0]->float_value
231 3 : * sub_node_values[1]->float_value;
232 3 : break;
233 :
234 : case SWQ_DIVIDE:
235 15 : if( sub_node_values[1]->float_value == 0 )
236 0 : poRet->float_value = INT_MAX;
237 : else
238 15 : poRet->float_value = sub_node_values[0]->float_value
239 15 : / sub_node_values[1]->float_value;
240 15 : break;
241 :
242 : case SWQ_MODULUS:
243 : {
244 23 : int nRight = (int) sub_node_values[1]->float_value;
245 23 : poRet->field_type = SWQ_INTEGER;
246 23 : if (nRight == 0)
247 0 : poRet->int_value = INT_MAX;
248 : else
249 23 : poRet->int_value = ((int) sub_node_values[0]->float_value)
250 23 : % nRight;
251 23 : break;
252 : }
253 :
254 : default:
255 0 : CPLAssert( FALSE );
256 0 : delete poRet;
257 0 : poRet = NULL;
258 : break;
259 : }
260 : }
261 : /* -------------------------------------------------------------------- */
262 : /* integer/boolean operations. */
263 : /* -------------------------------------------------------------------- */
264 1188771 : else if( sub_node_values[0]->field_type == SWQ_INTEGER
265 377254 : || sub_node_values[0]->field_type == SWQ_BOOLEAN )
266 : {
267 217957 : poRet = new swq_expr_node(0);
268 217957 : poRet->field_type = node->field_type;
269 :
270 217957 : if( node->nOperation != SWQ_ISNULL )
271 : {
272 653436 : for( int i = 0; i < node->nSubExprCount; i++ )
273 : {
274 435696 : if( sub_node_values[i]->is_null )
275 : {
276 199 : if( poRet->field_type == SWQ_BOOLEAN )
277 : {
278 185 : poRet->int_value = FALSE;
279 185 : return poRet;
280 : }
281 14 : else if( poRet->field_type == SWQ_INTEGER )
282 : {
283 14 : poRet->int_value = 0;
284 14 : poRet->is_null = 1;
285 14 : return poRet;
286 : }
287 : }
288 : }
289 : }
290 :
291 217758 : switch( (swq_op) node->nOperation )
292 : {
293 : case SWQ_AND:
294 1297 : poRet->int_value = sub_node_values[0]->int_value
295 1297 : && sub_node_values[1]->int_value;
296 1297 : break;
297 :
298 : case SWQ_OR:
299 81 : poRet->int_value = sub_node_values[0]->int_value
300 81 : || sub_node_values[1]->int_value;
301 81 : break;
302 :
303 : case SWQ_NOT:
304 74 : poRet->int_value = !sub_node_values[0]->int_value;
305 74 : break;
306 :
307 : case SWQ_EQ:
308 177065 : poRet->int_value = sub_node_values[0]->int_value
309 177065 : == sub_node_values[1]->int_value;
310 177065 : break;
311 :
312 : case SWQ_NE:
313 38888 : poRet->int_value = sub_node_values[0]->int_value
314 38888 : != sub_node_values[1]->int_value;
315 38888 : break;
316 :
317 : case SWQ_GT:
318 39 : poRet->int_value = sub_node_values[0]->int_value
319 39 : > sub_node_values[1]->int_value;
320 39 : break;
321 :
322 : case SWQ_LT:
323 108 : poRet->int_value = sub_node_values[0]->int_value
324 108 : < sub_node_values[1]->int_value;
325 108 : break;
326 :
327 : case SWQ_GE:
328 38 : poRet->int_value = sub_node_values[0]->int_value
329 38 : >= sub_node_values[1]->int_value;
330 38 : break;
331 :
332 : case SWQ_LE:
333 38 : poRet->int_value = sub_node_values[0]->int_value
334 38 : <= sub_node_values[1]->int_value;
335 38 : break;
336 :
337 : case SWQ_IN:
338 : {
339 : int i;
340 21 : poRet->int_value = 0;
341 41 : for( i = 1; i < node->nSubExprCount; i++ )
342 : {
343 62 : if( sub_node_values[0]->int_value
344 31 : == sub_node_values[i]->int_value )
345 : {
346 11 : poRet->int_value = 1;
347 11 : break;
348 : }
349 : }
350 : }
351 21 : break;
352 :
353 : case SWQ_BETWEEN:
354 50 : poRet->int_value = sub_node_values[0]->int_value
355 50 : >= sub_node_values[1]->int_value &&
356 40 : sub_node_values[0]->int_value
357 140 : <= sub_node_values[2]->int_value;
358 50 : break;
359 :
360 : case SWQ_ISNULL:
361 18 : poRet->int_value = sub_node_values[0]->is_null;
362 18 : break;
363 :
364 : case SWQ_ADD:
365 14 : poRet->int_value = sub_node_values[0]->int_value
366 14 : + sub_node_values[1]->int_value;
367 14 : break;
368 :
369 : case SWQ_SUBTRACT:
370 12 : poRet->int_value = sub_node_values[0]->int_value
371 12 : - sub_node_values[1]->int_value;
372 12 : break;
373 :
374 : case SWQ_MULTIPLY:
375 9 : poRet->int_value = sub_node_values[0]->int_value
376 9 : * sub_node_values[1]->int_value;
377 9 : break;
378 :
379 : case SWQ_DIVIDE:
380 5 : if( sub_node_values[1]->int_value == 0 )
381 0 : poRet->int_value = INT_MAX;
382 : else
383 5 : poRet->int_value = sub_node_values[0]->int_value
384 5 : / sub_node_values[1]->int_value;
385 5 : break;
386 :
387 : case SWQ_MODULUS:
388 1 : if( sub_node_values[1]->int_value == 0 )
389 0 : poRet->int_value = INT_MAX;
390 : else
391 1 : poRet->int_value = sub_node_values[0]->int_value
392 1 : % sub_node_values[1]->int_value;
393 1 : break;
394 :
395 : default:
396 0 : CPLAssert( FALSE );
397 0 : delete poRet;
398 0 : poRet = NULL;
399 : break;
400 : }
401 : }
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* String operations. */
405 : /* -------------------------------------------------------------------- */
406 : else
407 : {
408 375802 : poRet = new swq_expr_node(0);
409 375802 : poRet->field_type = node->field_type;
410 :
411 375802 : if( node->nOperation != SWQ_ISNULL )
412 : {
413 1126952 : for( int i = 0; i < node->nSubExprCount; i++ )
414 : {
415 751369 : if( sub_node_values[i]->is_null )
416 : {
417 92 : if( poRet->field_type == SWQ_BOOLEAN )
418 : {
419 85 : poRet->int_value = FALSE;
420 85 : return poRet;
421 : }
422 7 : else if( poRet->field_type == SWQ_STRING )
423 : {
424 7 : poRet->string_value = CPLStrdup("");
425 7 : poRet->is_null = 1;
426 7 : return poRet;
427 : }
428 : }
429 : }
430 : }
431 :
432 375710 : switch( (swq_op) node->nOperation )
433 : {
434 : case SWQ_EQ:
435 : poRet->int_value =
436 125362 : strcasecmp(sub_node_values[0]->string_value,
437 250724 : sub_node_values[1]->string_value) == 0;
438 125362 : break;
439 :
440 : case SWQ_NE:
441 : poRet->int_value =
442 249863 : strcasecmp(sub_node_values[0]->string_value,
443 499726 : sub_node_values[1]->string_value) != 0;
444 249863 : break;
445 :
446 : case SWQ_GT:
447 : poRet->int_value =
448 56 : strcasecmp(sub_node_values[0]->string_value,
449 112 : sub_node_values[1]->string_value) > 0;
450 56 : break;
451 :
452 : case SWQ_LT:
453 : poRet->int_value =
454 58 : strcasecmp(sub_node_values[0]->string_value,
455 116 : sub_node_values[1]->string_value) < 0;
456 58 : break;
457 :
458 : case SWQ_GE:
459 : poRet->int_value =
460 38 : strcasecmp(sub_node_values[0]->string_value,
461 76 : sub_node_values[1]->string_value) >= 0;
462 38 : break;
463 :
464 : case SWQ_LE:
465 : poRet->int_value =
466 38 : strcasecmp(sub_node_values[0]->string_value,
467 76 : sub_node_values[1]->string_value) <= 0;
468 38 : break;
469 :
470 : case SWQ_IN:
471 : {
472 : int i;
473 39 : poRet->int_value = 0;
474 91 : for( i = 1; i < node->nSubExprCount; i++ )
475 : {
476 65 : if( strcasecmp(sub_node_values[0]->string_value,
477 65 : sub_node_values[i]->string_value) == 0 )
478 : {
479 13 : poRet->int_value = 1;
480 13 : break;
481 : }
482 : }
483 : }
484 39 : break;
485 :
486 : case SWQ_BETWEEN:
487 : poRet->int_value =
488 50 : strcasecmp(sub_node_values[0]->string_value,
489 50 : sub_node_values[1]->string_value) >= 0 &&
490 40 : strcasecmp(sub_node_values[0]->string_value,
491 140 : sub_node_values[2]->string_value) <= 0;
492 50 : break;
493 :
494 : case SWQ_LIKE:
495 : {
496 42 : char chEscape = '\0';
497 42 : if( node->nSubExprCount == 3 )
498 10 : chEscape = sub_node_values[2]->string_value[0];
499 42 : poRet->int_value = swq_test_like(sub_node_values[0]->string_value,
500 42 : sub_node_values[1]->string_value,
501 126 : chEscape);
502 42 : break;
503 : }
504 :
505 : case SWQ_ISNULL:
506 127 : poRet->int_value = sub_node_values[0]->is_null;
507 127 : break;
508 :
509 : case SWQ_CONCAT:
510 : case SWQ_ADD:
511 : {
512 23 : CPLString osResult = sub_node_values[0]->string_value;
513 : int i;
514 :
515 48 : for( i = 1; i < node->nSubExprCount; i++ )
516 25 : osResult += sub_node_values[i]->string_value;
517 :
518 23 : poRet->string_value = CPLStrdup(osResult);
519 23 : poRet->is_null = sub_node_values[0]->is_null;
520 23 : break;
521 : }
522 :
523 : case SWQ_SUBSTR:
524 : {
525 : int nOffset, nSize;
526 14 : const char *pszSrcStr = sub_node_values[0]->string_value;
527 :
528 14 : if( sub_node_values[1]->field_type == SWQ_INTEGER )
529 14 : nOffset = sub_node_values[1]->int_value;
530 0 : else if( sub_node_values[1]->field_type == SWQ_FLOAT )
531 0 : nOffset = (int) sub_node_values[1]->float_value;
532 : else
533 0 : nOffset = 0;
534 :
535 14 : if( node->nSubExprCount < 3 )
536 2 : nSize = 100000;
537 12 : else if( sub_node_values[2]->field_type == SWQ_INTEGER )
538 12 : nSize = sub_node_values[2]->int_value;
539 0 : else if( sub_node_values[2]->field_type == SWQ_FLOAT )
540 0 : nSize = (int) sub_node_values[2]->float_value;
541 : else
542 0 : nSize = 0;
543 :
544 14 : int nSrcStrLen = (int)strlen(pszSrcStr);
545 :
546 :
547 : /* In SQL, the first character is at offset 1 */
548 : /* And 0 is considered as 1 */
549 14 : if (nOffset > 0)
550 12 : nOffset --;
551 : /* Some implementations allow negative offsets, to start */
552 : /* from the end of the string */
553 2 : else if( nOffset < 0 )
554 : {
555 2 : if( nSrcStrLen + nOffset >= 0 )
556 2 : nOffset = nSrcStrLen + nOffset;
557 : else
558 0 : nOffset = 0;
559 : }
560 :
561 14 : if( nSize < 0 || nOffset > nSrcStrLen )
562 : {
563 0 : nOffset = 0;
564 0 : nSize = 0;
565 : }
566 14 : else if( nOffset + nSize > nSrcStrLen )
567 2 : nSize = nSrcStrLen - nOffset;
568 :
569 14 : CPLString osResult = pszSrcStr + nOffset;
570 14 : if( (int)osResult.size() > nSize )
571 0 : osResult.resize( nSize );
572 :
573 14 : poRet->string_value = CPLStrdup(osResult);
574 14 : poRet->is_null = sub_node_values[0]->is_null;
575 14 : break;
576 : }
577 :
578 : default:
579 0 : CPLAssert( FALSE );
580 0 : delete poRet;
581 0 : poRet = NULL;
582 : break;
583 : }
584 : }
585 :
586 596799 : return poRet;
587 : }
588 :
589 : /************************************************************************/
590 : /* SWQAutoPromoteIntegerToFloat() */
591 : /************************************************************************/
592 :
593 1428 : static void SWQAutoPromoteIntegerToFloat( swq_expr_node *poNode )
594 :
595 : {
596 1428 : if( poNode->nSubExprCount < 2 )
597 0 : return;
598 :
599 1428 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
600 : int i;
601 :
602 : // We allow mixes of integer and float, and string and dates.
603 : // When encountered, we promote integers to floats, and strings to
604 : // dates. We do that now.
605 2917 : for( i = 1; i < poNode->nSubExprCount; i++ )
606 : {
607 2285 : if( eArgType == SWQ_INTEGER
608 796 : && poNode->papoSubExpr[i]->field_type == SWQ_FLOAT )
609 26 : eArgType = SWQ_FLOAT;
610 : }
611 :
612 4345 : for( i = 0; i < poNode->nSubExprCount; i++ )
613 : {
614 2917 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
615 :
616 2917 : if( eArgType == SWQ_FLOAT
617 : && poSubNode->field_type == SWQ_INTEGER )
618 : {
619 182 : if( poSubNode->eNodeType == SNT_CONSTANT )
620 : {
621 173 : poSubNode->float_value = poSubNode->int_value;
622 173 : poSubNode->field_type = SWQ_FLOAT;
623 : }
624 : }
625 : }
626 : }
627 :
628 : /************************************************************************/
629 : /* SWQAutoPromoteStringToDateTime() */
630 : /************************************************************************/
631 :
632 1386 : static void SWQAutoPromoteStringToDateTime( swq_expr_node *poNode )
633 :
634 : {
635 1386 : if( poNode->nSubExprCount < 2 )
636 0 : return;
637 :
638 1386 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
639 : int i;
640 :
641 : // We allow mixes of integer and float, and string and dates.
642 : // When encountered, we promote integers to floats, and strings to
643 : // dates. We do that now.
644 2833 : for( i = 1; i < poNode->nSubExprCount; i++ )
645 : {
646 1447 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
647 :
648 1447 : if( eArgType == SWQ_STRING
649 : && (poSubNode->field_type == SWQ_DATE
650 : || poSubNode->field_type == SWQ_TIME
651 : || poSubNode->field_type == SWQ_TIMESTAMP) )
652 0 : eArgType = SWQ_TIMESTAMP;
653 : }
654 :
655 4219 : for( i = 0; i < poNode->nSubExprCount; i++ )
656 : {
657 2833 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
658 :
659 2833 : if( eArgType == SWQ_TIMESTAMP
660 : && (poSubNode->field_type == SWQ_STRING
661 : || poSubNode->field_type == SWQ_DATE
662 : || poSubNode->field_type == SWQ_TIME) )
663 : {
664 9 : if( poSubNode->eNodeType == SNT_CONSTANT )
665 : {
666 9 : poSubNode->field_type = SWQ_TIMESTAMP;
667 : }
668 : }
669 : }
670 : }
671 :
672 : /************************************************************************/
673 : /* SWQAutoConvertStringToNumeric() */
674 : /* */
675 : /* Convert string constants to integer or float constants */
676 : /* when there is a mix of arguments of type numeric and string */
677 : /************************************************************************/
678 :
679 1386 : static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
680 :
681 : {
682 1386 : if( poNode->nSubExprCount < 2 )
683 0 : return;
684 :
685 1386 : swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
686 : int i;
687 :
688 2830 : for( i = 1; i < poNode->nSubExprCount; i++ )
689 : {
690 1447 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
691 :
692 : /* identify the mixture of the argument type */
693 1447 : if( (eArgType == SWQ_STRING
694 : && (poSubNode->field_type == SWQ_INTEGER
695 : || poSubNode->field_type == SWQ_FLOAT)) ||
696 : (eArgType == SWQ_INTEGER
697 : && poSubNode->field_type == SWQ_STRING) )
698 : {
699 3 : eArgType = SWQ_FLOAT;
700 3 : break;
701 : }
702 : }
703 :
704 4219 : for( i = 0; i < poNode->nSubExprCount; i++ )
705 : {
706 2833 : swq_expr_node *poSubNode = poNode->papoSubExpr[i];
707 :
708 2833 : if( eArgType == SWQ_FLOAT
709 : && poSubNode->field_type == SWQ_STRING )
710 : {
711 12 : if( poSubNode->eNodeType == SNT_CONSTANT )
712 : {
713 : /* apply the string to numeric conversion */
714 10 : char* endPtr = NULL;
715 10 : poSubNode->float_value = CPLStrtod(poSubNode->string_value, &endPtr);
716 10 : if ( !(endPtr == NULL || *endPtr == '\0') )
717 : {
718 : CPLError(CE_Warning, CPLE_NotSupported,
719 : "Conversion failed when converting the string value '%s' to data type float.",
720 0 : poSubNode->string_value);
721 0 : continue;
722 : }
723 :
724 10 : poSubNode->float_value = atof(poSubNode->string_value);
725 : /* we should also fill the integer value in this case */
726 10 : poSubNode->int_value = (int)poSubNode->float_value;
727 10 : poSubNode->field_type = SWQ_FLOAT;
728 : }
729 : }
730 : }
731 : }
732 :
733 : /************************************************************************/
734 : /* SWQGeneralChecker() */
735 : /* */
736 : /* Check the general purpose functions have appropriate types, */
737 : /* and count and indicate the function return type under the */
738 : /* circumstances. */
739 : /************************************************************************/
740 :
741 1780 : swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
742 :
743 : {
744 1780 : swq_field_type eRetType = SWQ_ERROR;
745 1780 : swq_field_type eArgType = SWQ_OTHER;
746 1780 : int nArgCount = -1;
747 :
748 1780 : switch( (swq_op) poNode->nOperation )
749 : {
750 : case SWQ_AND:
751 : case SWQ_OR:
752 : case SWQ_NOT:
753 307 : eRetType = SWQ_BOOLEAN;
754 307 : break;
755 :
756 : case SWQ_EQ:
757 : case SWQ_NE:
758 : case SWQ_GT:
759 : case SWQ_LT:
760 : case SWQ_GE:
761 : case SWQ_LE:
762 : case SWQ_IN:
763 : case SWQ_BETWEEN:
764 1386 : eRetType = SWQ_BOOLEAN;
765 1386 : SWQAutoConvertStringToNumeric( poNode );
766 1386 : SWQAutoPromoteIntegerToFloat( poNode );
767 1386 : SWQAutoPromoteStringToDateTime( poNode );
768 1386 : eArgType = poNode->papoSubExpr[0]->field_type;
769 1386 : break;
770 :
771 : case SWQ_ISNULL:
772 19 : eRetType = SWQ_BOOLEAN;
773 19 : break;
774 :
775 : case SWQ_LIKE:
776 12 : eRetType = SWQ_BOOLEAN;
777 12 : eArgType = SWQ_STRING;
778 12 : break;
779 :
780 : case SWQ_MODULUS:
781 6 : eRetType = SWQ_INTEGER;
782 6 : eArgType = SWQ_INTEGER;
783 6 : break;
784 :
785 : case SWQ_ADD:
786 19 : SWQAutoPromoteIntegerToFloat( poNode );
787 19 : if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
788 2 : eRetType = eArgType = SWQ_STRING;
789 17 : else if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
790 5 : eRetType = eArgType = SWQ_FLOAT;
791 : else
792 12 : eRetType = eArgType = SWQ_INTEGER;
793 19 : break;
794 :
795 : case SWQ_SUBTRACT:
796 : case SWQ_MULTIPLY:
797 : case SWQ_DIVIDE:
798 23 : SWQAutoPromoteIntegerToFloat( poNode );
799 23 : if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
800 12 : eRetType = eArgType = SWQ_FLOAT;
801 : else
802 11 : eRetType = eArgType = SWQ_INTEGER;
803 23 : break;
804 :
805 : case SWQ_CONCAT:
806 5 : eRetType = SWQ_STRING;
807 5 : eArgType = SWQ_STRING;
808 5 : break;
809 :
810 : case SWQ_SUBSTR:
811 3 : eRetType = SWQ_STRING;
812 3 : if( poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2 )
813 : {
814 : CPLError( CE_Failure, CPLE_AppDefined,
815 : "Expected 2 or 3 arguments to SUBSTR(), but got %d.",
816 0 : poNode->nSubExprCount );
817 0 : return SWQ_ERROR;
818 : }
819 8 : if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
820 3 : || poNode->papoSubExpr[1]->field_type != SWQ_INTEGER
821 : || (poNode->nSubExprCount > 2
822 2 : && poNode->papoSubExpr[2]->field_type != SWQ_INTEGER) )
823 : {
824 : CPLError( CE_Failure, CPLE_AppDefined,
825 0 : "Wrong argument type for SUBSTR(), expected SUBSTR(string,int,int) or SUBSTR(string,int)." );
826 0 : return SWQ_ERROR;
827 : }
828 3 : break;
829 :
830 : default:
831 : {
832 : const swq_operation *poOp =
833 0 : swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
834 :
835 : CPLError( CE_Failure, CPLE_AppDefined,
836 : "SWQGeneralChecker() called on unsupported operation %s.",
837 0 : poOp->osName.c_str());
838 0 : return SWQ_ERROR;
839 : }
840 : }
841 : /* -------------------------------------------------------------------- */
842 : /* Check argument types. */
843 : /* -------------------------------------------------------------------- */
844 1780 : if( eArgType != SWQ_OTHER )
845 : {
846 : int i;
847 :
848 1448 : if( eArgType == SWQ_INTEGER )
849 771 : eArgType = SWQ_FLOAT;
850 :
851 4403 : for( i = 0; i < poNode->nSubExprCount; i++ )
852 : {
853 2960 : swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
854 2960 : if( eThisArgType == SWQ_INTEGER )
855 1544 : eThisArgType = SWQ_FLOAT;
856 :
857 2960 : if( eArgType != eThisArgType )
858 : {
859 : const swq_operation *poOp =
860 5 : swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
861 :
862 : CPLError( CE_Failure, CPLE_AppDefined,
863 : "Type mismatch or improper type of arguments to %s operator.",
864 5 : poOp->osName.c_str() );
865 5 : return SWQ_ERROR;
866 : }
867 : }
868 : }
869 :
870 : /* -------------------------------------------------------------------- */
871 : /* Validate the arg count if requested. */
872 : /* -------------------------------------------------------------------- */
873 1775 : if( nArgCount != -1
874 : && nArgCount != poNode->nSubExprCount )
875 : {
876 : const swq_operation *poOp =
877 0 : swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
878 :
879 : CPLError( CE_Failure, CPLE_AppDefined,
880 : "Expected %d arguments to %s, but got %d arguments.",
881 : nArgCount,
882 : poOp->osName.c_str(),
883 0 : poNode->nSubExprCount );
884 0 : return SWQ_ERROR;
885 : }
886 :
887 1775 : return eRetType;
888 : }
889 :
890 : /************************************************************************/
891 : /* SWQCastEvaluator() */
892 : /************************************************************************/
893 :
894 161 : swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
895 : swq_expr_node **sub_node_values )
896 :
897 : {
898 161 : swq_expr_node *poRetNode = NULL;
899 161 : swq_expr_node *poSrcNode = sub_node_values[0];
900 :
901 161 : switch( node->field_type )
902 : {
903 : case SWQ_INTEGER:
904 : {
905 15 : poRetNode = new swq_expr_node( 0 );
906 15 : poRetNode->is_null = poSrcNode->is_null;
907 :
908 15 : switch( poSrcNode->field_type )
909 : {
910 : case SWQ_INTEGER:
911 : case SWQ_BOOLEAN:
912 0 : poRetNode->int_value = poSrcNode->int_value;
913 0 : break;
914 :
915 : case SWQ_FLOAT:
916 0 : poRetNode->int_value = (int) poSrcNode->float_value;
917 0 : break;
918 :
919 : default:
920 15 : poRetNode->int_value = atoi(poSrcNode->string_value);
921 : break;
922 : }
923 : }
924 15 : break;
925 :
926 : case SWQ_FLOAT:
927 : {
928 135 : poRetNode = new swq_expr_node( 0.0 );
929 135 : poRetNode->is_null = poSrcNode->is_null;
930 :
931 135 : switch( poSrcNode->field_type )
932 : {
933 : case SWQ_INTEGER:
934 : case SWQ_BOOLEAN:
935 2 : poRetNode->float_value = poSrcNode->int_value;
936 2 : break;
937 :
938 : case SWQ_FLOAT:
939 0 : poRetNode->float_value = poSrcNode->float_value;
940 0 : break;
941 :
942 : default:
943 133 : poRetNode->float_value = atof(poSrcNode->string_value);
944 : break;
945 : }
946 : }
947 135 : break;
948 :
949 : // everything else is a string.
950 : default:
951 : {
952 11 : CPLString osRet;
953 :
954 11 : switch( poSrcNode->field_type )
955 : {
956 : case SWQ_INTEGER:
957 : case SWQ_BOOLEAN:
958 2 : osRet.Printf( "%d", poSrcNode->int_value );
959 2 : break;
960 :
961 : case SWQ_FLOAT:
962 2 : osRet.Printf( "%.15g", poSrcNode->float_value );
963 2 : break;
964 :
965 : default:
966 7 : osRet = poSrcNode->string_value;
967 : break;
968 : }
969 :
970 11 : if( node->nSubExprCount > 2 )
971 : {
972 : int nWidth;
973 :
974 11 : nWidth = sub_node_values[2]->int_value;
975 11 : if( nWidth > 0 && (int) strlen(osRet) > nWidth )
976 0 : osRet.resize(nWidth);
977 : }
978 :
979 11 : poRetNode = new swq_expr_node( osRet.c_str() );
980 11 : poRetNode->is_null = poSrcNode->is_null;
981 : }
982 : }
983 :
984 161 : return poRetNode;
985 : }
986 :
987 : /************************************************************************/
988 : /* SWQCastChecker() */
989 : /************************************************************************/
990 :
991 34 : swq_field_type SWQCastChecker( swq_expr_node *poNode )
992 :
993 : {
994 34 : swq_field_type eType = SWQ_ERROR;
995 34 : const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
996 :
997 34 : if( EQUAL(pszTypeName,"character") )
998 4 : eType = SWQ_STRING;
999 30 : else if( strcasecmp(pszTypeName,"integer") == 0 )
1000 5 : eType = SWQ_INTEGER;
1001 25 : else if( strcasecmp(pszTypeName,"float") == 0 )
1002 24 : eType = SWQ_FLOAT;
1003 1 : else if( strcasecmp(pszTypeName,"numeric") == 0 )
1004 1 : eType = SWQ_FLOAT;
1005 0 : else if( strcasecmp(pszTypeName,"timestamp") == 0 )
1006 0 : eType = SWQ_TIMESTAMP;
1007 0 : else if( strcasecmp(pszTypeName,"date") == 0 )
1008 0 : eType = SWQ_DATE;
1009 0 : else if( strcasecmp(pszTypeName,"time") == 0 )
1010 0 : eType = SWQ_TIME;
1011 : else
1012 : {
1013 : CPLError( CE_Failure, CPLE_AppDefined,
1014 : "Unrecognized typename %s in CAST operator.",
1015 0 : pszTypeName );
1016 : }
1017 :
1018 34 : poNode->field_type = eType;
1019 :
1020 34 : return eType;
1021 : }
|