LCOV - code coverage report
Current view: directory - ogr - swq_op_general.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 418 317 75.8 %
Date: 2011-12-18 Functions: 8 8 100.0 %

       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                 : }

Generated by: LCOV version 1.7