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

Generated by: LCOV version 1.7