LCOV - code coverage report
Current view: directory - ogr - swq.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 303 276 91.1 %
Date: 2012-12-26 Functions: 12 11 91.7 %

       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           14738 : int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
      37                 : {
      38           14738 :     const char *pszInput = context->pszNext;
      39                 : 
      40           14738 :     *ppNode = NULL;
      41                 : 
      42                 : /* -------------------------------------------------------------------- */
      43                 : /*      Do we have a start symbol to return?                            */
      44                 : /* -------------------------------------------------------------------- */
      45           14738 :     if( context->nStartToken != 0 )
      46                 :     {
      47            1463 :         int nRet = context->nStartToken;
      48            1463 :         context->nStartToken = 0;
      49            1463 :         return nRet;
      50                 :     }
      51                 : 
      52                 : /* -------------------------------------------------------------------- */
      53                 : /*      Skip white space.                                               */
      54                 : /* -------------------------------------------------------------------- */
      55           32826 :     while( *pszInput == ' ' || *pszInput == '\t'
      56                 :            || *pszInput == 10 || *pszInput == 13 )
      57            6276 :         pszInput++;
      58                 : 
      59           13275 :     if( *pszInput == '\0' )
      60                 :     {
      61            1394 :         context->pszNext = pszInput;
      62            1394 :         return EOF; 
      63                 :     }
      64                 : 
      65                 : /* -------------------------------------------------------------------- */
      66                 : /*      Handle string constants.                                        */
      67                 : /* -------------------------------------------------------------------- */
      68           11881 :     if( *pszInput == '"' || *pszInput == '\'' )
      69                 :     {
      70                 :         char *token;
      71                 :         int i_token;
      72             498 :         char chQuote = *pszInput;
      73             498 :         int bFoundEndQuote = FALSE;
      74                 : 
      75             498 :         pszInput++;
      76                 : 
      77             498 :         token = (char *) CPLMalloc(strlen(pszInput)+1);
      78             498 :         i_token = 0;
      79                 : 
      80            4171 :         while( *pszInput != '\0' )
      81                 :         {
      82            3671 :             if( *pszInput == '\\' && pszInput[1] == '"' )
      83               0 :                 pszInput++;
      84            3671 :             else if( *pszInput == '\\' && pszInput[1] == '\'' )
      85               0 :                 pszInput++;
      86            3671 :             else if( *pszInput == '\'' && pszInput[1] == '\'' )
      87               0 :                 pszInput++;
      88            3671 :             else if( *pszInput == chQuote )
      89                 :             {
      90             496 :                 pszInput++;
      91             496 :                 bFoundEndQuote = TRUE;
      92             496 :                 break;
      93                 :             }
      94                 :             
      95            3175 :             token[i_token++] = *(pszInput++);
      96                 :         }
      97             498 :         token[i_token] = '\0';
      98                 : 
      99             498 :         if( !bFoundEndQuote )
     100                 :         {
     101                 :             CPLError(CE_Failure, CPLE_AppDefined,
     102               2 :                      "Did not find end-of-string character");
     103               2 :             CPLFree( token );
     104               2 :             return 0;
     105                 :         }
     106                 : 
     107             496 :         *ppNode = new swq_expr_node( token );
     108             496 :         CPLFree( token );
     109                 : 
     110             496 :         context->pszNext = pszInput;
     111                 : 
     112             496 :         return SWQT_STRING;
     113                 :     }
     114                 : 
     115                 : /* -------------------------------------------------------------------- */
     116                 : /*      Handle numbers.                                                 */
     117                 : /* -------------------------------------------------------------------- */
     118           11383 :     else if( *pszInput >= '0' && *pszInput <= '9' )
     119                 :     {
     120            1551 :         CPLString osToken;
     121            1551 :         const char *pszNext = pszInput + 1;
     122                 : 
     123            1551 :         osToken += *pszInput;
     124                 : 
     125                 :         // collect non-decimal part of number
     126            3841 :         while( *pszNext >= '0' && *pszNext <= '9' )
     127             739 :             osToken += *(pszNext++);
     128                 : 
     129                 :         // collect decimal places.
     130            1551 :         if( *pszNext == '.' )
     131                 :         {
     132             333 :             osToken += *(pszNext++);
     133            1294 :             while( *pszNext >= '0' && *pszNext <= '9' )
     134             628 :                 osToken += *(pszNext++);
     135                 :         }
     136                 : 
     137                 :         // collect exponent
     138            1551 :         if( *pszNext == 'e' || *pszNext == 'E' )
     139                 :         {
     140               1 :             osToken += *(pszNext++);
     141               1 :             if( *pszNext == '-' || *pszNext == '+' )
     142               1 :                 osToken += *(pszNext++);
     143               3 :             while( *pszNext >= '0' && *pszNext <= '9' )
     144               1 :                 osToken += *(pszNext++);
     145                 :         }
     146                 : 
     147            1551 :         context->pszNext = pszNext;
     148                 : 
     149            1551 :         if( strstr(osToken,".") 
     150                 :             || strstr(osToken,"e") 
     151                 :             || strstr(osToken,"E") )
     152                 :         {
     153             334 :             *ppNode = new swq_expr_node( CPLAtof(osToken) );
     154                 :         }
     155                 :         else
     156                 :         {
     157            1217 :             *ppNode = new swq_expr_node( atoi(osToken) );
     158                 :         }
     159                 : 
     160            1551 :         return SWQT_NUMBER;
     161                 :     }
     162                 : 
     163                 : /* -------------------------------------------------------------------- */
     164                 : /*      Handle alpha-numerics.                                          */
     165                 : /* -------------------------------------------------------------------- */
     166            9832 :     else if( isalnum( *pszInput ) )
     167                 :     {
     168            5390 :         int nReturn = SWQT_IDENTIFIER;
     169            5390 :         CPLString osToken;
     170            5390 :         const char *pszNext = pszInput + 1;
     171                 : 
     172            5390 :         osToken += *pszInput;
     173                 : 
     174                 :         // collect text characters
     175           31579 :         while( isalnum( *pszNext ) || *pszNext == '_' 
     176                 :                || ((unsigned char) *pszNext) > 127 )
     177           20799 :             osToken += *(pszNext++);
     178                 : 
     179            5390 :         context->pszNext = pszNext;
     180                 : 
     181            5390 :         if( EQUAL(osToken,"IN") )
     182              48 :             nReturn = SWQT_IN;
     183            5342 :         else if( EQUAL(osToken,"LIKE") )
     184              12 :             nReturn = SWQT_LIKE;
     185            5330 :         else if( EQUAL(osToken,"ILIKE") )
     186               1 :             nReturn = SWQT_LIKE;
     187            5329 :         else if( EQUAL(osToken,"ESCAPE") )
     188               2 :             nReturn = SWQT_ESCAPE;
     189            5327 :         else if( EQUAL(osToken,"NULL") )
     190              35 :             nReturn = SWQT_NULL;
     191            5292 :         else if( EQUAL(osToken,"IS") )
     192              24 :             nReturn = SWQT_IS;
     193            5268 :         else if( EQUAL(osToken,"NOT") )
     194              22 :             nReturn = SWQT_NOT;
     195            5246 :         else if( EQUAL(osToken,"AND") )
     196             301 :             nReturn = SWQT_AND;
     197            4945 :         else if( EQUAL(osToken,"OR") )
     198              23 :             nReturn = SWQT_OR;
     199            4922 :         else if( EQUAL(osToken,"BETWEEN") )
     200              34 :             nReturn = SWQT_BETWEEN;
     201            4888 :         else if( EQUAL(osToken,"SELECT") )
     202             590 :             nReturn = SWQT_SELECT;
     203            4298 :         else if( EQUAL(osToken,"LEFT") )
     204              25 :             nReturn = SWQT_LEFT;
     205            4273 :         else if( EQUAL(osToken,"JOIN") )
     206              26 :             nReturn = SWQT_JOIN;
     207            4247 :         else if( EQUAL(osToken,"WHERE") )
     208             319 :             nReturn = SWQT_WHERE;
     209            3928 :         else if( EQUAL(osToken,"ON") )
     210              24 :             nReturn = SWQT_ON;
     211            3904 :         else if( EQUAL(osToken,"ORDER") )
     212              27 :             nReturn = SWQT_ORDER;
     213            3877 :         else if( EQUAL(osToken,"BY") )
     214              27 :             nReturn = SWQT_BY;
     215            3850 :         else if( EQUAL(osToken,"FROM") )
     216             553 :             nReturn = SWQT_FROM;
     217            3297 :         else if( EQUAL(osToken,"AS") )
     218              63 :             nReturn = SWQT_AS;
     219            3234 :         else if( EQUAL(osToken,"ASC") )
     220              11 :             nReturn = SWQT_ASC;
     221            3223 :         else if( EQUAL(osToken,"DESC") )
     222               9 :             nReturn = SWQT_DESC;
     223            3214 :         else if( EQUAL(osToken,"DISTINCT") )
     224              31 :             nReturn = SWQT_DISTINCT;
     225            3183 :         else if( EQUAL(osToken,"CAST") )
     226              53 :             nReturn = SWQT_CAST;
     227            3130 :         else if( EQUAL(osToken,"UNION") )
     228               7 :             nReturn = SWQT_UNION;
     229            3123 :         else if( EQUAL(osToken,"ALL") )
     230               6 :             nReturn = SWQT_ALL;
     231                 :         else
     232                 :         {
     233            3117 :             *ppNode = new swq_expr_node( osToken );
     234            3117 :             nReturn = SWQT_IDENTIFIER;
     235                 :         }
     236                 : 
     237            5390 :         return nReturn;
     238                 :     }
     239                 : 
     240                 : /* -------------------------------------------------------------------- */
     241                 : /*      Handle special tokens.                                          */
     242                 : /* -------------------------------------------------------------------- */
     243                 :     else
     244                 :     {
     245            4442 :         context->pszNext = pszInput+1;
     246            4442 :         return *pszInput;
     247                 :     }
     248                 : }
     249                 : 
     250                 : /************************************************************************/
     251                 : /*                        swq_select_summarize()                        */
     252                 : /************************************************************************/
     253                 : 
     254                 : const char *
     255             262 : swq_select_summarize( swq_select *select_info, 
     256                 :                       int dest_column, const char *value )
     257                 : 
     258                 : {
     259             262 :     swq_col_def *def = select_info->column_defs + dest_column;
     260                 :     swq_summary *summary;
     261                 : 
     262                 : /* -------------------------------------------------------------------- */
     263                 : /*      Do various checking.                                            */
     264                 : /* -------------------------------------------------------------------- */
     265             262 :     if( select_info->query_mode == SWQM_RECORDSET )
     266               0 :         return "swq_select_summarize() called on non-summary query.";
     267                 : 
     268             262 :     if( dest_column < 0 || dest_column >= select_info->result_columns )
     269               0 :         return "dest_column out of range in swq_select_summarize().";
     270                 : 
     271             262 :     if( def->col_func == SWQCF_NONE && !def->distinct_flag )
     272               0 :         return NULL;
     273                 : 
     274                 : /* -------------------------------------------------------------------- */
     275                 : /*      Create the summary information if this is the first row         */
     276                 : /*      being processed.                                                */
     277                 : /* -------------------------------------------------------------------- */
     278             262 :     if( select_info->column_summary == NULL && value != NULL )
     279                 :     {
     280                 :         int i;
     281                 : 
     282                 :         select_info->column_summary = (swq_summary *) 
     283              21 :             CPLMalloc(sizeof(swq_summary) * select_info->result_columns);
     284                 :         memset( select_info->column_summary, 0, 
     285              21 :                 sizeof(swq_summary) * select_info->result_columns );
     286                 : 
     287              50 :         for( i = 0; i < select_info->result_columns; i++ )
     288                 :         {
     289              29 :             select_info->column_summary[i].min = 1e20;
     290              29 :             select_info->column_summary[i].max = -1e20;
     291                 :         }
     292                 :     }
     293                 : 
     294             262 :     if( select_info->column_summary == NULL )
     295               8 :         return NULL;
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      If distinct processing is on, process that now.                 */
     299                 : /* -------------------------------------------------------------------- */
     300             254 :     summary = select_info->column_summary + dest_column;
     301                 :     
     302             254 :     if( def->distinct_flag )
     303                 :     {
     304                 :         int  i;
     305                 : 
     306                 :         /* This should be implemented with a much more complicated
     307                 :            data structure to achieve any sort of efficiency. */
     308             804 :         for( i = 0; i < summary->count; i++ )
     309                 :         {
     310             736 :             if( value == NULL )
     311                 :             {
     312              93 :                 if (summary->distinct_list[i] == NULL)
     313               6 :                     break;
     314                 :             }
     315            1286 :             else if( summary->distinct_list[i] != NULL &&
     316             643 :                      strcmp(value,summary->distinct_list[i]) == 0 )
     317             125 :                 break;
     318                 :         }
     319                 :         
     320             199 :         if( i == summary->count )
     321                 :         {
     322              68 :             char  **old_list = summary->distinct_list;
     323                 :             
     324                 :             summary->distinct_list = (char **) 
     325              68 :                 CPLMalloc(sizeof(char *) * (summary->count+1));
     326                 :             memcpy( summary->distinct_list, old_list, 
     327              68 :                     sizeof(char *) * summary->count );
     328             136 :             summary->distinct_list[(summary->count)++] = 
     329              68 :                 (value != NULL) ? CPLStrdup( value ) : NULL;
     330                 : 
     331              68 :             CPLFree(old_list);
     332                 :         }
     333                 :     }
     334                 : 
     335                 : /* -------------------------------------------------------------------- */
     336                 : /*      Process various options.                                        */
     337                 : /* -------------------------------------------------------------------- */
     338                 : 
     339             254 :     switch( def->col_func )
     340                 :     {
     341                 :       case SWQCF_MIN:
     342              10 :         if( value != NULL && value[0] != '\0' )
     343                 :         {
     344              10 :             double df_val = CPLAtof(value);
     345              10 :             if( df_val < summary->min )
     346               3 :                 summary->min = df_val;
     347                 :         }
     348              10 :         break;
     349                 :       case SWQCF_MAX:
     350              17 :         if( value != NULL && value[0] != '\0' )
     351                 :         {
     352              17 :             double df_val = CPLAtof(value);
     353              17 :             if( df_val > summary->max )
     354               7 :                 summary->max = df_val;
     355                 :         }
     356              17 :         break;
     357                 :       case SWQCF_AVG:
     358                 :       case SWQCF_SUM:
     359               0 :         if( value != NULL && value[0] != '\0' )
     360                 :         {
     361               0 :             summary->count++;
     362               0 :             summary->sum += CPLAtof(value);
     363                 :         }
     364               0 :         break;
     365                 : 
     366                 :       case SWQCF_COUNT:
     367              40 :         if( value != NULL && !def->distinct_flag )
     368              28 :             summary->count++;
     369              40 :         break;
     370                 : 
     371                 :       case SWQCF_NONE:
     372             187 :         break;
     373                 : 
     374                 :       case SWQCF_CUSTOM:
     375               0 :         return "swq_select_summarize() called on custom field function.";
     376                 : 
     377                 :       default:
     378               0 :         return "swq_select_summarize() - unexpected col_func";
     379                 :     }
     380                 : 
     381             254 :     return NULL;
     382                 : }
     383                 : /************************************************************************/
     384                 : /*                      sort comparison functions.                      */
     385                 : /************************************************************************/
     386                 : 
     387              52 : static int FORCE_CDECL swq_compare_int( const void *item1, const void *item2 )
     388                 : {
     389                 :     int  v1, v2;
     390                 : 
     391              52 :     const char* pszStr1 = *((const char **) item1);
     392              52 :     const char* pszStr2 = *((const char **) item2);
     393              52 :     if (pszStr1 == NULL)
     394               0 :         return (pszStr2 == NULL) ? 0 : -1;
     395              52 :     else if (pszStr2 == NULL)
     396              10 :         return 1;
     397                 : 
     398              42 :     v1 = atoi(pszStr1);
     399              42 :     v2 = atoi(pszStr2);
     400                 : 
     401              42 :     if( v1 < v2 )
     402              16 :         return -1;
     403              26 :     else if( v1 == v2 )
     404               0 :         return 0;
     405                 :     else
     406              26 :         return 1;
     407                 : }
     408                 : 
     409              25 : static int FORCE_CDECL swq_compare_real( const void *item1, const void *item2 )
     410                 : {
     411                 :     double  v1, v2;
     412                 : 
     413              25 :     const char* pszStr1 = *((const char **) item1);
     414              25 :     const char* pszStr2 = *((const char **) item2);
     415              25 :     if (pszStr1 == NULL)
     416               0 :         return (pszStr2 == NULL) ? 0 : -1;
     417              25 :     else if (pszStr2 == NULL)
     418               2 :         return 1;
     419                 : 
     420              23 :     v1 = CPLAtof(pszStr1);
     421              23 :     v2 = CPLAtof(pszStr2);
     422                 : 
     423              23 :     if( v1 < v2 )
     424               9 :         return -1;
     425              14 :     else if( v1 == v2 )
     426               0 :         return 0;
     427                 :     else
     428              14 :         return 1;
     429                 : }
     430                 : 
     431              14 : static int FORCE_CDECL swq_compare_string( const void *item1, const void *item2 )
     432                 : {
     433              14 :     const char* pszStr1 = *((const char **) item1);
     434              14 :     const char* pszStr2 = *((const char **) item2);
     435              14 :     if (pszStr1 == NULL)
     436               0 :         return (pszStr2 == NULL) ? 0 : -1;
     437              14 :     else if (pszStr2 == NULL)
     438               2 :         return 1;
     439                 : 
     440              12 :     return strcmp( pszStr1, pszStr2 );
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                    swq_select_finish_summarize()                     */
     445                 : /*                                                                      */
     446                 : /*      Call to complete summarize work.  Does stuff like ordering      */
     447                 : /*      the distinct list for instance.                                 */
     448                 : /************************************************************************/
     449                 : 
     450              27 : const char *swq_select_finish_summarize( swq_select *select_info )
     451                 : 
     452                 : {
     453                 :     int (FORCE_CDECL *compare_func)(const void *, const void*);
     454              27 :     int count = 0;
     455              27 :     char **distinct_list = NULL;
     456                 : 
     457              27 :     if( select_info->query_mode != SWQM_DISTINCT_LIST 
     458                 :         || select_info->order_specs == 0 )
     459              16 :         return NULL;
     460                 : 
     461              11 :     if( select_info->order_specs > 1 )
     462               0 :         return "Can't ORDER BY a DISTINCT list by more than one key.";
     463                 : 
     464              22 :     if( select_info->order_defs[0].field_index != 
     465              11 :         select_info->column_defs[0].field_index )
     466               0 :         return "Only selected DISTINCT field can be used for ORDER BY.";
     467                 : 
     468              11 :     if( select_info->column_summary == NULL )
     469               0 :         return NULL;
     470                 : 
     471              11 :     if( select_info->column_defs[0].field_type == SWQ_INTEGER )
     472               4 :         compare_func = swq_compare_int;
     473               7 :     else if( select_info->column_defs[0].field_type == SWQ_FLOAT )
     474               4 :         compare_func = swq_compare_real;
     475                 :     else
     476               3 :         compare_func = swq_compare_string;
     477                 : 
     478              11 :     distinct_list = select_info->column_summary[0].distinct_list;
     479              11 :     count = select_info->column_summary[0].count;
     480                 : 
     481              11 :     qsort( distinct_list, count, sizeof(char *), compare_func );
     482                 : 
     483                 : /* -------------------------------------------------------------------- */
     484                 : /*      Do we want the list ascending in stead of descending?           */
     485                 : /* -------------------------------------------------------------------- */
     486              11 :     if( !select_info->order_defs[0].ascending_flag )
     487                 :     {
     488                 :         char *saved;
     489                 :         int i;
     490                 : 
     491              21 :         for( i = 0; i < count/2; i++ )
     492                 :         {
     493              15 :             saved = distinct_list[i];
     494              15 :             distinct_list[i] = distinct_list[count-i-1];
     495              15 :             distinct_list[count-i-1] = saved;
     496                 :         }
     497                 :     }
     498                 : 
     499              11 :     return NULL;
     500                 : }
     501                 : 
     502                 : /************************************************************************/
     503                 : /*                          swq_select_free()                           */
     504                 : /************************************************************************/
     505                 : 
     506               0 : void swq_select_free( swq_select *select_info )
     507                 : 
     508                 : {
     509               0 :     delete select_info;
     510               0 : }
     511                 : 
     512                 : /************************************************************************/
     513                 : /*                         swq_identify_field()                         */
     514                 : /************************************************************************/
     515                 : static 
     516                 : int swq_identify_field_internal( const char *field_token, const char* table_name,
     517                 :                                  swq_field_list *field_list,
     518                 :                                  swq_field_type *this_type, int *table_id, int tables_enabled );
     519                 : 
     520            4262 : int swq_identify_field( const char *token, swq_field_list *field_list,
     521                 :                         swq_field_type *this_type, int *table_id )
     522                 : 
     523                 : {
     524            4262 :     CPLString osTableName;
     525            4262 :     const char *field_token = token;
     526                 :     int   tables_enabled;
     527                 : 
     528            7334 :     if( field_list->table_count > 0 && field_list->table_ids != NULL )
     529            3072 :         tables_enabled = TRUE;
     530                 :     else
     531            1190 :         tables_enabled = FALSE;
     532                 : 
     533                 : /* -------------------------------------------------------------------- */
     534                 : /*      Parse out table name if present, and table support enabled.     */
     535                 : /* -------------------------------------------------------------------- */
     536            4262 :     if( tables_enabled && strchr(token, '.') != NULL )
     537                 :     {
     538              97 :         int dot_offset = (int)(strchr(token,'.') - token);
     539                 : 
     540              97 :         osTableName = token;
     541              97 :         osTableName.resize(dot_offset);
     542              97 :         field_token = token + dot_offset + 1;
     543                 : 
     544                 : #ifdef notdef
     545                 :         /* We try to detect if a.b is the a.b field */
     546                 :         /* of the main table, or the b field of the a table */
     547                 :         /* If both exists, report an error. */
     548                 :         /* This works, but I'm not sure this is a good idea to */
     549                 :         /* enable that. It is a sign that our SQL grammar is somewhat */
     550                 :         /* ambiguous */
     551                 : 
     552                 :         swq_field_type eTypeWithTablesEnabled;
     553                 :         int            nTableIdWithTablesEnabled;
     554                 :         int nRetWithTablesEnabled = swq_identify_field_internal(
     555                 :             field_token, osTableName.c_str(), field_list,
     556                 :             &eTypeWithTablesEnabled, &nTableIdWithTablesEnabled, TRUE);
     557                 : 
     558                 :         swq_field_type eTypeWithTablesDisabled;
     559                 :         int            nTableIdWithTablesDisabled;
     560                 :         int nRetWithTablesDisabled = swq_identify_field_internal(
     561                 :             token, "", field_list,
     562                 :             &eTypeWithTablesDisabled, &nTableIdWithTablesDisabled, FALSE);
     563                 : 
     564                 :         if( nRetWithTablesEnabled >= 0 && nRetWithTablesDisabled >= 0 )
     565                 :         {
     566                 :             CPLError(CE_Failure, CPLE_AppDefined,
     567                 :                         "Ambiguous situation. Both %s exists as a field in "
     568                 :                         "main table and %s exists as a field in %s table",
     569                 :                         token, osTableName.c_str(), field_token);
     570                 :             return -1;
     571                 :         }
     572                 :         else if( nRetWithTablesEnabled >= 0 )
     573                 :         {
     574                 :             if( this_type != NULL ) *this_type = eTypeWithTablesEnabled;
     575                 :             if( table_id != NULL ) *table_id = nTableIdWithTablesEnabled;
     576                 :             return nRetWithTablesEnabled;
     577                 :         }
     578                 :         else if( nRetWithTablesDisabled >= 0 )
     579                 :         {
     580                 :             if( this_type != NULL ) *this_type = eTypeWithTablesDisabled;
     581                 :             if( table_id != NULL ) *table_id = nTableIdWithTablesDisabled;
     582                 :             return nRetWithTablesDisabled;
     583                 :         }
     584                 :         else
     585                 :         {
     586                 :             return -1;
     587                 :         }
     588                 : #endif
     589                 :     }
     590                 : 
     591                 :     return swq_identify_field_internal(field_token, osTableName.c_str(), field_list,
     592            4262 :                                        this_type, table_id, tables_enabled);
     593                 : }
     594                 : 
     595                 : 
     596            4262 : int swq_identify_field_internal( const char *field_token, const char* table_name,
     597                 :                                  swq_field_list *field_list,
     598                 :                                  swq_field_type *this_type, int *table_id, int tables_enabled )
     599                 : 
     600                 : {
     601                 :     int i;
     602                 : /* -------------------------------------------------------------------- */
     603                 : /*      Search for matching field.                                      */
     604                 : /* -------------------------------------------------------------------- */
     605           22174 :     for( i = 0; i < field_list->count; i++ )
     606                 :     {
     607           21621 :         int  t_id = 0;
     608                 : 
     609           21621 :         if( !EQUAL( field_list->names[i], field_token ) )
     610           17878 :             continue;
     611                 : 
     612                 :         /* Do the table specifications match? */
     613            3743 :         if( tables_enabled )
     614                 :         {
     615            2882 :             t_id = field_list->table_ids[i];
     616            3010 :             if( table_name[0] != '\0' 
     617             128 :                 && !EQUAL(table_name,field_list->table_defs[t_id].table_alias))
     618              34 :                 continue;
     619                 : 
     620                 : //            if( t_id != 0 && table_name[0] == '\0' )
     621                 : //                continue;
     622                 :         }
     623                 : 
     624                 :         /* We have a match, return various information */
     625            3709 :         if( this_type != NULL )
     626                 :         {
     627            3646 :             if( field_list->types != NULL )
     628            3646 :                 *this_type = field_list->types[i];
     629                 :             else
     630               0 :                 *this_type = SWQ_OTHER;
     631                 :         }
     632                 :         
     633            3709 :         if( table_id != NULL )
     634            3709 :             *table_id = t_id;
     635                 : 
     636            3709 :         if( field_list->ids == NULL )
     637             861 :             return i;
     638                 :         else
     639            2848 :             return field_list->ids[i];
     640                 :     }
     641                 : 
     642                 : /* -------------------------------------------------------------------- */
     643                 : /*      No match, return failure.                                       */
     644                 : /* -------------------------------------------------------------------- */
     645             553 :     if( this_type != NULL )
     646             550 :         *this_type = SWQ_OTHER;
     647                 : 
     648             553 :     if( table_id != NULL )
     649             553 :         *table_id = 0;
     650                 : 
     651             553 :     return -1;
     652                 : }
     653                 : 
     654                 : /************************************************************************/
     655                 : /*                          swq_expr_compile()                          */
     656                 : /************************************************************************/
     657                 : 
     658             849 : CPLErr swq_expr_compile( const char *where_clause,
     659                 :                          int field_count,
     660                 :                          char **field_names, 
     661                 :                          swq_field_type *field_types, 
     662                 :                          swq_expr_node **expr_out )
     663                 : 
     664                 : {
     665                 :     swq_field_list  field_list;
     666                 : 
     667             849 :     field_list.count = field_count;
     668             849 :     field_list.names = field_names;
     669             849 :     field_list.types = field_types;
     670             849 :     field_list.table_ids = NULL;
     671             849 :     field_list.ids = NULL;
     672                 :     
     673             849 :     field_list.table_count = 0;
     674             849 :     field_list.table_defs = NULL;
     675                 : 
     676             849 :     return swq_expr_compile2( where_clause, &field_list, expr_out );
     677                 : }
     678                 : 
     679                 : 
     680                 : /************************************************************************/
     681                 : /*                         swq_expr_compile2()                          */
     682                 : /************************************************************************/
     683                 : 
     684             849 : CPLErr swq_expr_compile2( const char *where_clause, 
     685                 :                           swq_field_list *field_list,
     686                 :                           swq_expr_node **expr_out )
     687                 : 
     688                 : {
     689                 : 
     690             849 :     swq_parse_context context;
     691                 : 
     692             849 :     context.pszInput = where_clause;
     693             849 :     context.pszNext = where_clause;
     694             849 :     context.nStartToken = SWQT_LOGICAL_START;
     695                 :     
     696             849 :     if( swqparse( &context ) == 0 
     697                 :         && context.poRoot->Check( field_list ) != SWQ_ERROR )
     698                 :     {
     699             849 :         *expr_out = context.poRoot;
     700                 : 
     701             849 :         return CE_None;
     702                 :     }
     703                 :     else
     704                 :     {
     705               0 :         delete context.poRoot;
     706               0 :         *expr_out = NULL;
     707               0 :         return CE_Failure;
     708                 :     }
     709                 : }
     710                 : 
     711                 : /************************************************************************/
     712                 : /*                        swq_is_reserved_keyword()                     */
     713                 : /************************************************************************/
     714                 : 
     715                 : static const char* apszSQLReservedKeywords[] = {
     716                 :     "OR",
     717                 :     "AND",
     718                 :     "NOT",
     719                 :     "LIKE",
     720                 :     "IS",
     721                 :     "NULL",
     722                 :     "IN",
     723                 :     "BETWEEN",
     724                 :     "CAST",
     725                 :     "DISTINCT",
     726                 :     "ESCAPE",
     727                 :     "SELECT",
     728                 :     "LEFT",
     729                 :     "JOIN",
     730                 :     "WHERE",
     731                 :     "ON",
     732                 :     "ORDER",
     733                 :     "BY",
     734                 :     "FROM",
     735                 :     "AS",
     736                 :     "ASC",
     737                 :     "DESC",
     738                 :     "UNION",
     739                 :     "ALL"
     740                 : };
     741                 : 
     742             404 : int swq_is_reserved_keyword(const char* pszStr)
     743                 : {
     744           10052 :     for(int i = 0; i < (int)(sizeof(apszSQLReservedKeywords)/sizeof(char*)); i++)
     745                 :     {
     746            9656 :         if (EQUAL(pszStr, apszSQLReservedKeywords[i]))
     747               8 :             return TRUE;
     748                 :     }
     749             396 :     return FALSE;
     750                 : }

Generated by: LCOV version 1.7