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

Generated by: LCOV version 1.7