LCOV - code coverage report
Current view: directory - ogr - swq_select.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 357 275 77.0 %
Date: 2011-12-18 Functions: 12 9 75.0 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Component: OGR SQL Engine
       4                 :  * Purpose: swq_select class implementation.
       5                 :  * Author: Frank Warmerdam <warmerdam@pobox.com>
       6                 :  * 
       7                 :  ******************************************************************************
       8                 :  * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
       9                 :  *
      10                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      11                 :  * copy of this software and associated documentation files (the "Software"),
      12                 :  * to deal in the Software without restriction, including without limitation
      13                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14                 :  * and/or sell copies of the Software, and to permit persons to whom the
      15                 :  * Software is furnished to do so, subject to the following conditions:
      16                 :  *
      17                 :  * The above copyright notice and this permission notice shall be included
      18                 :  * in all copies or substantial portions of the Software.
      19                 :  *
      20                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26                 :  * DEALINGS IN THE SOFTWARE.
      27                 :  ****************************************************************************/
      28                 : 
      29                 : #include "swq.h"
      30                 : #include "swq_parser.hpp"
      31                 : 
      32                 : /************************************************************************/
      33                 : /*                             swq_select()                             */
      34                 : /************************************************************************/
      35                 : 
      36             303 : swq_select::swq_select()
      37                 : 
      38                 : {
      39             303 :     query_mode = 0;
      40             303 :     raw_select = NULL;
      41                 : 
      42             303 :     result_columns = 0;
      43             303 :     column_defs = NULL;
      44             303 :     column_summary = NULL;
      45                 :     
      46             303 :     table_count = 0;
      47             303 :     table_defs = NULL;
      48                 :     
      49             303 :     join_count = 0;
      50             303 :     join_defs = NULL;
      51                 :     
      52             303 :     where_expr = NULL;
      53                 : 
      54             303 :     order_specs = 0;
      55             303 :     order_defs = NULL;
      56             303 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*                            ~swq_select()                             */
      60                 : /************************************************************************/
      61                 : 
      62             303 : swq_select::~swq_select()
      63                 : 
      64                 : {
      65                 :     int i;
      66                 : 
      67             303 :     delete where_expr;
      68             303 :     CPLFree( raw_select );
      69                 : 
      70             565 :     for( i = 0; i < table_count; i++ )
      71                 :     {
      72             262 :         swq_table_def *table_def = table_defs + i;
      73                 : 
      74             262 :         CPLFree( table_def->data_source );
      75             262 :         CPLFree( table_def->table_name );
      76             262 :         CPLFree( table_def->table_alias );
      77                 :     }
      78             303 :     if( table_defs != NULL )
      79             239 :         CPLFree( table_defs );
      80                 : 
      81            1795 :     for( i = 0; i < result_columns; i++ )
      82                 :     {
      83            1492 :         CPLFree( column_defs[i].field_name );
      84            1492 :         CPLFree( column_defs[i].field_alias );
      85                 : 
      86            1492 :         delete column_defs[i].expr;
      87                 : 
      88            1519 :         if( column_summary != NULL 
      89              27 :             && column_summary[i].distinct_list != NULL )
      90                 :         {
      91                 :             int j;
      92                 :             
      93              84 :             for( j = 0; j < column_summary[i].count; j++ )
      94              66 :                 CPLFree( column_summary[i].distinct_list[j] );
      95                 : 
      96              18 :             CPLFree( column_summary[i].distinct_list );
      97                 :         }
      98                 :     }
      99                 : 
     100             303 :     CPLFree( column_defs );
     101                 : 
     102             303 :     CPLFree( column_summary );
     103                 : 
     104             326 :     for( i = 0; i < order_specs; i++ )
     105                 :     {
     106              23 :         CPLFree( order_defs[i].field_name );
     107                 :     }
     108                 :     
     109             303 :     CPLFree( order_defs );
     110                 : 
     111             324 :     for( i = 0; i < join_count; i++ )
     112                 :     {
     113              21 :         CPLFree( join_defs[i].primary_field_name );
     114              21 :         CPLFree( join_defs[i].secondary_field_name );
     115                 :     }
     116             303 :     CPLFree( join_defs );
     117             303 : }
     118                 : 
     119                 : 
     120                 : /************************************************************************/
     121                 : /*                              preparse()                              */
     122                 : /*                                                                      */
     123                 : /*      Parse the expression but without knowing the available          */
     124                 : /*      tables and fields.                                              */
     125                 : /************************************************************************/
     126                 : 
     127             303 : CPLErr swq_select::preparse( const char *select_statement )
     128                 : 
     129                 : {
     130                 : /* -------------------------------------------------------------------- */
     131                 : /*      Allocate a big field list.  It would be nice to make this       */
     132                 : /*      dynamic!                                                        */
     133                 : /* -------------------------------------------------------------------- */
     134                 : #define MAX_COLUMNS 250
     135                 : 
     136             303 :     column_defs = (swq_col_def *) CPLMalloc(sizeof(swq_col_def) * MAX_COLUMNS);
     137             303 :     memset( column_defs, 0, sizeof(swq_col_def) * MAX_COLUMNS );
     138                 : 
     139                 : /* -------------------------------------------------------------------- */
     140                 : /*      Prepare a parser context.                                       */
     141                 : /* -------------------------------------------------------------------- */
     142             303 :     swq_parse_context context;
     143                 : 
     144             303 :     context.pszInput = select_statement;
     145             303 :     context.pszNext = select_statement;
     146             303 :     context.nStartToken = SWQT_SELECT_START;
     147             303 :     context.poSelect = this;
     148                 :     
     149                 : /* -------------------------------------------------------------------- */
     150                 : /*      Do the parse.                                                   */
     151                 : /* -------------------------------------------------------------------- */
     152             303 :     if( swqparse( &context ) != 0 )
     153                 :     {
     154              90 :         delete context.poRoot;
     155              90 :         return CE_Failure;
     156                 :     }
     157                 : 
     158                 : /* -------------------------------------------------------------------- */
     159                 : /*      resize the columns list properly.                               */
     160                 : /* -------------------------------------------------------------------- */
     161                 :     column_defs = (swq_col_def *) 
     162             213 :         CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
     163                 : 
     164             213 :     return CE_None;
     165                 : }
     166                 : 
     167                 : /************************************************************************/
     168                 : /*                                Dump()                                */
     169                 : /************************************************************************/
     170                 : 
     171               0 : void swq_select::Dump( FILE *fp )
     172                 : 
     173                 : {
     174                 :     int i;
     175                 : 
     176               0 :     fprintf( fp, "SELECT Statement:\n" );
     177                 : 
     178                 : /* -------------------------------------------------------------------- */
     179                 : /*      query mode.                                                     */
     180                 : /* -------------------------------------------------------------------- */
     181               0 :     if( query_mode == SWQM_SUMMARY_RECORD )
     182               0 :         fprintf( fp, "  QUERY MODE: SUMMARY RECORD\n" );
     183               0 :     else if( query_mode == SWQM_RECORDSET )
     184               0 :         fprintf( fp, "  QUERY MODE: RECORDSET\n" );
     185               0 :     else if( query_mode == SWQM_DISTINCT_LIST )
     186               0 :         fprintf( fp, "  QUERY MODE: DISTINCT LIST\n" );
     187                 :     else
     188               0 :         fprintf( fp, "  QUERY MODE: %d/unknown\n", query_mode );
     189                 : 
     190                 : /* -------------------------------------------------------------------- */
     191                 : /*      column_defs                                                     */
     192                 : /* -------------------------------------------------------------------- */
     193               0 :     fprintf( fp, "  Result Columns:\n" );
     194               0 :     for( i = 0; i < result_columns; i++ )
     195                 :     {
     196               0 :         swq_col_def *def = column_defs + i;
     197                 : 
     198                 :         
     199               0 :         fprintf( fp, "  Name: %s\n", def->field_name );
     200                 : 
     201               0 :         if( def->field_alias )
     202               0 :             fprintf( fp, "    Alias: %s\n", def->field_alias );
     203                 : 
     204               0 :         if( def->col_func == SWQCF_NONE )
     205                 :             /* nothing */;
     206               0 :         else if( def->col_func == SWQCF_AVG )
     207               0 :             fprintf( fp, "    Function: AVG\n" );
     208               0 :         else if( def->col_func == SWQCF_MIN )
     209               0 :             fprintf( fp, "    Function: MIN\n" );
     210               0 :         else if( def->col_func == SWQCF_MAX )
     211               0 :             fprintf( fp, "    Function: MAX\n" );
     212               0 :         else if( def->col_func == SWQCF_COUNT )
     213               0 :             fprintf( fp, "    Function: COUNT\n" );
     214               0 :         else if( def->col_func == SWQCF_SUM )
     215               0 :             fprintf( fp, "    Function: SUM\n" ); 
     216               0 :         else if( def->col_func == SWQCF_CUSTOM )
     217               0 :             fprintf( fp, "    Function: CUSTOM\n" );
     218                 :         else
     219               0 :             fprintf( fp, "    Function: UNKNOWN!\n" );
     220                 : 
     221               0 :         if( def->distinct_flag )
     222               0 :             fprintf( fp, "    DISTINCT flag set\n" );
     223                 : 
     224                 :         fprintf( fp, "    Field Index: %d, Table Index: %d\n", 
     225               0 :                  def->field_index, def->table_index );
     226                 : 
     227               0 :         fprintf( fp, "    Field Type: %d\n", def->field_type );
     228               0 :         fprintf( fp, "    Target Type: %d\n", def->target_type );
     229                 :         fprintf( fp, "    Length: %d, Precision: %d\n",
     230               0 :                  def->field_length, def->field_precision );
     231                 : 
     232               0 :         if( def->expr != NULL )
     233                 :         {
     234               0 :             fprintf( fp, "    Expression:\n" );
     235               0 :             def->expr->Dump( fp, 3 );
     236                 :         }
     237                 :     }
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      table_defs                                                      */
     241                 : /* -------------------------------------------------------------------- */
     242               0 :     fprintf( fp, "  Table Defs: %d\n", table_count );
     243               0 :     for( i = 0; i < table_count; i++ )
     244                 :     {
     245                 :         fprintf( fp, "    datasource=%s, table_name=%s, table_alias=%s\n",
     246               0 :                  table_defs[i].data_source,
     247               0 :                  table_defs[i].table_name,
     248               0 :                  table_defs[i].table_alias );
     249                 :     }
     250                 : 
     251                 : /* -------------------------------------------------------------------- */
     252                 : /*      join_defs                                                       */
     253                 : /* -------------------------------------------------------------------- */
     254               0 :     if( join_count > 0 )
     255               0 :         fprintf( fp, "  joins:\n" );
     256                 : 
     257               0 :     for( i = 0; i < join_count; i++ )
     258                 :     {
     259               0 :         fprintf( fp, "  %d:\n", i );
     260                 :         fprintf( fp, "    Primary Field: %s/%d\n", 
     261               0 :                  join_defs[i].primary_field_name,
     262               0 :                  join_defs[i].primary_field );
     263                 : 
     264                 :         fprintf( fp, "    Operation: %d\n", 
     265               0 :                  join_defs[i].op );
     266                 : 
     267                 :         fprintf( fp, "    Secondary Field: %s/%d\n", 
     268               0 :                  join_defs[i].secondary_field_name,
     269               0 :                  join_defs[i].secondary_field );
     270                 :         fprintf( fp, "    Secondary Table: %d\n", 
     271               0 :                  join_defs[i].secondary_table );
     272                 :     }
     273                 : 
     274                 : /* -------------------------------------------------------------------- */
     275                 : /*      Where clause.                                                   */
     276                 : /* -------------------------------------------------------------------- */
     277               0 :     if( where_expr != NULL )
     278                 :     {
     279               0 :         fprintf( fp, "  WHERE:\n" );
     280               0 :         where_expr->Dump( fp, 2 );
     281                 :     }
     282                 : 
     283                 : /* -------------------------------------------------------------------- */
     284                 : /*      Order by                                                        */
     285                 : /* -------------------------------------------------------------------- */
     286                 : 
     287               0 :     for( i = 0; i < order_specs; i++ )
     288                 :     {
     289                 :         fprintf( fp, "  ORDER BY: %s (%d/%d)",
     290               0 :                  order_defs[i].field_name,
     291               0 :                  order_defs[i].table_index,
     292               0 :                  order_defs[i].field_index );
     293               0 :         if( order_defs[i].ascending_flag )
     294               0 :             fprintf( fp, " ASC\n" );
     295                 :         else
     296               0 :             fprintf( fp, " DESC\n" );
     297                 :     }
     298               0 : }
     299                 : 
     300                 : /************************************************************************/
     301                 : /*                             PushField()                              */
     302                 : /*                                                                      */
     303                 : /*      Create a new field definition by name and possibly alias.       */
     304                 : /************************************************************************/
     305                 : 
     306            1336 : int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
     307                 :                            int distinct_flag )
     308                 : 
     309                 : {
     310                 : /* -------------------------------------------------------------------- */
     311                 : /*      Grow the array.                                                 */
     312                 : /* -------------------------------------------------------------------- */
     313            1336 :     result_columns++;
     314                 : 
     315                 :     column_defs = (swq_col_def *) 
     316            1336 :         CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
     317                 : 
     318            1336 :     swq_col_def *col_def = column_defs + result_columns - 1;
     319                 : 
     320            1336 :     memset( col_def, 0, sizeof(swq_col_def) );
     321                 : 
     322                 : /* -------------------------------------------------------------------- */
     323                 : /*      Try to capture a field name.                                    */
     324                 : /* -------------------------------------------------------------------- */
     325            1336 :     if( poExpr->eNodeType == SNT_COLUMN )
     326                 :         col_def->field_name = 
     327            1190 :             CPLStrdup(poExpr->string_value);
     328             403 :     else if( poExpr->eNodeType == SNT_OPERATION
     329                 :              && poExpr->nSubExprCount >= 1
     330             134 :              && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN )
     331                 :         col_def->field_name = 
     332             123 :             CPLStrdup(poExpr->papoSubExpr[0]->string_value);
     333                 :     else
     334              23 :         col_def->field_name = CPLStrdup("");
     335                 : 
     336                 : /* -------------------------------------------------------------------- */
     337                 : /*      Initialize fields.                                              */
     338                 : /* -------------------------------------------------------------------- */
     339            1336 :     if( pszAlias != NULL )
     340               9 :         col_def->field_alias = CPLStrdup( pszAlias );
     341                 : 
     342            1336 :     col_def->table_index = -1;
     343            1336 :     col_def->field_index = -1;
     344            1336 :     col_def->field_type = SWQ_OTHER;
     345            1336 :     col_def->field_precision = -1;
     346            1336 :     col_def->target_type = SWQ_OTHER;
     347            1336 :     col_def->col_func = SWQCF_NONE;
     348            1336 :     col_def->distinct_flag = distinct_flag;
     349                 : 
     350                 : /* -------------------------------------------------------------------- */
     351                 : /*      Do we have a CAST operator in play?                             */
     352                 : /* -------------------------------------------------------------------- */
     353            1336 :     if( poExpr->eNodeType == SNT_OPERATION 
     354                 :         && poExpr->nOperation == SWQ_CAST )
     355                 :     {
     356              12 :         const char *pszTypeName = poExpr->papoSubExpr[1]->string_value;
     357              12 :         int parse_precision = 0;
     358                 : 
     359              12 :         if( EQUAL(pszTypeName,"character") )
     360                 :         {
     361               7 :             col_def->target_type = SWQ_STRING;
     362               7 :             col_def->field_length = 1;
     363                 :         }
     364               5 :         else if( strcasecmp(pszTypeName,"integer") == 0 )
     365                 :         {
     366               1 :             col_def->target_type = SWQ_INTEGER;
     367                 :         }
     368               4 :         else if( strcasecmp(pszTypeName,"float") == 0 )
     369                 :         {
     370               0 :             col_def->target_type = SWQ_FLOAT;
     371                 :         }
     372               4 :         else if( strcasecmp(pszTypeName,"numeric") == 0 )
     373                 :         {
     374               1 :             col_def->target_type = SWQ_FLOAT;
     375               1 :             parse_precision = 1;
     376                 :         }
     377               3 :         else if( strcasecmp(pszTypeName,"timestamp") == 0 )
     378                 :         {
     379               0 :             col_def->target_type = SWQ_TIMESTAMP;
     380                 :         }
     381               3 :         else if( strcasecmp(pszTypeName,"date") == 0 )
     382                 :         {
     383               0 :             col_def->target_type = SWQ_DATE;
     384                 :         }
     385               3 :         else if( strcasecmp(pszTypeName,"time") == 0 )
     386                 :         {
     387               0 :             col_def->target_type = SWQ_TIME;
     388                 :         }
     389                 :         else
     390                 :         {
     391                 :             CPLError( CE_Failure, CPLE_AppDefined,
     392                 :                       "Unrecognized typename %s in CAST operator.", 
     393               3 :                       pszTypeName );
     394               3 :             CPLFree(col_def->field_name);
     395               3 :             col_def->field_name = NULL;
     396               3 :             CPLFree(col_def->field_alias);
     397               3 :             col_def->field_alias = NULL;
     398               3 :             result_columns--;
     399               3 :             return FALSE;
     400                 :         }
     401                 : 
     402                 :         // field width.
     403               9 :         if( poExpr->nSubExprCount > 2 )
     404                 :         {
     405               5 :             col_def->field_length = poExpr->papoSubExpr[2]->int_value;
     406                 :         }
     407                 : 
     408                 :         // field width.
     409               9 :         if( poExpr->nSubExprCount > 3 && parse_precision )
     410                 :         {
     411               1 :             col_def->field_precision = poExpr->papoSubExpr[3]->int_value;
     412                 :         }
     413                 :     }
     414                 : 
     415                 : /* -------------------------------------------------------------------- */
     416                 : /*      Do we have a special column function in play?                   */
     417                 : /* -------------------------------------------------------------------- */
     418            1333 :     if( poExpr->eNodeType == SNT_OPERATION 
     419                 :         && poExpr->nOperation >= SWQ_AVG
     420                 :         && poExpr->nOperation <= SWQ_SUM )
     421                 :     {
     422             108 :         if( poExpr->nSubExprCount != 1 )
     423                 :         {
     424                 :             CPLError( CE_Failure, CPLE_AppDefined,
     425                 :                       "Column Summary Function '%s' has wrong number of arguments.", 
     426               2 :                       poExpr->string_value ? poExpr->string_value : "(null)");
     427               2 :             CPLFree(col_def->field_name);
     428               2 :             col_def->field_name = NULL;
     429               2 :             CPLFree(col_def->field_alias);
     430               2 :             col_def->field_alias = NULL;
     431               2 :             result_columns--;
     432               2 :             return FALSE;
     433                 :         }
     434                 :         else
     435                 :         {
     436                 :             col_def->col_func = 
     437             106 :                 (swq_col_func) poExpr->nOperation;
     438                 : 
     439             106 :             swq_expr_node *poSubExpr = poExpr->papoSubExpr[0];
     440                 :         
     441             106 :             poExpr->papoSubExpr[0] = NULL;
     442             106 :             poExpr->nSubExprCount = 0;
     443             106 :             delete poExpr;
     444                 : 
     445             106 :             poExpr = poSubExpr;
     446                 :         }
     447                 :     }
     448                 : 
     449            1331 :     col_def->expr = poExpr;
     450                 : 
     451            1331 :     return TRUE;
     452                 : }
     453                 : 
     454                 : /************************************************************************/
     455                 : /*                            PushTableDef()                            */
     456                 : /************************************************************************/
     457                 : 
     458             262 : int swq_select::PushTableDef( const char *pszDataSource,
     459                 :                               const char *pszName,
     460                 :                               const char *pszAlias )
     461                 : 
     462                 : {
     463             262 :     table_count++;
     464                 : 
     465                 :     table_defs = (swq_table_def *) 
     466             262 :         CPLRealloc( table_defs, sizeof(swq_table_def) * table_count );
     467                 : 
     468             262 :     if( pszDataSource != NULL )
     469               5 :         table_defs[table_count-1].data_source = CPLStrdup(pszDataSource);
     470                 :     else
     471             257 :         table_defs[table_count-1].data_source = NULL;
     472                 : 
     473             262 :     table_defs[table_count-1].table_name = CPLStrdup(pszName);
     474                 : 
     475             262 :     if( pszAlias != NULL )
     476              16 :         table_defs[table_count-1].table_alias = CPLStrdup(pszAlias);
     477                 :     else
     478             246 :         table_defs[table_count-1].table_alias = CPLStrdup(pszName);
     479                 : 
     480             262 :     return table_count-1;
     481                 : }
     482                 : 
     483                 : /************************************************************************/
     484                 : /*                            PushOrderBy()                             */
     485                 : /************************************************************************/
     486                 : 
     487              23 : void swq_select::PushOrderBy( const char *pszFieldName, int bAscending )
     488                 : 
     489                 : {
     490              23 :     order_specs++;
     491                 :     order_defs = (swq_order_def *) 
     492              23 :         CPLRealloc( order_defs, sizeof(swq_order_def) * order_specs );
     493                 : 
     494              23 :     order_defs[order_specs-1].field_name = CPLStrdup(pszFieldName);
     495              23 :     order_defs[order_specs-1].table_index = -1;
     496              23 :     order_defs[order_specs-1].field_index = -1;
     497              23 :     order_defs[order_specs-1].ascending_flag = bAscending;
     498              23 : }
     499                 : 
     500                 : /************************************************************************/
     501                 : /*                              PushJoin()                              */
     502                 : /************************************************************************/
     503                 : 
     504              21 : void swq_select::PushJoin( int iSecondaryTable,
     505                 :                            const char *pszPrimaryField,
     506                 :                            const char *pszSecondaryField )
     507                 : 
     508                 : {
     509              21 :     join_count++;
     510                 :     join_defs = (swq_join_def *) 
     511              21 :         CPLRealloc( join_defs, sizeof(swq_join_def) * join_count );
     512                 : 
     513              21 :     join_defs[join_count-1].secondary_table = iSecondaryTable;
     514              21 :     join_defs[join_count-1].primary_field_name = CPLStrdup(pszPrimaryField);
     515              21 :     join_defs[join_count-1].primary_field = -1;
     516              21 :     join_defs[join_count-1].op = SWQ_EQ;
     517              21 :     join_defs[join_count-1].secondary_field_name = CPLStrdup(pszSecondaryField);
     518              21 :     join_defs[join_count-1].secondary_field = -1;
     519              21 : }
     520                 : 
     521                 : 
     522                 : /************************************************************************/
     523                 : /*                          expand_wildcard()                           */
     524                 : /*                                                                      */
     525                 : /*      This function replaces the '*' in a "SELECT *" with the list    */
     526                 : /*      provided list of fields.  Itis used by swq_select_parse(),      */
     527                 : /*      but may be called in advance by applications wanting the        */
     528                 : /*      "default" field list to be different than the full list of      */
     529                 : /*      fields.                                                         */
     530                 : /************************************************************************/
     531                 : 
     532             415 : CPLErr swq_select::expand_wildcard( swq_field_list *field_list )
     533                 : 
     534                 : {
     535                 :     int isrc;
     536                 : 
     537                 : /* ==================================================================== */
     538                 : /*      Check each pre-expansion field.                                 */
     539                 : /* ==================================================================== */
     540            3366 :     for( isrc = 0; isrc < result_columns; isrc++ )
     541                 :     {
     542            2951 :         const char *src_fieldname = column_defs[isrc].field_name;
     543                 :         int itable, new_fields, i, iout;
     544                 : 
     545            5864 :         if( *src_fieldname == '\0'
     546            2913 :             || src_fieldname[strlen(src_fieldname)-1] != '*' )
     547            2728 :             continue;
     548                 : 
     549                 :         /* We don't want to expand COUNT(*) */
     550             223 :         if( column_defs[isrc].col_func == SWQCF_COUNT )
     551             151 :             continue;
     552                 : 
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Parse out the table name, verify it, and establish the          */
     555                 : /*      number of fields to insert from it.                             */
     556                 : /* -------------------------------------------------------------------- */
     557              72 :         if( strcmp(src_fieldname,"*") == 0 )
     558                 :         {
     559              62 :             itable = -1;
     560              62 :             new_fields = field_list->count;
     561                 :         }
     562              20 :         else if( strlen(src_fieldname) < 3 
     563              10 :                  || src_fieldname[strlen(src_fieldname)-2] != '.' )
     564                 :         {
     565                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     566                 :                       "Ill formatted field definition '%s'.",
     567               0 :                      src_fieldname );
     568               0 :             return CE_Failure;
     569                 :         }
     570                 :         else
     571                 :         {
     572              10 :             char *table_name = CPLStrdup( src_fieldname );
     573              10 :             table_name[strlen(src_fieldname)-2] = '\0';
     574                 : 
     575              12 :             for( itable = 0; itable < field_list->table_count; itable++ )
     576                 :             {
     577              12 :                 if( strcasecmp(table_name,
     578              12 :                         field_list->table_defs[itable].table_alias ) == 0 )
     579              10 :                     break;
     580                 :             }
     581                 :             
     582              10 :             if( itable == field_list->table_count )
     583                 :             {
     584                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     585                 :                          "Table %s not recognised from %s definition.", 
     586               0 :                          table_name, src_fieldname );
     587               0 :                 CPLFree( table_name );
     588               0 :                 return CE_Failure;
     589                 :             }
     590              10 :             CPLFree( table_name );
     591                 :             
     592                 :             /* count the number of fields in this table. */
     593              10 :             new_fields = 0;
     594              66 :             for( i = 0; i < field_list->count; i++ )
     595                 :             {
     596              56 :                 if( field_list->table_ids[i] == itable )
     597              30 :                     new_fields++;
     598                 :             }
     599                 :         }
     600                 : 
     601              72 :         if (new_fields > 0)
     602                 :         {
     603                 : /* -------------------------------------------------------------------- */
     604                 : /*      Reallocate the column list larger.                              */
     605                 : /* -------------------------------------------------------------------- */
     606              70 :             CPLFree( column_defs[isrc].field_name );
     607              70 :             delete column_defs[isrc].expr;
     608                 : 
     609                 :             column_defs = (swq_col_def *) 
     610                 :                 CPLRealloc( column_defs, 
     611                 :                             sizeof(swq_col_def) * 
     612              70 :                             (result_columns + new_fields - 1 ) );
     613                 : 
     614                 : /* -------------------------------------------------------------------- */
     615                 : /*      Push the old definitions that came after the one to be          */
     616                 : /*      replaced further up in the array.                               */
     617                 : /* -------------------------------------------------------------------- */
     618              70 :             if (new_fields != 1)
     619                 :             {
     620              76 :                 for( i = result_columns-1; i > isrc; i-- )
     621                 :                 {
     622                 :                     memcpy( column_defs + i + new_fields - 1,
     623                 :                             column_defs + i,
     624              11 :                             sizeof( swq_col_def ) );
     625                 :                 }
     626                 :             }
     627                 : 
     628              70 :             result_columns += (new_fields - 1 );
     629                 : 
     630                 : /* -------------------------------------------------------------------- */
     631                 : /*      Zero out all the stuff in the target column definitions.        */
     632                 : /* -------------------------------------------------------------------- */
     633                 :             memset( column_defs + isrc, 0, 
     634              70 :                     new_fields * sizeof(swq_col_def) );
     635                 :         }
     636                 :         else
     637                 :         {
     638                 : /* -------------------------------------------------------------------- */
     639                 : /*      The wildcard expands to nothing                                 */
     640                 : /* -------------------------------------------------------------------- */
     641               2 :             CPLFree( column_defs[isrc].field_name );
     642               2 :             delete column_defs[isrc].expr;
     643                 : 
     644                 :             memmove( column_defs + isrc,
     645                 :                      column_defs + isrc + 1,
     646               2 :                      sizeof( swq_col_def ) * (result_columns-1-isrc) );
     647                 : 
     648               2 :             result_columns --;
     649                 :         }
     650                 : 
     651                 : /* -------------------------------------------------------------------- */
     652                 : /*      Assign the selected fields.                                     */
     653                 : /* -------------------------------------------------------------------- */
     654              72 :         iout = isrc;
     655                 :         
     656             331 :         for( i = 0; i < field_list->count; i++ )
     657                 :         {
     658                 :             swq_col_def *def;
     659             259 :             int compose = itable != -1;
     660                 : 
     661                 :             /* skip this field if it isn't in the target table.  */
     662             315 :             if( itable != -1 && field_list->table_ids != NULL 
     663              56 :                 && itable != field_list->table_ids[i] )
     664              26 :                 continue;
     665                 : 
     666                 :             /* set up some default values. */
     667             233 :             def = column_defs + iout;
     668             233 :             def->field_precision = -1; 
     669             233 :             def->target_type = SWQ_OTHER;
     670                 : 
     671                 :             /* does this field duplicate an earlier one? */
     672             466 :             if( field_list->table_ids != NULL 
     673             233 :                 && field_list->table_ids[i] != 0 
     674                 :                 && !compose )
     675                 :             {
     676                 :                 int other;
     677                 : 
     678             159 :                 for( other = 0; other < i; other++ )
     679                 :                 {
     680             270 :                     if( strcasecmp(field_list->names[i],
     681             135 :                                    field_list->names[other]) == 0 )
     682                 :                     {
     683               9 :                         compose = 1;
     684               9 :                         break;
     685                 :                     }
     686                 :                 }
     687                 :             }
     688                 : 
     689             233 :             if( !compose )
     690             194 :                 def->field_name = CPLStrdup( field_list->names[i] );
     691                 :             else
     692                 :             {
     693              39 :                 int itable = field_list->table_ids[i];
     694                 :                 char *composed_name;
     695              39 :                 const char *field_name = field_list->names[i];
     696                 :                 const char *table_alias = 
     697              39 :                     field_list->table_defs[itable].table_alias;
     698                 : 
     699                 :                 composed_name = (char *) 
     700              39 :                     CPLMalloc(strlen(field_name)+strlen(table_alias)+2);
     701                 : 
     702              39 :                 sprintf( composed_name, "%s.%s", table_alias, field_name );
     703                 : 
     704              39 :                 def->field_name = composed_name;
     705                 :             }             
     706                 : 
     707             233 :             iout++;
     708                 : 
     709                 :             /* All the other table info will be provided by the later
     710                 :                parse operation. */
     711                 :         }
     712                 : 
     713                 :         /* If there are several occurrences of '*', go on, but stay on the */
     714                 :         /* same index in case '*' is expanded to nothing */
     715                 :         /* (the -- is to compensate the fact that isrc will be incremented in */
     716                 :         /*  the after statement of the for loop) */
     717              72 :         isrc --;
     718                 :     }
     719                 : 
     720             415 :     return CE_None;
     721                 : }
     722                 : 
     723                 : /************************************************************************/
     724                 : /*                               parse()                                */
     725                 : /*                                                                      */
     726                 : /*      This method really does post-parse processing.                  */
     727                 : /************************************************************************/
     728                 : 
     729             208 : CPLErr swq_select::parse( swq_field_list *field_list,
     730                 :                           int parse_flags )
     731                 : 
     732                 : {
     733                 :     int  i;
     734                 :     CPLErr eError;
     735                 : 
     736             208 :     eError = expand_wildcard( field_list );
     737             208 :     if( eError != CE_None )
     738               0 :         return eError;
     739                 : 
     740                 :     
     741                 : /* -------------------------------------------------------------------- */
     742                 : /*      Identify field information.                                     */
     743                 : /* -------------------------------------------------------------------- */
     744            1637 :     for( i = 0; i < result_columns; i++ )
     745                 :     {
     746            1442 :         swq_col_def *def = column_defs + i;
     747                 : 
     748            1465 :         if( def->expr != NULL && def->expr->eNodeType != SNT_COLUMN )
     749                 :         {
     750              25 :             def->field_index = -1;
     751              25 :             def->table_index = -1;
     752                 : 
     753              25 :             if( def->expr->Check( field_list ) == SWQ_ERROR )
     754               2 :                 return CE_Failure;
     755                 :                 
     756              23 :             def->field_type = def->expr->field_type;
     757                 : 
     758                 :             // If the field was changed from string constant to 
     759                 :             // column field then adopt the name. 
     760              23 :             if( def->expr->eNodeType == SNT_COLUMN )
     761                 :             {
     762               2 :                 def->field_index = def->expr->field_index;
     763               2 :                 def->table_index = def->expr->table_index;
     764                 : 
     765               2 :                 CPLFree( def->field_name );
     766               2 :                 def->field_name = CPLStrdup(def->expr->string_value);
     767                 :             }
     768                 :         }
     769                 :         else
     770                 :         {
     771                 :             swq_field_type  this_type;
     772                 : 
     773                 :             /* identify field */
     774                 :             def->field_index = swq_identify_field( def->field_name, field_list,
     775                 :                                                    &this_type, 
     776            1417 :                                                    &(def->table_index) );
     777                 :             
     778                 :             /* record field type */
     779            1417 :             def->field_type = this_type;
     780                 :             
     781            1417 :             if( def->field_index == -1 && def->col_func != SWQCF_COUNT )
     782                 :             {
     783                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     784                 :                           "Unrecognised field name %s.", 
     785               7 :                           def->field_name );
     786               7 :                 return CE_Failure;
     787                 :             }
     788                 :         }
     789                 : 
     790                 :         /* identify column function if present */
     791            1433 :         if( (def->col_func == SWQCF_MIN 
     792                 :              || def->col_func == SWQCF_MAX
     793                 :              || def->col_func == SWQCF_AVG
     794                 :              || def->col_func == SWQCF_SUM)
     795                 :             && def->field_type == SWQ_STRING )
     796                 :         {
     797                 :             // possibly this is already enforced by the checker?
     798                 :             const swq_operation *op = swq_op_registrar::GetOperator( 
     799               4 :                 (swq_op) def->col_func );
     800                 :             
     801                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     802                 :                       "Use of field function %s() on string field %s illegal.", 
     803               4 :                           op->osName.c_str(), def->field_name );
     804               4 :             return CE_Failure;
     805                 :         }
     806                 :     }
     807                 : 
     808                 : /* -------------------------------------------------------------------- */
     809                 : /*      Check if we are producing a one row summary result or a set     */
     810                 : /*      of records.  Generate an error if we get conflicting            */
     811                 : /*      indications.                                                    */
     812                 : /* -------------------------------------------------------------------- */
     813             195 :     query_mode = -1;
     814            1618 :     for( i = 0; i < result_columns; i++ )
     815                 :     {
     816            1424 :         swq_col_def *def = column_defs + i;
     817            1424 :         int this_indicator = -1;
     818                 : 
     819            1519 :         if( def->col_func == SWQCF_MIN 
     820                 :             || def->col_func == SWQCF_MAX
     821                 :             || def->col_func == SWQCF_AVG
     822                 :             || def->col_func == SWQCF_SUM
     823                 :             || def->col_func == SWQCF_COUNT )
     824              95 :             this_indicator = SWQM_SUMMARY_RECORD;
     825            1329 :         else if( def->col_func == SWQCF_NONE )
     826                 :         {
     827            1329 :             if( def->distinct_flag )
     828              15 :                 this_indicator = SWQM_DISTINCT_LIST;
     829                 :             else
     830            1314 :                 this_indicator = SWQM_RECORDSET;
     831                 :         }
     832                 : 
     833            1424 :         if( this_indicator != query_mode
     834                 :              && this_indicator != -1
     835                 :             && query_mode != -1 )
     836                 :         {
     837                 :             CPLError( CE_Failure, CPLE_AppDefined,
     838               1 :                       "Field list implies mixture of regular recordset mode, summary mode or distinct field list mode." );
     839               1 :             return CE_Failure;
     840                 :         }
     841                 : 
     842            1423 :         if( this_indicator != -1 )
     843            1423 :             query_mode = this_indicator;
     844                 :     }
     845                 : 
     846             194 :     if( result_columns > 1 
     847                 :         && query_mode == SWQM_DISTINCT_LIST )
     848                 :     {
     849                 :         CPLError( CE_Failure, CPLE_AppDefined,
     850               0 :                   "SELECTing more than one DISTINCT field is a query not supported." );
     851               0 :         return CE_Failure;
     852                 :     }
     853             194 :     else if (result_columns == 0)
     854                 :     {
     855               1 :         query_mode = SWQM_RECORDSET;
     856                 :     }
     857                 : 
     858                 : /* -------------------------------------------------------------------- */
     859                 : /*      Process column names in JOIN specs.                             */
     860                 : /* -------------------------------------------------------------------- */
     861             211 :     for( i = 0; i < join_count; i++ )
     862                 :     {
     863              19 :         swq_join_def *def = join_defs + i;
     864                 :         int          table_id;
     865                 : 
     866                 :         /* identify primary field */
     867                 :         def->primary_field = swq_identify_field( def->primary_field_name,
     868              19 :                                                  field_list, NULL, &table_id );
     869              19 :         if( def->primary_field == -1 )
     870                 :         {
     871                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     872                 :                      "Unrecognised primary field %s in JOIN clause..", 
     873               0 :                      def->primary_field_name );
     874               0 :             return CE_Failure;
     875                 :         }
     876                 :         
     877              19 :         if( table_id != 0 )
     878                 :         {
     879                 :             CPLError( CE_Failure, CPLE_AppDefined,
     880                 :                      "Currently the primary key must come from the primary table in\n"
     881                 :                      "JOIN, %s is not from the primary table.",
     882               0 :                      def->primary_field_name );
     883               0 :             return CE_Failure;
     884                 :         }
     885                 :         
     886                 :         /* identify secondary field */
     887                 :         def->secondary_field = swq_identify_field( def->secondary_field_name,
     888              19 :                                                    field_list, NULL,&table_id);
     889              19 :         if( def->secondary_field == -1 )
     890                 :         {
     891                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     892                 :                      "Unrecognised secondary field %s in JOIN clause..", 
     893               2 :                      def->primary_field_name );
     894               2 :             return CE_Failure;
     895                 :         }
     896                 :         
     897              17 :         if( table_id != def->secondary_table )
     898                 :         {
     899                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     900                 :                      "Currently the secondary key must come from the secondary table\n"
     901                 :                      "listed in the JOIN.  %s is not from table %s..",
     902                 :                      def->primary_field_name,
     903               0 :                      table_defs[def->secondary_table].table_name);
     904               0 :             return CE_Failure;
     905                 :         }
     906                 :     }
     907                 : 
     908                 : /* -------------------------------------------------------------------- */
     909                 : /*      Process column names in order specs.                            */
     910                 : /* -------------------------------------------------------------------- */
     911             213 :     for( i = 0; i < order_specs; i++ )
     912                 :     {
     913              22 :         swq_order_def *def = order_defs + i;
     914                 : 
     915                 :         /* identify field */
     916                 :         def->field_index = swq_identify_field( def->field_name, field_list,
     917              22 :                                                NULL, &(def->table_index) );
     918              22 :         if( def->field_index == -1 )
     919                 :         {
     920                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     921                 :                       "Unrecognised field name %s in ORDER BY.", 
     922               1 :                      def->field_name );
     923               1 :             return CE_Failure;
     924                 :         }
     925                 :     }
     926                 : 
     927                 : /* -------------------------------------------------------------------- */
     928                 : /*      Post process the where clause, subbing in field indexes and     */
     929                 : /*      doing final validation.                                         */
     930                 : /* -------------------------------------------------------------------- */
     931             191 :     if( where_expr != NULL 
     932                 :         && where_expr->Check( field_list ) == SWQ_ERROR )
     933                 :     {
     934               7 :         return CE_Failure;
     935                 :     }
     936                 :     
     937             184 :     return CE_None;
     938                 : }
     939                 : 

Generated by: LCOV version 1.7