LCOV - code coverage report
Current view: directory - ogr - swq_select.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 371 289 77.9 %
Date: 2012-12-26 Functions: 14 11 78.6 %

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

Generated by: LCOV version 1.7