LCOV - code coverage report
Current view: directory - ogr - swq.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 292 266 91.1 %
Date: 2011-12-18 Functions: 11 10 90.9 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Component: OGDI Driver Support Library
       4                 :  * Purpose: Generic SQL WHERE Expression Implementation.
       5                 :  * Author: Frank Warmerdam <warmerdam@pobox.com>
       6                 :  * 
       7                 :  ******************************************************************************
       8                 :  * Copyright (C) 2001 Information Interoperability Institute (3i)
       9                 :  *
      10                 :  * Permission to use, copy, modify and distribute this software and
      11                 :  * its documentation for any purpose and without fee is hereby granted,
      12                 :  * provided that the above copyright notice appear in all copies, that
      13                 :  * both the copyright notice and this permission notice appear in
      14                 :  * supporting documentation, and that the name of 3i not be used 
      15                 :  * in advertising or publicity pertaining to distribution of the software 
      16                 :  * without specific, written prior permission.  3i makes no
      17                 :  * representations about the suitability of this software for any purpose.
      18                 :  * It is provided "as is" without express or implied warranty.
      19                 :  ****************************************************************************/
      20                 : 
      21                 : #include <ctype.h>
      22                 : 
      23                 : #include "cpl_conv.h"
      24                 : #include "cpl_multiproc.h"
      25                 : #include "swq.h"
      26                 : #include "swq_parser.hpp"
      27                 : 
      28                 : #define YYSTYPE  swq_expr_node*
      29                 : 
      30                 : /************************************************************************/
      31                 : /*                               swqlex()                               */
      32                 : /*                                                                      */
      33                 : /*      Read back a token from the input.                               */
      34                 : /************************************************************************/
      35                 : 
      36            7404 : int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
      37                 : {
      38            7404 :     const char *pszInput = context->pszNext;
      39                 : 
      40            7404 :     *ppNode = NULL;
      41                 : 
      42                 : /* -------------------------------------------------------------------- */
      43                 : /*      Do we have a start symbol to return?                            */
      44                 : /* -------------------------------------------------------------------- */
      45            7404 :     if( context->nStartToken != 0 )
      46                 :     {
      47             641 :         int nRet = context->nStartToken;
      48             641 :         context->nStartToken = 0;
      49             641 :         return nRet;
      50                 :     }
      51                 : 
      52                 : /* -------------------------------------------------------------------- */
      53                 : /*      Skip white space.                                               */
      54                 : /* -------------------------------------------------------------------- */
      55           15983 :     while( *pszInput == ' ' || *pszInput == '\t'
      56                 :            || *pszInput == 10 || *pszInput == 13 )
      57            2457 :         pszInput++;
      58                 : 
      59            6763 :     if( *pszInput == '\0' )
      60                 :     {
      61             599 :         context->pszNext = pszInput;
      62             599 :         return EOF; 
      63                 :     }
      64                 : 
      65                 : /* -------------------------------------------------------------------- */
      66                 : /*      Handle string constants.                                        */
      67                 : /* -------------------------------------------------------------------- */
      68            6164 :     if( *pszInput == '"' || *pszInput == '\'' )
      69                 :     {
      70                 :         char *token;
      71                 :         int i_token;
      72                 : 
      73             218 :         pszInput++;
      74                 : 
      75             218 :         token = (char *) CPLMalloc(strlen(pszInput)+1);
      76             218 :         i_token = 0;
      77                 : 
      78            2339 :         while( *pszInput != '\0' )
      79                 :         {
      80            2120 :             if( *pszInput == '\\' && pszInput[1] == '"' )
      81               0 :                 pszInput++;
      82            2120 :             else if( *pszInput == '\\' && pszInput[1] == '\'' )
      83               0 :                 pszInput++;
      84            2120 :             else if( *pszInput == '\'' && pszInput[1] == '\'' )
      85               0 :                 pszInput++;
      86            2120 :             else if( *pszInput == '"' )
      87                 :             {
      88              27 :                 pszInput++;
      89              27 :                 break;
      90                 :             }
      91            2093 :             else if( *pszInput == '\'' )
      92                 :             {
      93             190 :                 pszInput++;
      94             190 :                 break;
      95                 :             }
      96                 :             
      97            1903 :             token[i_token++] = *(pszInput++);
      98                 :         }
      99             218 :         token[i_token] = '\0';
     100                 : 
     101             218 :         *ppNode = new swq_expr_node( token );
     102             218 :         CPLFree( token );
     103                 : 
     104             218 :         context->pszNext = pszInput;
     105                 : 
     106             218 :         return SWQT_STRING;
     107                 :     }
     108                 : 
     109                 : /* -------------------------------------------------------------------- */
     110                 : /*      Handle numbers.                                                 */
     111                 : /* -------------------------------------------------------------------- */
     112            5946 :     else if( *pszInput >= '0' && *pszInput <= '9' )
     113                 :     {
     114             341 :         CPLString osToken;
     115             341 :         const char *pszNext = pszInput + 1;
     116                 : 
     117             341 :         osToken += *pszInput;
     118                 : 
     119                 :         // collect non-decimal part of number
     120            1106 :         while( *pszNext >= '0' && *pszNext <= '9' )
     121             424 :             osToken += *(pszNext++);
     122                 : 
     123                 :         // collect decimal places.
     124             341 :         if( *pszNext == '.' )
     125                 :         {
     126              27 :             osToken += *(pszNext++);
     127             105 :             while( *pszNext >= '0' && *pszNext <= '9' )
     128              51 :                 osToken += *(pszNext++);
     129                 :         }
     130                 : 
     131                 :         // collect exponent
     132             341 :         if( *pszNext == 'e' || *pszNext == 'E' )
     133                 :         {
     134               1 :             osToken += *(pszNext++);
     135               1 :             if( *pszNext == '-' || *pszNext == '+' )
     136               1 :                 osToken += *(pszNext++);
     137               3 :             while( *pszNext >= '0' && *pszNext <= '9' )
     138               1 :                 osToken += *(pszNext++);
     139                 :         }
     140                 : 
     141             341 :         context->pszNext = pszNext;
     142                 : 
     143             341 :         if( strstr(osToken,".") 
     144                 :             || strstr(osToken,"e") 
     145                 :             || strstr(osToken,"E") )
     146                 :         {
     147              28 :             *ppNode = new swq_expr_node( CPLAtof(osToken) );
     148                 :         }
     149                 :         else
     150                 :         {
     151             313 :             *ppNode = new swq_expr_node( atoi(osToken) );
     152                 :         }
     153                 : 
     154             341 :         return SWQT_NUMBER;
     155                 :     }
     156                 : 
     157                 : /* -------------------------------------------------------------------- */
     158                 : /*      Handle alpha-numerics.                                          */
     159                 : /* -------------------------------------------------------------------- */
     160            5605 :     else if( isalnum( *pszInput ) )
     161                 :     {
     162            3229 :         int nReturn = SWQT_IDENTIFIER;
     163            3229 :         CPLString osToken;
     164            3229 :         const char *pszNext = pszInput + 1;
     165                 : 
     166            3229 :         osToken += *pszInput;
     167                 : 
     168                 :         // collect text characters
     169           18838 :         while( isalnum( *pszNext ) || *pszNext == '_' 
     170                 :                || ((unsigned char) *pszNext) > 127 )
     171           12380 :             osToken += *(pszNext++);
     172                 : 
     173            3229 :         context->pszNext = pszNext;
     174                 : 
     175            3229 :         if( EQUAL(osToken,"IN") )
     176              36 :             nReturn = SWQT_IN;
     177            3193 :         else if( EQUAL(osToken,"LIKE") )
     178              12 :             nReturn = SWQT_LIKE;
     179            3181 :         else if( EQUAL(osToken,"ILIKE") )
     180               1 :             nReturn = SWQT_LIKE;
     181            3180 :         else if( EQUAL(osToken,"ESCAPE") )
     182               2 :             nReturn = SWQT_ESCAPE;
     183            3178 :         else if( EQUAL(osToken,"NULL") )
     184              15 :             nReturn = SWQT_NULL;
     185            3163 :         else if( EQUAL(osToken,"IS") )
     186              14 :             nReturn = SWQT_IS;
     187            3149 :         else if( EQUAL(osToken,"NOT") )
     188              16 :             nReturn = SWQT_NOT;
     189            3133 :         else if( EQUAL(osToken,"AND") )
     190              43 :             nReturn = SWQT_AND;
     191            3090 :         else if( EQUAL(osToken,"OR") )
     192               6 :             nReturn = SWQT_OR;
     193            3084 :         else if( EQUAL(osToken,"BETWEEN") )
     194               4 :             nReturn = SWQT_BETWEEN;
     195            3080 :         else if( EQUAL(osToken,"SELECT") )
     196             299 :             nReturn = SWQT_SELECT;
     197            2781 :         else if( EQUAL(osToken,"LEFT") )
     198              25 :             nReturn = SWQT_LEFT;
     199            2756 :         else if( EQUAL(osToken,"JOIN") )
     200              24 :             nReturn = SWQT_JOIN;
     201            2732 :         else if( EQUAL(osToken,"WHERE") )
     202              82 :             nReturn = SWQT_WHERE;
     203            2650 :         else if( EQUAL(osToken,"ON") )
     204              22 :             nReturn = SWQT_ON;
     205            2628 :         else if( EQUAL(osToken,"ORDER") )
     206              24 :             nReturn = SWQT_ORDER;
     207            2604 :         else if( EQUAL(osToken,"BY") )
     208              24 :             nReturn = SWQT_BY;
     209            2580 :         else if( EQUAL(osToken,"FROM") )
     210             264 :             nReturn = SWQT_FROM;
     211            2316 :         else if( EQUAL(osToken,"AS") )
     212              53 :             nReturn = SWQT_AS;
     213            2263 :         else if( EQUAL(osToken,"ASC") )
     214              11 :             nReturn = SWQT_ASC;
     215            2252 :         else if( EQUAL(osToken,"DESC") )
     216               7 :             nReturn = SWQT_DESC;
     217            2245 :         else if( EQUAL(osToken,"DISTINCT") )
     218              29 :             nReturn = SWQT_DISTINCT;
     219            2216 :         else if( EQUAL(osToken,"CAST") )
     220              43 :             nReturn = SWQT_CAST;
     221                 :         else
     222                 :         {
     223            2173 :             *ppNode = new swq_expr_node( osToken );
     224            2173 :             nReturn = SWQT_IDENTIFIER;
     225                 :         }
     226                 : 
     227            3229 :         return nReturn;
     228                 :     }
     229                 : 
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Handle special tokens.                                          */
     232                 : /* -------------------------------------------------------------------- */
     233                 :     else
     234                 :     {
     235            2376 :         context->pszNext = pszInput+1;
     236            2376 :         return *pszInput;
     237                 :     }
     238                 : }
     239                 : 
     240                 : /************************************************************************/
     241                 : /*                        swq_select_summarize()                        */
     242                 : /************************************************************************/
     243                 : 
     244                 : const char *
     245             244 : swq_select_summarize( swq_select *select_info, 
     246                 :                       int dest_column, const char *value )
     247                 : 
     248                 : {
     249             244 :     swq_col_def *def = select_info->column_defs + dest_column;
     250                 :     swq_summary *summary;
     251                 : 
     252                 : /* -------------------------------------------------------------------- */
     253                 : /*      Do various checking.                                            */
     254                 : /* -------------------------------------------------------------------- */
     255             244 :     if( select_info->query_mode == SWQM_RECORDSET )
     256               0 :         return "swq_select_summarize() called on non-summary query.";
     257                 : 
     258             244 :     if( dest_column < 0 || dest_column >= select_info->result_columns )
     259               0 :         return "dest_column out of range in swq_select_summarize().";
     260                 : 
     261             244 :     if( def->col_func == SWQCF_NONE && !def->distinct_flag )
     262               0 :         return NULL;
     263                 : 
     264                 : /* -------------------------------------------------------------------- */
     265                 : /*      Create the summary information if this is the first row         */
     266                 : /*      being processed.                                                */
     267                 : /* -------------------------------------------------------------------- */
     268             244 :     if( select_info->column_summary == NULL && value != NULL )
     269                 :     {
     270                 :         int i;
     271                 : 
     272                 :         select_info->column_summary = (swq_summary *) 
     273              19 :             CPLMalloc(sizeof(swq_summary) * select_info->result_columns);
     274                 :         memset( select_info->column_summary, 0, 
     275              19 :                 sizeof(swq_summary) * select_info->result_columns );
     276                 : 
     277              46 :         for( i = 0; i < select_info->result_columns; i++ )
     278                 :         {
     279              27 :             select_info->column_summary[i].min = 1e20;
     280              27 :             select_info->column_summary[i].max = -1e20;
     281                 :         }
     282                 :     }
     283                 : 
     284                 : /* -------------------------------------------------------------------- */
     285                 : /*      If distinct processing is on, process that now.                 */
     286                 : /* -------------------------------------------------------------------- */
     287             244 :     summary = select_info->column_summary + dest_column;
     288                 :     
     289             244 :     if( def->distinct_flag )
     290                 :     {
     291                 :         int  i;
     292                 : 
     293                 :         /* This should be implemented with a much more complicated
     294                 :            data structure to achieve any sort of efficiency. */
     295             801 :         for( i = 0; i < summary->count; i++ )
     296                 :         {
     297             735 :             if( value == NULL )
     298                 :             {
     299              92 :                 if (summary->distinct_list[i] == NULL)
     300               6 :                     break;
     301                 :             }
     302            1286 :             else if( summary->distinct_list[i] != NULL &&
     303             643 :                      strcmp(value,summary->distinct_list[i]) == 0 )
     304             125 :                 break;
     305                 :         }
     306                 :         
     307             197 :         if( i == summary->count )
     308                 :         {
     309              66 :             char  **old_list = summary->distinct_list;
     310                 :             
     311                 :             summary->distinct_list = (char **) 
     312              66 :                 CPLMalloc(sizeof(char *) * (summary->count+1));
     313                 :             memcpy( summary->distinct_list, old_list, 
     314              66 :                     sizeof(char *) * summary->count );
     315             132 :             summary->distinct_list[(summary->count)++] = 
     316              66 :                 (value != NULL) ? CPLStrdup( value ) : NULL;
     317                 : 
     318              66 :             CPLFree(old_list);
     319                 :         }
     320                 :     }
     321                 : 
     322                 : /* -------------------------------------------------------------------- */
     323                 : /*      Process various options.                                        */
     324                 : /* -------------------------------------------------------------------- */
     325                 : 
     326             244 :     switch( def->col_func )
     327                 :     {
     328                 :       case SWQCF_MIN:
     329              10 :         if( value != NULL && value[0] != '\0' )
     330                 :         {
     331              10 :             double df_val = CPLAtof(value);
     332              10 :             if( df_val < summary->min )
     333               3 :                 summary->min = df_val;
     334                 :         }
     335              10 :         break;
     336                 :       case SWQCF_MAX:
     337               7 :         if( value != NULL && value[0] != '\0' )
     338                 :         {
     339               7 :             double df_val = CPLAtof(value);
     340               7 :             if( df_val > summary->max )
     341               2 :                 summary->max = df_val;
     342                 :         }
     343               7 :         break;
     344                 :       case SWQCF_AVG:
     345                 :       case SWQCF_SUM:
     346               2 :         if( value != NULL && value[0] != '\0' )
     347                 :         {
     348               0 :             summary->count++;
     349               0 :             summary->sum += CPLAtof(value);
     350                 :         }
     351               2 :         break;
     352                 : 
     353                 :       case SWQCF_COUNT:
     354              40 :         if( value != NULL && !def->distinct_flag )
     355              28 :             summary->count++;
     356              40 :         break;
     357                 : 
     358                 :       case SWQCF_NONE:
     359             185 :         break;
     360                 : 
     361                 :       case SWQCF_CUSTOM:
     362               0 :         return "swq_select_summarize() called on custom field function.";
     363                 : 
     364                 :       default:
     365               0 :         return "swq_select_summarize() - unexpected col_func";
     366                 :     }
     367                 : 
     368             244 :     return NULL;
     369                 : }
     370                 : /************************************************************************/
     371                 : /*                      sort comparison functions.                      */
     372                 : /************************************************************************/
     373                 : 
     374              52 : static int FORCE_CDECL swq_compare_int( const void *item1, const void *item2 )
     375                 : {
     376                 :     int  v1, v2;
     377                 : 
     378              52 :     const char* pszStr1 = *((const char **) item1);
     379              52 :     const char* pszStr2 = *((const char **) item2);
     380              52 :     if (pszStr1 == NULL)
     381               0 :         return (pszStr2 == NULL) ? 0 : -1;
     382              52 :     else if (pszStr2 == NULL)
     383              10 :         return 1;
     384                 : 
     385              42 :     v1 = atoi(pszStr1);
     386              42 :     v2 = atoi(pszStr2);
     387                 : 
     388              42 :     if( v1 < v2 )
     389              16 :         return -1;
     390              26 :     else if( v1 == v2 )
     391               0 :         return 0;
     392                 :     else
     393              26 :         return 1;
     394                 : }
     395                 : 
     396              25 : static int FORCE_CDECL swq_compare_real( const void *item1, const void *item2 )
     397                 : {
     398                 :     double  v1, v2;
     399                 : 
     400              25 :     const char* pszStr1 = *((const char **) item1);
     401              25 :     const char* pszStr2 = *((const char **) item2);
     402              25 :     if (pszStr1 == NULL)
     403               0 :         return (pszStr2 == NULL) ? 0 : -1;
     404              25 :     else if (pszStr2 == NULL)
     405               2 :         return 1;
     406                 : 
     407              23 :     v1 = CPLAtof(pszStr1);
     408              23 :     v2 = CPLAtof(pszStr2);
     409                 : 
     410              23 :     if( v1 < v2 )
     411               9 :         return -1;
     412              14 :     else if( v1 == v2 )
     413               0 :         return 0;
     414                 :     else
     415              14 :         return 1;
     416                 : }
     417                 : 
     418              14 : static int FORCE_CDECL swq_compare_string( const void *item1, const void *item2 )
     419                 : {
     420              14 :     const char* pszStr1 = *((const char **) item1);
     421              14 :     const char* pszStr2 = *((const char **) item2);
     422              14 :     if (pszStr1 == NULL)
     423               0 :         return (pszStr2 == NULL) ? 0 : -1;
     424              14 :     else if (pszStr2 == NULL)
     425               2 :         return 1;
     426                 : 
     427              12 :     return strcmp( pszStr1, pszStr2 );
     428                 : }
     429                 : 
     430                 : /************************************************************************/
     431                 : /*                    swq_select_finish_summarize()                     */
     432                 : /*                                                                      */
     433                 : /*      Call to complete summarize work.  Does stuff like ordering      */
     434                 : /*      the distinct list for instance.                                 */
     435                 : /************************************************************************/
     436                 : 
     437              24 : const char *swq_select_finish_summarize( swq_select *select_info )
     438                 : 
     439                 : {
     440                 :     int (FORCE_CDECL *compare_func)(const void *, const void*);
     441              24 :     int count = 0;
     442              24 :     char **distinct_list = NULL;
     443                 : 
     444              24 :     if( select_info->query_mode != SWQM_DISTINCT_LIST 
     445                 :         || select_info->order_specs == 0 )
     446              13 :         return NULL;
     447                 : 
     448              11 :     if( select_info->order_specs > 1 )
     449               0 :         return "Can't ORDER BY a DISTINCT list by more than one key.";
     450                 : 
     451              22 :     if( select_info->order_defs[0].field_index != 
     452              11 :         select_info->column_defs[0].field_index )
     453               0 :         return "Only selected DISTINCT field can be used for ORDER BY.";
     454                 : 
     455              11 :     if( select_info->column_summary == NULL )
     456               0 :         return NULL;
     457                 : 
     458              11 :     if( select_info->column_defs[0].field_type == SWQ_INTEGER )
     459               4 :         compare_func = swq_compare_int;
     460               7 :     else if( select_info->column_defs[0].field_type == SWQ_FLOAT )
     461               4 :         compare_func = swq_compare_real;
     462                 :     else
     463               3 :         compare_func = swq_compare_string;
     464                 : 
     465              11 :     distinct_list = select_info->column_summary[0].distinct_list;
     466              11 :     count = select_info->column_summary[0].count;
     467                 : 
     468              11 :     qsort( distinct_list, count, sizeof(char *), compare_func );
     469                 : 
     470                 : /* -------------------------------------------------------------------- */
     471                 : /*      Do we want the list ascending in stead of descending?           */
     472                 : /* -------------------------------------------------------------------- */
     473              11 :     if( !select_info->order_defs[0].ascending_flag )
     474                 :     {
     475                 :         char *saved;
     476                 :         int i;
     477                 : 
     478              21 :         for( i = 0; i < count/2; i++ )
     479                 :         {
     480              15 :             saved = distinct_list[i];
     481              15 :             distinct_list[i] = distinct_list[count-i-1];
     482              15 :             distinct_list[count-i-1] = saved;
     483                 :         }
     484                 :     }
     485                 : 
     486              11 :     return NULL;
     487                 : }
     488                 : 
     489                 : /************************************************************************/
     490                 : /*                          swq_select_free()                           */
     491                 : /************************************************************************/
     492                 : 
     493               0 : void swq_select_free( swq_select *select_info )
     494                 : 
     495                 : {
     496               0 :     delete select_info;
     497               0 : }
     498                 : 
     499                 : /************************************************************************/
     500                 : /*                         swq_identify_field()                         */
     501                 : /************************************************************************/
     502                 : 
     503            2134 : int swq_identify_field( const char *token, swq_field_list *field_list,
     504                 :                         swq_field_type *this_type, int *table_id )
     505                 : 
     506                 : {
     507                 :     int i;
     508                 :     char table_name[128];
     509            2134 :     const char *field_token = token;
     510                 :     int   tables_enabled;
     511                 : 
     512            3724 :     if( field_list->table_count > 0 && field_list->table_ids != NULL )
     513            1590 :         tables_enabled = TRUE;
     514                 :     else
     515             544 :         tables_enabled = FALSE;
     516                 : 
     517                 : /* -------------------------------------------------------------------- */
     518                 : /*      Parse out table name if present, and table support enabled.     */
     519                 : /* -------------------------------------------------------------------- */
     520            2134 :     table_name[0] = '\0';
     521            2134 :     if( tables_enabled && strchr(token, '.') != NULL )
     522                 :     {
     523              93 :         int dot_offset = (int)(strchr(token,'.') - token);
     524                 : 
     525              93 :         if( dot_offset < (int) sizeof(table_name) )
     526                 :         {
     527              93 :             strncpy( table_name, token, dot_offset );
     528              93 :             table_name[dot_offset] = '\0';
     529              93 :             field_token = token + dot_offset + 1;
     530                 :         }
     531                 :     }
     532                 : 
     533                 : /* -------------------------------------------------------------------- */
     534                 : /*      Search for matching field.                                      */
     535                 : /* -------------------------------------------------------------------- */
     536            6452 :     for( i = 0; i < field_list->count; i++ )
     537                 :     {
     538            6172 :         int  t_id = 0;
     539                 : 
     540            6172 :         if( !EQUAL( field_list->names[i], field_token ) )
     541            4287 :             continue;
     542                 : 
     543                 :         /* Do the table specifications match? */
     544            1885 :         if( tables_enabled )
     545                 :         {
     546            1501 :             t_id = field_list->table_ids[i];
     547            1622 :             if( table_name[0] != '\0' 
     548             121 :                 && !EQUAL(table_name,field_list->table_defs[t_id].table_alias))
     549              31 :                 continue;
     550                 : 
     551                 : //            if( t_id != 0 && table_name[0] == '\0' )
     552                 : //                continue;
     553                 :         }
     554                 : 
     555                 :         /* We have a match, return various information */
     556            1854 :         if( this_type != NULL )
     557                 :         {
     558            1797 :             if( field_list->types != NULL )
     559            1797 :                 *this_type = field_list->types[i];
     560                 :             else
     561               0 :                 *this_type = SWQ_OTHER;
     562                 :         }
     563                 :         
     564            1854 :         if( table_id != NULL )
     565            1854 :             *table_id = t_id;
     566                 : 
     567            1854 :         if( field_list->ids == NULL )
     568             384 :             return i;
     569                 :         else
     570            1470 :             return field_list->ids[i];
     571                 :     }
     572                 : 
     573                 : /* -------------------------------------------------------------------- */
     574                 : /*      No match, return failure.                                       */
     575                 : /* -------------------------------------------------------------------- */
     576             280 :     if( this_type != NULL )
     577             277 :         *this_type = SWQ_OTHER;
     578                 : 
     579             280 :     if( table_id != NULL )
     580             280 :         *table_id = 0;
     581                 : 
     582             280 :     return -1;
     583                 : }
     584                 : 
     585                 : /************************************************************************/
     586                 : /*                          swq_expr_compile()                          */
     587                 : /************************************************************************/
     588                 : 
     589             338 : CPLErr swq_expr_compile( const char *where_clause,
     590                 :                          int field_count,
     591                 :                          char **field_names, 
     592                 :                          swq_field_type *field_types, 
     593                 :                          swq_expr_node **expr_out )
     594                 : 
     595                 : {
     596                 :     swq_field_list  field_list;
     597                 : 
     598             338 :     field_list.count = field_count;
     599             338 :     field_list.names = field_names;
     600             338 :     field_list.types = field_types;
     601             338 :     field_list.table_ids = NULL;
     602             338 :     field_list.ids = NULL;
     603                 :     
     604             338 :     field_list.table_count = 0;
     605             338 :     field_list.table_defs = NULL;
     606                 : 
     607             338 :     return swq_expr_compile2( where_clause, &field_list, expr_out );
     608                 : }
     609                 : 
     610                 : 
     611                 : /************************************************************************/
     612                 : /*                         swq_expr_compile2()                          */
     613                 : /************************************************************************/
     614                 : 
     615             338 : CPLErr swq_expr_compile2( const char *where_clause, 
     616                 :                           swq_field_list *field_list,
     617                 :                           swq_expr_node **expr_out )
     618                 : 
     619                 : {
     620                 : 
     621             338 :     swq_parse_context context;
     622                 : 
     623             338 :     context.pszInput = where_clause;
     624             338 :     context.pszNext = where_clause;
     625             338 :     context.nStartToken = SWQT_LOGICAL_START;
     626                 :     
     627             338 :     if( swqparse( &context ) == 0 
     628                 :         && context.poRoot->Check( field_list ) != SWQ_ERROR )
     629                 :     {
     630             338 :         *expr_out = context.poRoot;
     631                 : 
     632             338 :         return CE_None;
     633                 :     }
     634                 :     else
     635                 :     {
     636               0 :         delete context.poRoot;
     637               0 :         *expr_out = NULL;
     638               0 :         return CE_Failure;
     639                 :     }
     640                 : }
     641                 : 
     642                 : /************************************************************************/
     643                 : /*                        swq_is_reserved_keyword()                     */
     644                 : /************************************************************************/
     645                 : 
     646                 : static const char* apszSQLReservedKeywords[] = {
     647                 :     "OR",
     648                 :     "AND",
     649                 :     "NOT",
     650                 :     "LIKE",
     651                 :     "IS",
     652                 :     "NULL",
     653                 :     "IN",
     654                 :     "BETWEEN",
     655                 :     "CAST",
     656                 :     "DISTINCT",
     657                 :     "ESCAPE",
     658                 :     "SELECT",
     659                 :     "LEFT",
     660                 :     "JOIN",
     661                 :     "WHERE",
     662                 :     "ON",
     663                 :     "ORDER",
     664                 :     "BY",
     665                 :     "FROM",
     666                 :     "AS",
     667                 :     "ASC",
     668                 :     "DESC"
     669                 : };
     670                 : 
     671              55 : int swq_is_reserved_keyword(const char* pszStr)
     672                 : {
     673            1265 :     for(int i = 0; i < (int)(sizeof(apszSQLReservedKeywords)/sizeof(char*)); i++)
     674                 :     {
     675            1210 :         if (EQUAL(pszStr, apszSQLReservedKeywords[i]))
     676               0 :             return TRUE;
     677                 :     }
     678              55 :     return FALSE;
     679                 : }

Generated by: LCOV version 1.7