LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogr_gensql.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 630 519 82.4 %
Date: 2011-12-18 Functions: 27 24 88.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr_gensql.cpp 23531 2011-12-11 19:11:56Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRGenSQLResultsLayer.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "swq.h"
      31                 : #include "ogr_p.h"
      32                 : #include "ogr_gensql.h"
      33                 : #include "cpl_string.h"
      34                 : #include <vector>
      35                 : 
      36                 : CPL_CVSID("$Id: ogr_gensql.cpp 23531 2011-12-11 19:11:56Z rouault $");
      37                 : 
      38                 : 
      39                 : /************************************************************************/
      40                 : /*               OGRGenSQLResultsLayerHasSpecialField()                 */
      41                 : /************************************************************************/
      42                 : 
      43                 : static
      44               5 : int OGRGenSQLResultsLayerHasSpecialField(swq_expr_node* expr,
      45                 :                                          int nMinIndexForSpecialField)
      46                 : {
      47               5 :     if (expr->eNodeType == SNT_COLUMN)
      48                 :     {
      49               2 :         if (expr->table_index == 0)
      50                 :         {
      51               2 :             return expr->field_index >= nMinIndexForSpecialField;
      52                 :         }
      53                 :     }
      54               3 :     else if (expr->eNodeType == SNT_OPERATION)
      55                 :     {
      56               4 :         for( int i = 0; i < expr->nSubExprCount; i++ )
      57                 :         {
      58               3 :             if (OGRGenSQLResultsLayerHasSpecialField(expr->papoSubExpr[i],
      59                 :                                                      nMinIndexForSpecialField))
      60               1 :                 return TRUE;
      61                 :         }
      62                 :     }
      63               2 :     return FALSE;
      64                 : }
      65                 : 
      66                 : /************************************************************************/
      67                 : /*                       OGRGenSQLResultsLayer()                        */
      68                 : /************************************************************************/
      69                 : 
      70             183 : OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
      71                 :                                               void *pSelectInfo, 
      72                 :                                               OGRGeometry *poSpatFilter,
      73                 :                                               const char *pszWHERE,
      74             183 :                                               const char *pszDialect )
      75                 : 
      76                 : {
      77             183 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
      78                 : 
      79             183 :     this->poSrcDS = poSrcDS;
      80             183 :     this->pSelectInfo = pSelectInfo;
      81             183 :     poDefn = NULL;
      82             183 :     poSummaryFeature = NULL;
      83             183 :     panFIDIndex = NULL;
      84             183 :     nIndexSize = 0;
      85             183 :     nNextIndexFID = 0;
      86             183 :     nExtraDSCount = 0;
      87             183 :     papoExtraDS = NULL;
      88                 : 
      89                 : /* -------------------------------------------------------------------- */
      90                 : /*      Identify all the layers involved in the SELECT.                 */
      91                 : /* -------------------------------------------------------------------- */
      92                 :     int iTable;
      93                 : 
      94                 :     papoTableLayers = (OGRLayer **) 
      95             183 :         CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count );
      96                 : 
      97             383 :     for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
      98                 :     {
      99             200 :         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
     100             200 :         OGRDataSource *poTableDS = poSrcDS;
     101                 : 
     102             200 :         if( psTableDef->data_source != NULL )
     103                 :         {
     104               5 :             OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
     105                 : 
     106                 :             poTableDS = 
     107               5 :                 poReg->OpenShared( psTableDef->data_source, FALSE, NULL );
     108               5 :             if( poTableDS == NULL )
     109                 :             {
     110               0 :                 if( strlen(CPLGetLastErrorMsg()) == 0 )
     111                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     112                 :                               "Unable to open secondary datasource\n"
     113                 :                               "`%s' required by JOIN.",
     114               0 :                               psTableDef->data_source );
     115               0 :                 return;
     116                 :             }
     117                 : 
     118                 :             papoExtraDS = (OGRDataSource **)
     119               5 :                 CPLRealloc( papoExtraDS, sizeof(void*) * ++nExtraDSCount );
     120                 : 
     121               5 :             papoExtraDS[nExtraDSCount-1] = poTableDS;
     122                 :         }
     123                 : 
     124             200 :         papoTableLayers[iTable] = 
     125             200 :             poTableDS->GetLayerByName( psTableDef->table_name );
     126                 :         
     127             200 :         CPLAssert( papoTableLayers[iTable] != NULL );
     128                 : 
     129             200 :         if( papoTableLayers[iTable] == NULL )
     130               0 :             return;
     131                 :     }
     132                 :     
     133             183 :     poSrcLayer = papoTableLayers[0];
     134                 : 
     135                 : /* -------------------------------------------------------------------- */
     136                 : /*      If the user has explicitely requested a OGRSQL dialect, then    */
     137                 : /*      we should avoid to forward the where clause to the source layer */
     138                 : /*      when there is a risk it cannot understand it (#4022)            */
     139                 : /* -------------------------------------------------------------------- */
     140             183 :     int bForwardWhereToSourceLayer = TRUE;
     141             183 :     if( pszWHERE )
     142                 :     {
     143              52 :         if( psSelectInfo->where_expr && pszDialect != NULL &&
     144                 :             EQUAL(pszDialect, "OGRSQL") )
     145                 :         {
     146               2 :             int nMinIndexForSpecialField = poSrcLayer->GetLayerDefn()->GetFieldCount();
     147                 :             bForwardWhereToSourceLayer = !OGRGenSQLResultsLayerHasSpecialField
     148               2 :                             (psSelectInfo->where_expr, nMinIndexForSpecialField);
     149                 :         }
     150              52 :         if (bForwardWhereToSourceLayer)
     151              51 :             this->pszWHERE = CPLStrdup(pszWHERE);
     152                 :         else
     153               1 :             this->pszWHERE = NULL;
     154                 :     }
     155                 :     else
     156             131 :         this->pszWHERE = NULL;
     157                 : 
     158                 : /* -------------------------------------------------------------------- */
     159                 : /*      Now that we have poSrcLayer, we can install a spatial filter    */
     160                 : /*      if there is one.                                                */
     161                 : /* -------------------------------------------------------------------- */
     162             183 :     if( poSpatFilter != NULL )
     163               0 :         SetSpatialFilter( poSpatFilter );
     164                 : 
     165                 : /* -------------------------------------------------------------------- */
     166                 : /*      Prepare a feature definition based on the query.                */
     167                 : /* -------------------------------------------------------------------- */
     168             183 :     OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
     169                 : 
     170             183 :     poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias );
     171             183 :     poDefn->Reference();
     172                 : 
     173             183 :     iFIDFieldIndex = poSrcDefn->GetFieldCount();
     174                 : 
     175            1576 :     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     176                 :     {
     177            1393 :         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     178            1393 :         OGRFieldDefn oFDefn( "", OFTInteger );
     179            1393 :         OGRFieldDefn *poSrcFDefn = NULL;
     180            1393 :         OGRFeatureDefn *poLayerDefn = NULL;
     181                 : 
     182            1393 :         if( psColDef->table_index != -1 )
     183                 :             poLayerDefn = 
     184            1372 :                 papoTableLayers[psColDef->table_index]->GetLayerDefn();
     185                 : 
     186            1393 :         if( psColDef->field_index > -1 
     187                 :             && poLayerDefn != NULL
     188                 :             && psColDef->field_index < poLayerDefn->GetFieldCount() )
     189            1287 :             poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
     190                 : 
     191            1393 :         if( strlen(psColDef->field_name) == 0 )
     192                 :         {
     193              16 :             CPLFree( psColDef->field_name );
     194              16 :             psColDef->field_name = (char *) CPLMalloc(40);
     195              16 :             sprintf( psColDef->field_name, "FIELD_%d", iField+1 );
     196                 :         }
     197                 : 
     198            1393 :         if( psColDef->field_alias != NULL )
     199                 :         {
     200               5 :             oFDefn.SetName(psColDef->field_alias);
     201                 :         }
     202            1388 :         else if( psColDef->col_func != SWQCF_NONE )
     203                 :         {
     204                 :             const swq_operation *op = swq_op_registrar::GetOperator( 
     205              88 :                 (swq_op) psColDef->col_func );
     206                 : 
     207                 :             oFDefn.SetName( CPLSPrintf( "%s_%s",
     208                 :                                         op->osName.c_str(),
     209              88 :                                         psColDef->field_name ) );
     210                 :         }
     211                 :         else
     212            1300 :             oFDefn.SetName( psColDef->field_name );
     213                 : 
     214            1393 :         if( psColDef->col_func == SWQCF_COUNT )
     215              83 :             oFDefn.SetType( OFTInteger );
     216            1310 :         else if( poSrcFDefn != NULL )
     217                 :         {
     218            1279 :             oFDefn.SetType( poSrcFDefn->GetType() );
     219            1279 :             if( psColDef->col_func != SWQCF_AVG )
     220                 :             {
     221            1278 :                 oFDefn.SetWidth( poSrcFDefn->GetWidth() );
     222            1278 :                 oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
     223                 :             }
     224                 :         }
     225              31 :         else if ( psColDef->field_index >= iFIDFieldIndex )
     226                 :         {
     227              10 :             switch ( SpecialFieldTypes[psColDef->field_index-iFIDFieldIndex] )
     228                 :             {
     229                 :               case SWQ_INTEGER:
     230               5 :                 oFDefn.SetType( OFTInteger );
     231               5 :                 break;
     232                 :               case SWQ_FLOAT:
     233               1 :                 oFDefn.SetType( OFTReal );
     234               1 :                 break;
     235                 :               default:
     236               4 :                 oFDefn.SetType( OFTString );
     237                 :                 break;
     238                 :             }
     239                 :         }
     240                 :         else
     241                 :         {
     242              21 :             switch( psColDef->field_type )
     243                 :             {
     244                 :               case SWQ_INTEGER:
     245                 :               case SWQ_BOOLEAN:
     246               7 :                 oFDefn.SetType( OFTInteger );
     247               7 :                 break;
     248                 :                 
     249                 :               case SWQ_FLOAT:
     250               5 :                 oFDefn.SetType( OFTReal );
     251               5 :                 break;
     252                 : 
     253                 :               default:
     254               9 :                 oFDefn.SetType( OFTString );
     255                 :                 break;
     256                 :             }
     257                 :         }
     258                 : 
     259                 :         /* setting up the target_type */
     260            1393 :         switch (psColDef->target_type)
     261                 :         {
     262                 :           case SWQ_OTHER:
     263            1390 :             break;
     264                 :           case SWQ_INTEGER:
     265                 :           case SWQ_BOOLEAN:
     266               1 :             oFDefn.SetType( OFTInteger );
     267               1 :             break;
     268                 :           case SWQ_FLOAT:
     269               1 :             oFDefn.SetType( OFTReal );
     270               1 :             break;
     271                 :           case SWQ_STRING:
     272               1 :             oFDefn.SetType( OFTString );
     273               1 :             break;
     274                 :           case SWQ_TIMESTAMP:
     275               0 :             oFDefn.SetType( OFTDateTime );
     276               0 :             break;
     277                 :           case SWQ_DATE:
     278               0 :             oFDefn.SetType( OFTDate );
     279               0 :             break;
     280                 :           case SWQ_TIME:
     281               0 :             oFDefn.SetType( OFTTime );
     282               0 :             break;
     283                 : 
     284                 :           default:
     285               0 :             CPLAssert( FALSE );
     286               0 :             oFDefn.SetType( OFTString );
     287                 :             break;
     288                 :         }
     289                 : 
     290            1393 :         if (psColDef->field_length > 0)
     291                 :         {
     292               2 :             oFDefn.SetWidth( psColDef->field_length );
     293                 :         }
     294                 : 
     295            1393 :         if (psColDef->field_precision >= 0)
     296                 :         {
     297               1 :             oFDefn.SetPrecision( psColDef->field_precision );
     298                 :         }
     299                 : 
     300            1393 :         poDefn->AddFieldDefn( &oFDefn );
     301                 :     }
     302                 : 
     303             183 :     poDefn->SetGeomType( poSrcLayer->GetLayerDefn()->GetGeomType() );
     304                 : 
     305                 : /* -------------------------------------------------------------------- */
     306                 : /*      If an ORDER BY is in effect, apply it now.                      */
     307                 : /* -------------------------------------------------------------------- */
     308             183 :     if( psSelectInfo->order_specs > 0 
     309                 :         && psSelectInfo->query_mode == SWQM_RECORDSET )
     310              10 :         CreateOrderByIndex();
     311                 : 
     312             183 :     ResetReading();
     313                 : 
     314             183 :     FindAndSetIgnoredFields();
     315                 : 
     316             183 :     if( !bForwardWhereToSourceLayer )
     317               1 :         SetAttributeFilter( pszWHERE );
     318               0 : }
     319                 : 
     320                 : /************************************************************************/
     321                 : /*                       ~OGRGenSQLResultsLayer()                       */
     322                 : /************************************************************************/
     323                 : 
     324             183 : OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
     325                 : 
     326                 : {
     327             183 :     if( m_nFeaturesRead > 0 && poDefn != NULL )
     328                 :     {
     329                 :         CPLDebug( "GenSQL", "%d features read on layer '%s'.",
     330                 :                   (int) m_nFeaturesRead, 
     331              70 :                   poDefn->GetName() );
     332                 :     }
     333                 : 
     334             183 :     ClearFilters();
     335                 : 
     336                 : /* -------------------------------------------------------------------- */
     337                 : /*      Free various datastructures.                                    */
     338                 : /* -------------------------------------------------------------------- */
     339             183 :     CPLFree( papoTableLayers );
     340             183 :     papoTableLayers = NULL;
     341                 :              
     342             183 :     CPLFree( panFIDIndex );
     343                 : 
     344             183 :     delete poSummaryFeature;
     345             183 :     delete (swq_select *) pSelectInfo;
     346                 : 
     347             183 :     if( poDefn != NULL )
     348                 :     {
     349             183 :         poDefn->Release();
     350                 :     }
     351                 : 
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Release any additional datasources being used in joins.         */
     354                 : /* -------------------------------------------------------------------- */
     355             183 :     OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
     356                 : 
     357             188 :     for( int iEDS = 0; iEDS < nExtraDSCount; iEDS++ )
     358               5 :         poReg->ReleaseDataSource( papoExtraDS[iEDS] );
     359                 : 
     360             183 :     CPLFree( papoExtraDS );
     361             183 :     CPLFree( pszWHERE );
     362             183 : }
     363                 : 
     364                 : /************************************************************************/
     365                 : /*                            ClearFilters()                            */
     366                 : /*                                                                      */
     367                 : /*      Clear up all filters currently in place on the target layer,    */
     368                 : /*      and joined layers.  We try not to leave them installed          */
     369                 : /*      except when actively fetching features.                         */
     370                 : /************************************************************************/
     371                 : 
     372             207 : void OGRGenSQLResultsLayer::ClearFilters()
     373                 : 
     374                 : {
     375                 : /* -------------------------------------------------------------------- */
     376                 : /*      Clear any filters installed on the target layer.                */
     377                 : /* -------------------------------------------------------------------- */
     378             207 :     if( poSrcLayer != NULL )
     379                 :     {
     380             207 :         poSrcLayer->SetAttributeFilter( "" );
     381             207 :         poSrcLayer->SetSpatialFilter( NULL );
     382                 :     }
     383                 : 
     384                 : /* -------------------------------------------------------------------- */
     385                 : /*      Clear any attribute filter installed on the joined layers.      */
     386                 : /* -------------------------------------------------------------------- */
     387             207 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     388                 :     int iJoin;
     389                 : 
     390             207 :     if( psSelectInfo != NULL )
     391                 :     {
     392             224 :         for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
     393                 :         {
     394              17 :             swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
     395                 :             OGRLayer *poJoinLayer = 
     396              17 :                 papoTableLayers[psJoinInfo->secondary_table];
     397                 :             
     398              17 :             poJoinLayer->SetAttributeFilter( "" );
     399                 :         }
     400                 :     }
     401                 : 
     402                 : /* -------------------------------------------------------------------- */
     403                 : /*      Clear any ignored field lists installed on source layers        */
     404                 : /* -------------------------------------------------------------------- */
     405             207 :     if( psSelectInfo != NULL )
     406                 :     {
     407             431 :         for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
     408                 :         {
     409             224 :             OGRLayer* poLayer = papoTableLayers[iTable];
     410             224 :             poLayer->SetIgnoredFields(NULL);
     411                 :         }
     412                 :     }
     413             207 : }
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                            ResetReading()                            */
     417                 : /************************************************************************/
     418                 : 
     419             266 : void OGRGenSQLResultsLayer::ResetReading() 
     420                 : 
     421                 : {
     422             266 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     423                 : 
     424             266 :     if( psSelectInfo->query_mode == SWQM_RECORDSET )
     425                 :     {
     426             170 :         poSrcLayer->SetAttributeFilter( pszWHERE );
     427             170 :         poSrcLayer->SetSpatialFilter( m_poFilterGeom );
     428                 :         
     429             170 :         poSrcLayer->ResetReading();
     430                 :     }
     431                 : 
     432             266 :     nNextIndexFID = 0;
     433             266 : }
     434                 : 
     435                 : /************************************************************************/
     436                 : /*                           SetNextByIndex()                           */
     437                 : /*                                                                      */
     438                 : /*      If we already have an FID list, we can easily resposition       */
     439                 : /*      ourselves in it.                                                */
     440                 : /************************************************************************/
     441                 : 
     442               2 : OGRErr OGRGenSQLResultsLayer::SetNextByIndex( long nIndex )
     443                 : 
     444                 : {
     445               2 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     446                 : 
     447               2 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
     448                 :         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST 
     449                 :         || panFIDIndex != NULL )
     450                 :     {
     451               0 :         nNextIndexFID = nIndex;
     452               0 :         return OGRERR_NONE;
     453                 :     }
     454                 :     else
     455                 :     {
     456               2 :         return poSrcLayer->SetNextByIndex( nIndex );
     457                 :     }
     458                 : }
     459                 : 
     460                 : /************************************************************************/
     461                 : /*                             GetExtent()                              */
     462                 : /************************************************************************/
     463                 : 
     464               4 : OGRErr OGRGenSQLResultsLayer::GetExtent( OGREnvelope *psExtent, 
     465                 :                                          int bForce )
     466                 : 
     467                 : {
     468               4 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     469                 : 
     470               4 :     if( psSelectInfo->query_mode == SWQM_RECORDSET )
     471               4 :         return poSrcLayer->GetExtent( psExtent, bForce );
     472                 :     else
     473               0 :         return OGRERR_FAILURE;
     474                 : }
     475                 : 
     476                 : /************************************************************************/
     477                 : /*                           GetSpatialRef()                            */
     478                 : /************************************************************************/
     479                 : 
     480              19 : OGRSpatialReference *OGRGenSQLResultsLayer::GetSpatialRef() 
     481                 : 
     482                 : {
     483              19 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     484                 : 
     485              19 :     if( psSelectInfo->query_mode != SWQM_RECORDSET )
     486               0 :         return NULL;
     487                 :     else
     488              19 :         return poSrcLayer->GetSpatialRef();
     489                 : }
     490                 : 
     491                 : /************************************************************************/
     492                 : /*                          GetFeatureCount()                           */
     493                 : /************************************************************************/
     494                 : 
     495              49 : int OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
     496                 : 
     497                 : {
     498              49 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     499                 : 
     500              49 :     if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
     501                 :     {
     502               2 :         if( !PrepareSummary() )
     503               0 :             return 0;
     504                 : 
     505               2 :         swq_summary *psSummary = psSelectInfo->column_summary + 0;
     506                 : 
     507               2 :         if( psSummary == NULL )
     508               0 :             return 0;
     509                 : 
     510               2 :         return psSummary->count;
     511                 :     }
     512              47 :     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
     513               0 :         return 1;
     514              47 :     else if( m_poAttrQuery == NULL )
     515              43 :         return poSrcLayer->GetFeatureCount( bForce );
     516                 :     else
     517               4 :         return OGRLayer::GetFeatureCount( bForce );
     518                 : }
     519                 : 
     520                 : /************************************************************************/
     521                 : /*                           TestCapability()                           */
     522                 : /************************************************************************/
     523                 : 
     524              10 : int OGRGenSQLResultsLayer::TestCapability( const char *pszCap )
     525                 : 
     526                 : {
     527              10 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     528                 : 
     529              10 :     if( EQUAL(pszCap,OLCFastSetNextByIndex) )
     530                 :     {
     531               2 :         if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
     532                 :             || psSelectInfo->query_mode == SWQM_DISTINCT_LIST 
     533                 :             || panFIDIndex != NULL )
     534               0 :             return TRUE;
     535                 :         else 
     536               2 :             return poSrcLayer->TestCapability( pszCap );
     537                 :     }
     538                 : 
     539               8 :     if( psSelectInfo->query_mode == SWQM_RECORDSET
     540                 :         && (EQUAL(pszCap,OLCFastFeatureCount) 
     541                 :             || EQUAL(pszCap,OLCRandomRead) 
     542                 :             || EQUAL(pszCap,OLCFastGetExtent)) )
     543               2 :         return poSrcLayer->TestCapability( pszCap );
     544                 : 
     545               6 :     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
     546                 :     {
     547               0 :         if( EQUAL(pszCap,OLCFastFeatureCount) )
     548               0 :             return TRUE;
     549                 :     }
     550               6 :     return FALSE;
     551                 : }
     552                 : 
     553                 : /************************************************************************/
     554                 : /*                        ContainGeomSpecialField()                     */
     555                 : /************************************************************************/
     556                 : 
     557              17 : int OGRGenSQLResultsLayer::ContainGeomSpecialField(swq_expr_node* expr)
     558                 : {
     559              17 :     if (expr->eNodeType == SNT_COLUMN)
     560                 :     {
     561               6 :         if( expr->table_index != -1 && expr->field_index != -1 )
     562                 :         {
     563               6 :             OGRLayer* poLayer = papoTableLayers[expr->table_index];
     564                 :             int nSpecialFieldIdx = expr->field_index -
     565               6 :                             poLayer->GetLayerDefn()->GetFieldCount();
     566                 :             return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
     567                 :                    nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
     568               6 :                    nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
     569                 :         }
     570                 :     }
     571              11 :     else if (expr->eNodeType == SNT_OPERATION)
     572                 :     {
     573              17 :         for( int i = 0; i < expr->nSubExprCount; i++ )
     574                 :         {
     575              11 :             if (ContainGeomSpecialField(expr->papoSubExpr[i]))
     576               0 :                 return TRUE;
     577                 :         }
     578                 :     }
     579              11 :     return FALSE;
     580                 : }
     581                 : 
     582                 : /************************************************************************/
     583                 : /*                           PrepareSummary()                           */
     584                 : /************************************************************************/
     585                 : 
     586             155 : int OGRGenSQLResultsLayer::PrepareSummary()
     587                 : 
     588                 : {
     589             155 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     590                 : 
     591             155 :     if( poSummaryFeature != NULL )
     592              60 :         return TRUE;
     593                 : 
     594              95 :     poSummaryFeature = new OGRFeature( poDefn );
     595              95 :     poSummaryFeature->SetFID( 0 );
     596                 : 
     597                 : /* -------------------------------------------------------------------- */
     598                 : /*      Ensure our query parameters are in place on the source          */
     599                 : /*      layer.  And initialize reading.                                 */
     600                 : /* -------------------------------------------------------------------- */
     601              95 :     poSrcLayer->SetAttributeFilter(pszWHERE);
     602              95 :     poSrcLayer->SetSpatialFilter( m_poFilterGeom );
     603                 :         
     604              95 :     poSrcLayer->ResetReading();
     605                 : 
     606                 : /* -------------------------------------------------------------------- */
     607                 : /*      Ignore geometry reading if no spatial filter in place and that  */
     608                 : /*      the where clause doesn't include OGR_GEOMETRY, OGR_GEOM_WKT or  */
     609                 : /*      OGR_GEOM_AREA special fields.                                   */
     610                 : /* -------------------------------------------------------------------- */
     611              95 :     int bSaveIsGeomIgnored = poSrcLayer->GetLayerDefn()->IsGeometryIgnored();
     612             190 :     if ( m_poFilterGeom == NULL && ( psSelectInfo->where_expr == NULL ||
     613                 :                 !ContainGeomSpecialField(psSelectInfo->where_expr) ) )
     614                 :     {
     615              95 :         poSrcLayer->GetLayerDefn()->SetGeometryIgnored(TRUE);
     616                 :     }
     617                 : 
     618                 : /* -------------------------------------------------------------------- */
     619                 : /*      We treat COUNT(*) as a special case, and fill with              */
     620                 : /*      GetFeatureCount().                                              */
     621                 : /* -------------------------------------------------------------------- */
     622                 : 
     623             256 :     if( psSelectInfo->result_columns == 1 
     624              90 :         && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
     625              71 :         && psSelectInfo->column_defs[0].field_index < 0 )
     626                 :     {
     627              71 :         poSummaryFeature->SetField( 0, poSrcLayer->GetFeatureCount( TRUE ) );
     628              71 :         poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
     629              71 :         return TRUE;
     630                 :     }
     631                 : 
     632                 : /* -------------------------------------------------------------------- */
     633                 : /*      Otherwise, process all source feature through the summary       */
     634                 : /*      building facilities of SWQ.                                     */
     635                 : /* -------------------------------------------------------------------- */
     636                 :     const char *pszError;
     637                 :     OGRFeature *poSrcFeature;
     638                 :     int iField;
     639                 : 
     640             267 :     while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
     641                 :     {
     642             475 :         for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
     643                 :         {
     644             256 :             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     645                 : 
     646             256 :             if (psColDef->col_func == SWQCF_COUNT)
     647                 :             {
     648                 :                 /* psColDef->field_index can be -1 in the case of a COUNT(*) */
     649              52 :                 if (psColDef->field_index < 0)
     650              22 :                     pszError = swq_select_summarize( psSelectInfo, iField, "" );
     651              30 :                 else if (poSrcFeature->IsFieldSet(psColDef->field_index))
     652                 :                     pszError = swq_select_summarize( psSelectInfo, iField, poSrcFeature->GetFieldAsString(
     653              18 :                                                 psColDef->field_index ) );
     654                 :                 else
     655              12 :                     pszError = NULL;
     656                 :             }
     657                 :             else
     658                 :             {
     659             204 :                 const char* pszVal = NULL;
     660             204 :                 if (poSrcFeature->IsFieldSet(psColDef->field_index))
     661                 :                     pszVal = poSrcFeature->GetFieldAsString(
     662             188 :                                                 psColDef->field_index );
     663             204 :                 pszError = swq_select_summarize( psSelectInfo, iField, pszVal );
     664                 :             }
     665                 :             
     666             256 :             if( pszError != NULL )
     667                 :             {
     668               0 :                 delete poSrcFeature;
     669               0 :                 delete poSummaryFeature;
     670               0 :                 poSummaryFeature = NULL;
     671                 : 
     672               0 :                 poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
     673                 : 
     674               0 :                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
     675               0 :                 return FALSE;
     676                 :             }
     677                 :         }
     678                 : 
     679             219 :         delete poSrcFeature;
     680                 :     }
     681                 : 
     682              24 :     poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
     683                 : 
     684              24 :     pszError = swq_select_finish_summarize( psSelectInfo );
     685              24 :     if( pszError != NULL )
     686                 :     {
     687               0 :         delete poSummaryFeature;
     688               0 :         poSummaryFeature = NULL;
     689                 :         
     690               0 :         CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
     691               0 :         return FALSE;
     692                 :     }
     693                 : 
     694                 : /* -------------------------------------------------------------------- */
     695                 : /*      If we have run out of features on the source layer, clear       */
     696                 : /*      away the filters we have installed till a next run through      */
     697                 : /*      the features.                                                   */
     698                 : /* -------------------------------------------------------------------- */
     699              24 :     if( poSrcFeature == NULL )
     700              24 :         ClearFilters();
     701                 : 
     702                 : /* -------------------------------------------------------------------- */
     703                 : /*      Now apply the values to the summary feature.  If we are in      */
     704                 : /*      DISTINCT_LIST mode we don't do this step.                       */
     705                 : /* -------------------------------------------------------------------- */
     706              24 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
     707                 :     {
     708              28 :         for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
     709                 :         {
     710              18 :             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     711              18 :             if (psSelectInfo->column_summary != NULL)
     712                 :             {
     713              14 :                 swq_summary *psSummary = psSelectInfo->column_summary + iField;
     714                 : 
     715              14 :                 if( psColDef->col_func == SWQCF_AVG )
     716                 :                     poSummaryFeature->SetField( iField,
     717               0 :                                             psSummary->sum / psSummary->count );
     718              14 :                 else if( psColDef->col_func == SWQCF_MIN )
     719               1 :                     poSummaryFeature->SetField( iField, psSummary->min );
     720              13 :                 else if( psColDef->col_func == SWQCF_MAX )
     721               1 :                     poSummaryFeature->SetField( iField, psSummary->max );
     722              12 :                 else if( psColDef->col_func == SWQCF_COUNT )
     723              12 :                     poSummaryFeature->SetField( iField, psSummary->count );
     724               0 :                 else if( psColDef->col_func == SWQCF_SUM )
     725               0 :                     poSummaryFeature->SetField( iField, psSummary->sum );
     726                 :             }
     727               4 :             else if ( psColDef->col_func == SWQCF_COUNT )
     728               0 :                 poSummaryFeature->SetField( iField, 0 );
     729                 :         }
     730                 :     }
     731                 : 
     732              24 :     return TRUE;
     733                 : }
     734                 : 
     735                 : /************************************************************************/
     736                 : /*                       OGRMultiFeatureFetcher()                       */
     737                 : /************************************************************************/
     738                 : 
     739              13 : static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op, 
     740                 :                                               void *pFeatureList )
     741                 : 
     742                 : {
     743                 :     std::vector<OGRFeature*> *papoFeatures = 
     744              13 :         (std::vector<OGRFeature*> *) pFeatureList;
     745                 :     OGRFeature *poFeature;
     746              13 :     swq_expr_node *poRetNode = NULL;
     747                 : 
     748              13 :     CPLAssert( op->eNodeType == SNT_COLUMN );
     749                 : 
     750                 : /* -------------------------------------------------------------------- */
     751                 : /*      What feature are we using?  The primary or one of the joined ones?*/
     752                 : /* -------------------------------------------------------------------- */
     753              13 :     if( op->table_index < 0 || op->table_index >= (int)papoFeatures->size() )
     754                 :     {
     755                 :         CPLError( CE_Failure, CPLE_AppDefined,
     756                 :                   "Request for unexpected table_index (%d) in field fetcher.",
     757               0 :                   op->table_index );
     758               0 :         return NULL;
     759                 :     }
     760                 :     
     761              13 :     poFeature = (*papoFeatures)[op->table_index];
     762                 : 
     763                 : /* -------------------------------------------------------------------- */
     764                 : /*      Fetch the value.                                                */
     765                 : /* -------------------------------------------------------------------- */
     766              13 :     switch( op->field_type )
     767                 :     {
     768                 :       case SWQ_INTEGER:
     769                 :       case SWQ_BOOLEAN:
     770               5 :         if( poFeature == NULL 
     771                 :             || !poFeature->IsFieldSet(op->field_index) )
     772                 :         {
     773               0 :             poRetNode = new swq_expr_node(0);
     774               0 :             poRetNode->is_null = TRUE;
     775                 :         }
     776                 :         else
     777                 :             poRetNode = new swq_expr_node( 
     778               5 :                 poFeature->GetFieldAsInteger(op->field_index) );
     779               5 :         break;
     780                 : 
     781                 :       case SWQ_FLOAT:
     782               2 :         if( poFeature == NULL 
     783                 :             || !poFeature->IsFieldSet(op->field_index) )
     784                 :         {
     785               0 :             poRetNode = new swq_expr_node( 0.0 );
     786               0 :             poRetNode->is_null = TRUE;
     787                 :         }
     788                 :         else
     789                 :             poRetNode = new swq_expr_node( 
     790               2 :                 poFeature->GetFieldAsDouble(op->field_index) );
     791               2 :         break;
     792                 :         
     793                 :       default:
     794               6 :         if( poFeature == NULL 
     795                 :             || !poFeature->IsFieldSet(op->field_index) )
     796                 :         {
     797               0 :             poRetNode = new swq_expr_node("");
     798               0 :             poRetNode->is_null = TRUE;
     799                 :         }
     800                 :         else
     801                 :             poRetNode = new swq_expr_node( 
     802               6 :                 poFeature->GetFieldAsString(op->field_index) );
     803                 :         break;
     804                 :     }
     805                 : 
     806              13 :     return poRetNode;
     807                 : }
     808                 : 
     809                 : /************************************************************************/
     810                 : /*                          TranslateFeature()                          */
     811                 : /************************************************************************/
     812                 : 
     813           56824 : OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
     814                 : 
     815                 : {
     816           56824 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     817                 :     OGRFeature *poDstFeat;
     818           56824 :     std::vector<OGRFeature*> apoFeatures;
     819                 : 
     820           56824 :     if( poSrcFeat == NULL )
     821               0 :         return NULL;
     822                 : 
     823           56824 :     m_nFeaturesRead++;
     824                 : 
     825           56824 :     apoFeatures.push_back( poSrcFeat );
     826                 : 
     827                 : /* -------------------------------------------------------------------- */
     828                 : /*      Fetch the corresponding features from any jointed tables.       */
     829                 : /* -------------------------------------------------------------------- */
     830                 :     int iJoin;
     831                 : 
     832           56824 :     for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
     833                 :     {
     834              80 :         CPLString osFilter;
     835                 : 
     836              80 :         swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
     837              80 :         OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table];
     838                 :         
     839                 :         // if source key is null, we can't do join.
     840              80 :         if( !poSrcFeat->IsFieldSet( psJoinInfo->primary_field ) )
     841                 :         {
     842               0 :             apoFeatures.push_back( NULL );
     843               0 :             continue;
     844                 :         }
     845                 :         
     846                 :         OGRFieldDefn* poSecondaryFieldDefn =
     847              80 :             poJoinLayer->GetLayerDefn()->GetFieldDefn( 
     848             160 :                      psJoinInfo->secondary_field );
     849              80 :         OGRFieldType ePrimaryFieldType = poSrcLayer->GetLayerDefn()->
     850             160 :                     GetFieldDefn(psJoinInfo->primary_field )->GetType();
     851              80 :         OGRFieldType eSecondaryFieldType = poSecondaryFieldDefn->GetType();
     852                 : 
     853                 :         // Prepare attribute query to express fetching on the joined variable
     854                 :         
     855                 :         // If joining a (primary) numeric column with a (secondary) string column
     856                 :         // then add implicit casting of the secondary column to numeric. This behaviour
     857                 :         // worked in GDAL < 1.8, and it is consistant with how sqlite behaves too. See #4321
     858                 :         // For the reverse case, joining a string column with a numeric column, the
     859                 :         // string constant will be cast to float by SWQAutoConvertStringToNumeric (#4259)
     860             100 :         if( eSecondaryFieldType == OFTString &&
     861                 :             (ePrimaryFieldType == OFTInteger || ePrimaryFieldType == OFTReal) )
     862              20 :             osFilter.Printf("CAST(%s AS FLOAT) = ", poSecondaryFieldDefn->GetNameRef() );
     863                 :         else
     864              60 :             osFilter.Printf("%s = ", poSecondaryFieldDefn->GetNameRef() );
     865                 : 
     866                 :         OGRField *psSrcField = 
     867              80 :             poSrcFeat->GetRawFieldRef(psJoinInfo->primary_field);
     868                 : 
     869              80 :         switch( ePrimaryFieldType )
     870                 :         {
     871                 :           case OFTInteger:
     872              12 :             osFilter += CPLString().Printf("%d", psSrcField->Integer );
     873              12 :             break;
     874                 : 
     875                 :           case OFTReal:
     876              54 :             osFilter += CPLString().Printf("%.16g", psSrcField->Real );
     877              54 :             break;
     878                 : 
     879                 :           case OFTString:
     880                 :           {
     881                 :               char *pszEscaped = CPLEscapeString( psSrcField->String, 
     882                 :                                                   strlen(psSrcField->String),
     883              14 :                                                   CPLES_SQL );
     884              14 :               osFilter += "'";
     885              14 :               osFilter += pszEscaped;
     886              14 :               osFilter += "'";
     887              14 :               CPLFree( pszEscaped );
     888                 :           }
     889              14 :           break;
     890                 : 
     891                 :           default:
     892               0 :             CPLAssert( FALSE );
     893               0 :             continue;
     894                 :         }
     895                 : 
     896              80 :         OGRFeature *poJoinFeature = NULL;
     897                 : 
     898              80 :         poJoinLayer->ResetReading();
     899              80 :         if( poJoinLayer->SetAttributeFilter( osFilter.c_str() ) == OGRERR_NONE )
     900              80 :             poJoinFeature = poJoinLayer->GetNextFeature();
     901                 : 
     902              80 :         apoFeatures.push_back( poJoinFeature );
     903                 :     }
     904                 : 
     905                 : /* -------------------------------------------------------------------- */
     906                 : /*      Create destination feature.                                     */
     907                 : /* -------------------------------------------------------------------- */
     908           56824 :     poDstFeat = new OGRFeature( poDefn );
     909                 : 
     910          113648 :     poDstFeat->SetFID( poSrcFeat->GetFID() );
     911                 : 
     912           56824 :     poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
     913                 : 
     914           56824 :     poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
     915                 : 
     916                 : /* -------------------------------------------------------------------- */
     917                 : /*      Evaluate fields that are complex expressions.                   */
     918                 : /* -------------------------------------------------------------------- */
     919          397054 :     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     920                 :     {
     921          340230 :         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     922                 :         swq_expr_node *poResult;
     923                 : 
     924          340230 :         if( psColDef->field_index != -1 )
     925          340168 :             continue;
     926                 : 
     927                 :         poResult = psColDef->expr->Evaluate( OGRMultiFeatureFetcher, 
     928              62 :                                              (void *) &apoFeatures );
     929                 :         
     930              62 :         if( poResult == NULL )
     931                 :         {
     932               0 :             delete poDstFeat;
     933               0 :             return NULL;
     934                 :         }
     935                 : 
     936              62 :         if( poResult->is_null )
     937                 :         {
     938               3 :             delete poResult;
     939               3 :             continue;
     940                 :         }
     941                 : 
     942              59 :         switch( poResult->field_type )
     943                 :         {
     944                 :           case SWQ_INTEGER:
     945              25 :             poDstFeat->SetField( iField, poResult->int_value );
     946              25 :             break;
     947                 :             
     948                 :           case SWQ_FLOAT:
     949              19 :             poDstFeat->SetField( iField, poResult->float_value );
     950              19 :             break;
     951                 :             
     952                 :           default:
     953              15 :             poDstFeat->SetField( iField, poResult->string_value );
     954                 :             break;
     955                 :         }
     956                 : 
     957              59 :         delete poResult;
     958                 :     }
     959                 :     
     960                 : /* -------------------------------------------------------------------- */
     961                 : /*      Copy fields from primary record to the destination feature.     */
     962                 : /* -------------------------------------------------------------------- */
     963          397054 :     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     964                 :     {
     965          340230 :         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     966                 : 
     967          340230 :         if( psColDef->table_index != 0 )
     968             332 :             continue;
     969                 : 
     970          339921 :         if ( psColDef->field_index >= iFIDFieldIndex &&
     971                 :             psColDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
     972                 :         {
     973              23 :             switch (SpecialFieldTypes[psColDef->field_index - iFIDFieldIndex])
     974                 :             {
     975                 :               case SWQ_INTEGER:
     976               4 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
     977               4 :                 break;
     978                 :               case SWQ_FLOAT:
     979               1 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
     980               1 :                 break;
     981                 :               default:
     982              18 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
     983                 :             }
     984                 :         }
     985                 :         else
     986                 :         {
     987          339875 :             switch (psColDef->target_type)
     988                 :             {
     989                 :               case SWQ_INTEGER:
     990               0 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
     991               0 :                 break;
     992                 : 
     993                 :               case SWQ_FLOAT:
     994               0 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
     995               0 :                 break;
     996                 :               
     997                 :               case SWQ_STRING:
     998                 :               case SWQ_TIMESTAMP:
     999                 :               case SWQ_DATE:
    1000                 :               case SWQ_TIME:
    1001               0 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
    1002               0 :                 break;
    1003                 : 
    1004                 :               default:
    1005                 :                 poDstFeat->SetField( iField,
    1006          339875 :                          poSrcFeat->GetRawFieldRef( psColDef->field_index ) );
    1007                 :             }
    1008                 :         }
    1009                 :     }
    1010                 : 
    1011                 : /* -------------------------------------------------------------------- */
    1012                 : /*      Copy values from any joined tables.                             */
    1013                 : /* -------------------------------------------------------------------- */
    1014           56824 :     for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
    1015                 :     {
    1016              80 :         CPLString osFilter;
    1017                 : 
    1018              80 :         swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
    1019              80 :         OGRFeature *poJoinFeature = apoFeatures[iJoin+1];
    1020                 : 
    1021              80 :         if( poJoinFeature == NULL )
    1022              27 :             continue;
    1023                 : 
    1024                 :         // Copy over selected field values. 
    1025             374 :         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
    1026                 :         {
    1027             321 :             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
    1028                 :             
    1029             321 :             if( psColDef->table_index == psJoinInfo->secondary_table )
    1030                 :                 poDstFeat->SetField( iField,
    1031                 :                                      poJoinFeature->GetRawFieldRef( 
    1032             167 :                                          psColDef->field_index ) );
    1033                 :         }
    1034                 : 
    1035              53 :         delete poJoinFeature;
    1036                 :     }
    1037                 : 
    1038           56824 :     return poDstFeat;
    1039                 : }
    1040                 : 
    1041                 : /************************************************************************/
    1042                 : /*                           GetNextFeature()                           */
    1043                 : /************************************************************************/
    1044                 : 
    1045           47622 : OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
    1046                 : 
    1047                 : {
    1048           47622 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1049                 : 
    1050                 : /* -------------------------------------------------------------------- */
    1051                 : /*      Handle summary sets.                                            */
    1052                 : /* -------------------------------------------------------------------- */
    1053           47622 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
    1054                 :         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
    1055             153 :         return GetFeature( nNextIndexFID++ );
    1056                 : 
    1057                 : /* -------------------------------------------------------------------- */
    1058                 : /*      Handle ordered sets.                                            */
    1059                 : /* -------------------------------------------------------------------- */
    1060            9434 :     while( TRUE )
    1061                 :     {
    1062                 :         OGRFeature *poFeature;
    1063                 : 
    1064           56903 :         if( panFIDIndex != NULL )
    1065              37 :             poFeature =  GetFeature( nNextIndexFID++ );
    1066                 :         else
    1067                 :         {
    1068           56866 :             OGRFeature *poSrcFeat = poSrcLayer->GetNextFeature();
    1069                 : 
    1070           56866 :             if( poSrcFeat == NULL )
    1071              71 :                 return NULL;
    1072                 :             
    1073           56795 :             poFeature = TranslateFeature( poSrcFeat );
    1074           56795 :             delete poSrcFeat;
    1075                 :         }
    1076                 : 
    1077           56832 :         if( poFeature == NULL )
    1078              10 :             return NULL;
    1079                 : 
    1080           56822 :         if( m_poAttrQuery == NULL
    1081                 :             || m_poAttrQuery->Evaluate( poFeature ) )
    1082           47388 :             return poFeature;
    1083                 : 
    1084            9434 :         delete poFeature;
    1085                 :     }
    1086                 : 
    1087                 :     return NULL;
    1088                 : }
    1089                 : 
    1090                 : /************************************************************************/
    1091                 : /*                             GetFeature()                             */
    1092                 : /************************************************************************/
    1093                 : 
    1094             192 : OGRFeature *OGRGenSQLResultsLayer::GetFeature( long nFID )
    1095                 : 
    1096                 : {
    1097             192 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1098                 : 
    1099                 : /* -------------------------------------------------------------------- */
    1100                 : /*      Handle request for summary record.                              */
    1101                 : /* -------------------------------------------------------------------- */
    1102             192 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
    1103                 :     {
    1104              87 :         if( !PrepareSummary() || nFID != 0 || poSummaryFeature == NULL )
    1105               5 :             return NULL;
    1106                 :         else
    1107              82 :             return poSummaryFeature->Clone();
    1108                 :     }
    1109                 : 
    1110                 : /* -------------------------------------------------------------------- */
    1111                 : /*      Handle request for distinct list record.                        */
    1112                 : /* -------------------------------------------------------------------- */
    1113             105 :     if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
    1114                 :     {
    1115              66 :         if( !PrepareSummary() )
    1116               0 :             return NULL;
    1117                 : 
    1118              66 :         swq_summary *psSummary = psSelectInfo->column_summary + 0;
    1119                 : 
    1120              66 :         if( psSummary == NULL )
    1121               1 :             return NULL;
    1122                 : 
    1123              65 :         if( nFID < 0 || nFID >= psSummary->count )
    1124               6 :             return NULL;
    1125                 : 
    1126              59 :         if( psSummary->distinct_list[nFID] != NULL )
    1127              51 :             poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
    1128                 :         else
    1129               8 :             poSummaryFeature->UnsetField( 0 );
    1130              59 :         poSummaryFeature->SetFID( nFID );
    1131                 : 
    1132              59 :         return poSummaryFeature->Clone();
    1133                 :     }
    1134                 : 
    1135                 : /* -------------------------------------------------------------------- */
    1136                 : /*      Are we running in sorted mode?  If so, run the fid through      */
    1137                 : /*      the index.                                                      */
    1138                 : /* -------------------------------------------------------------------- */
    1139              39 :     if( panFIDIndex != NULL )
    1140                 :     {
    1141              37 :         if( nFID < 0 || nFID >= nIndexSize )
    1142              10 :             return NULL;
    1143                 :         else
    1144              27 :             nFID = panFIDIndex[nFID];
    1145                 :     }
    1146                 : 
    1147                 : /* -------------------------------------------------------------------- */
    1148                 : /*      Handle request for random record.                               */
    1149                 : /* -------------------------------------------------------------------- */
    1150              29 :     OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
    1151                 :     OGRFeature *poResult;
    1152                 : 
    1153              29 :     if( poSrcFeature == NULL )
    1154               0 :         return NULL;
    1155                 : 
    1156              29 :     poResult = TranslateFeature( poSrcFeature );
    1157              29 :     poResult->SetFID( nFID );
    1158                 :     
    1159              29 :     delete poSrcFeature;
    1160                 : 
    1161              29 :     return poResult;
    1162                 : }
    1163                 : 
    1164                 : /************************************************************************/
    1165                 : /*                          GetSpatialFilter()                          */
    1166                 : /************************************************************************/
    1167                 : 
    1168               2 : OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter() 
    1169                 : 
    1170                 : {
    1171               2 :     return NULL;
    1172                 : }
    1173                 : 
    1174                 : /************************************************************************/
    1175                 : /*                            GetLayerDefn()                            */
    1176                 : /************************************************************************/
    1177                 : 
    1178             160 : OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
    1179                 : 
    1180                 : {
    1181             160 :     return poDefn;
    1182                 : }
    1183                 : 
    1184                 : /************************************************************************/
    1185                 : /*                         CreateOrderByIndex()                         */
    1186                 : /*                                                                      */
    1187                 : /*      This method is responsible for creating an index providing      */
    1188                 : /*      ordered access to the features according to the supplied        */
    1189                 : /*      ORDER BY clauses.                                               */
    1190                 : /*                                                                      */
    1191                 : /*      This is accomplished by making one pass through all the         */
    1192                 : /*      eligible source features, and capturing the order by fields     */
    1193                 : /*      of all records in memory.  A quick sort is then applied to      */
    1194                 : /*      this in memory copy of the order-by fields to create the        */
    1195                 : /*      required index.                                                 */
    1196                 : /*                                                                      */
    1197                 : /*      Keeping all the key values in memory will *not* scale up to     */
    1198                 : /*      very large input datasets.                                      */
    1199                 : /************************************************************************/
    1200                 : 
    1201              10 : void OGRGenSQLResultsLayer::CreateOrderByIndex()
    1202                 : 
    1203                 : {
    1204              10 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1205                 :     OGRField *pasIndexFields;
    1206              10 :     int      i, nOrderItems = psSelectInfo->order_specs;
    1207                 :     long     *panFIDList;
    1208                 : 
    1209              10 :     if( nOrderItems == 0 )
    1210               0 :         return;
    1211                 : 
    1212              10 :     ResetReading();
    1213                 : 
    1214                 : /* -------------------------------------------------------------------- */
    1215                 : /*      Allocate set of key values, and the output index.               */
    1216                 : /* -------------------------------------------------------------------- */
    1217              10 :     nIndexSize = poSrcLayer->GetFeatureCount();
    1218                 : 
    1219                 :     pasIndexFields = (OGRField *) 
    1220              10 :         CPLCalloc(sizeof(OGRField), nOrderItems * nIndexSize);
    1221              10 :     panFIDIndex = (long *) CPLCalloc(sizeof(long),nIndexSize);
    1222              10 :     panFIDList = (long *) CPLCalloc(sizeof(long),nIndexSize);
    1223                 : 
    1224              37 :     for( i = 0; i < nIndexSize; i++ )
    1225              27 :         panFIDIndex[i] = i;
    1226                 : 
    1227                 : /* -------------------------------------------------------------------- */
    1228                 : /*      Read in all the key values.                                     */
    1229                 : /* -------------------------------------------------------------------- */
    1230                 :     OGRFeature *poSrcFeat;
    1231              10 :     int         iFeature = 0;
    1232                 : 
    1233              47 :     while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
    1234                 :     {
    1235                 :         int iKey;
    1236                 : 
    1237              54 :         for( iKey = 0; iKey < nOrderItems; iKey++ )
    1238                 :         {
    1239              27 :             swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
    1240                 :             OGRFieldDefn *poFDefn;
    1241                 :             OGRField *psSrcField, *psDstField;
    1242                 : 
    1243              27 :             psDstField = pasIndexFields + iFeature * nOrderItems + iKey;
    1244                 : 
    1245              27 :             if ( psKeyDef->field_index >= iFIDFieldIndex)
    1246                 :             {
    1247               0 :                 if ( psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
    1248                 :                 {
    1249               0 :                     switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
    1250                 :                     {
    1251                 :                       case SWQ_INTEGER:
    1252               0 :                         psDstField->Integer = poSrcFeat->GetFieldAsInteger(psKeyDef->field_index);
    1253               0 :                         break;
    1254                 : 
    1255                 :                       case SWQ_FLOAT:
    1256               0 :                         psDstField->Real = poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
    1257               0 :                         break;
    1258                 : 
    1259                 :                       default:
    1260               0 :                         psDstField->String = CPLStrdup( poSrcFeat->GetFieldAsString(psKeyDef->field_index) );
    1261                 :                         break;
    1262                 :                     }
    1263                 :                 }
    1264               0 :                 continue;
    1265                 :             }
    1266                 :             
    1267              27 :             poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
    1268              54 :                 psKeyDef->field_index );
    1269                 : 
    1270              27 :             psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
    1271                 : 
    1272              27 :             if( poFDefn->GetType() == OFTInteger 
    1273                 :                 || poFDefn->GetType() == OFTReal
    1274                 :                 || poFDefn->GetType() == OFTDate
    1275                 :                 || poFDefn->GetType() == OFTTime
    1276                 :                 || poFDefn->GetType() == OFTDateTime)
    1277              27 :                 memcpy( psDstField, psSrcField, sizeof(OGRField) );
    1278               0 :             else if( poFDefn->GetType() == OFTString )
    1279                 :             {
    1280               0 :                 if( poSrcFeat->IsFieldSet( psKeyDef->field_index ) )
    1281               0 :                     psDstField->String = CPLStrdup( psSrcField->String );
    1282                 :                 else
    1283               0 :                     memcpy( psDstField, psSrcField, sizeof(OGRField) );
    1284                 :             }
    1285                 :         }
    1286                 : 
    1287              27 :         panFIDList[iFeature] = poSrcFeat->GetFID();
    1288              27 :         delete poSrcFeat;
    1289                 : 
    1290              27 :         iFeature++;
    1291                 :     }
    1292                 : 
    1293              10 :     CPLAssert( nIndexSize == iFeature );
    1294                 : 
    1295                 : /* -------------------------------------------------------------------- */
    1296                 : /*      Quick sort the records.                                         */
    1297                 : /* -------------------------------------------------------------------- */
    1298              10 :     SortIndexSection( pasIndexFields, 0, nIndexSize );
    1299                 : 
    1300                 : /* -------------------------------------------------------------------- */
    1301                 : /*      Rework the FID map to map to real FIDs.                         */
    1302                 : /* -------------------------------------------------------------------- */
    1303              37 :     for( i = 0; i < nIndexSize; i++ )
    1304              27 :         panFIDIndex[i] = panFIDList[panFIDIndex[i]];
    1305                 : 
    1306              10 :     CPLFree( panFIDList );
    1307                 : 
    1308                 : /* -------------------------------------------------------------------- */
    1309                 : /*      Free the key field values.                                      */
    1310                 : /* -------------------------------------------------------------------- */
    1311              20 :     for( int iKey = 0; iKey < nOrderItems; iKey++ )
    1312                 :     {
    1313              10 :         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
    1314                 :         OGRFieldDefn *poFDefn;
    1315                 : 
    1316              10 :         if ( psKeyDef->field_index >= iFIDFieldIndex &&
    1317                 :             psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
    1318                 :         {
    1319                 :             /* warning: only special fields of type string should be deallocated */
    1320               0 :             if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
    1321                 :             {
    1322               0 :                 for( i = 0; i < nIndexSize; i++ )
    1323                 :                 {
    1324               0 :                     OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
    1325               0 :                     CPLFree( psField->String );
    1326                 :                 }
    1327                 :             }
    1328               0 :             continue;
    1329                 :         }
    1330                 : 
    1331              10 :         poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
    1332              20 :             psKeyDef->field_index );
    1333                 : 
    1334              10 :         if( poFDefn->GetType() == OFTString )
    1335                 :         {
    1336               0 :             for( i = 0; i < nIndexSize; i++ )
    1337                 :             {
    1338               0 :                 OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
    1339                 :                 
    1340               0 :                 if( psField->Set.nMarker1 != OGRUnsetMarker 
    1341                 :                     || psField->Set.nMarker2 != OGRUnsetMarker )
    1342               0 :                     CPLFree( psField->String );
    1343                 :             }
    1344                 :         }
    1345                 :     }
    1346                 : 
    1347              10 :     CPLFree( pasIndexFields );
    1348                 : }
    1349                 : 
    1350                 : /************************************************************************/
    1351                 : /*                          SortIndexSection()                          */
    1352                 : /*                                                                      */
    1353                 : /*      Sort the records in a section of the index.                     */
    1354                 : /************************************************************************/
    1355                 : 
    1356              44 : void OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields, 
    1357                 :                                               int nStart, int nEntries )
    1358                 : 
    1359                 : {
    1360              44 :     if( nEntries < 2 )
    1361              27 :         return;
    1362                 : 
    1363              17 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1364              17 :     int      nOrderItems = psSelectInfo->order_specs;
    1365                 : 
    1366              17 :     int nFirstGroup = nEntries / 2;
    1367              17 :     int nFirstStart = nStart;
    1368              17 :     int nSecondGroup = nEntries - nFirstGroup;
    1369              17 :     int nSecondStart = nStart + nFirstGroup;
    1370              17 :     int iMerge = 0;
    1371                 :     long *panMerged;
    1372                 : 
    1373              17 :     SortIndexSection( pasIndexFields, nFirstStart, nFirstGroup );
    1374              17 :     SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup );
    1375                 : 
    1376              17 :     panMerged = (long *) CPLMalloc( sizeof(long) * nEntries );
    1377                 :         
    1378              76 :     while( iMerge < nEntries )
    1379                 :     {
    1380                 :         int  nResult;
    1381                 : 
    1382              42 :         if( nFirstGroup == 0 )
    1383               1 :             nResult = -1;
    1384              41 :         else if( nSecondGroup == 0 )
    1385              16 :             nResult = 1;
    1386                 :         else
    1387                 :             nResult = Compare( pasIndexFields 
    1388              25 :                                + panFIDIndex[nFirstStart] * nOrderItems, 
    1389                 :                                pasIndexFields 
    1390              50 :                                + panFIDIndex[nSecondStart] * nOrderItems );
    1391                 : 
    1392              42 :         if( nResult < 0 )
    1393                 :         {
    1394              22 :             panMerged[iMerge++] = panFIDIndex[nSecondStart++];
    1395              22 :             nSecondGroup--;
    1396                 :         }
    1397                 :         else
    1398                 :         {
    1399              20 :             panMerged[iMerge++] = panFIDIndex[nFirstStart++];
    1400              20 :             nFirstGroup--;
    1401                 :         }
    1402                 :     }
    1403                 : 
    1404                 :     /* Copy the merge list back into the main index */
    1405                 : 
    1406              17 :     memcpy( panFIDIndex + nStart, panMerged, sizeof(long) * nEntries );
    1407              17 :     CPLFree( panMerged );
    1408                 : }
    1409                 : 
    1410                 : /************************************************************************/
    1411                 : /*                              Compare()                               */
    1412                 : /************************************************************************/
    1413                 : 
    1414              25 : int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
    1415                 :                                     OGRField *pasSecondTuple )
    1416                 : 
    1417                 : {
    1418              25 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1419              25 :     int  nResult = 0, iKey;
    1420                 : 
    1421              50 :     for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
    1422                 :     {
    1423              25 :         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
    1424                 :         OGRFieldDefn *poFDefn;
    1425                 : 
    1426              25 :         if( psKeyDef->field_index >= iFIDFieldIndex )
    1427               0 :             poFDefn = NULL;
    1428                 :         else
    1429              25 :             poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
    1430              50 :                 psKeyDef->field_index );
    1431                 :         
    1432              50 :         if( (pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker 
    1433               0 :              && pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker)
    1434              25 :             || (pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker 
    1435               0 :                 && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker) )
    1436               0 :             nResult = 0;
    1437              25 :         else if ( poFDefn == NULL )
    1438                 :         {
    1439               0 :             switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
    1440                 :             {
    1441                 :               case SWQ_INTEGER:
    1442               0 :                 if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
    1443               0 :                     nResult = -1;
    1444               0 :                 else if( pasFirstTuple[iKey].Integer > pasSecondTuple[iKey].Integer )
    1445               0 :                     nResult = 1;
    1446               0 :                 break;
    1447                 :               case SWQ_FLOAT:
    1448               0 :                 if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
    1449               0 :                     nResult = -1;
    1450               0 :                 else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
    1451               0 :                     nResult = 1;
    1452               0 :                 break;
    1453                 :               case SWQ_STRING:
    1454               0 :                 nResult = strcmp(pasFirstTuple[iKey].String,
    1455               0 :                                  pasSecondTuple[iKey].String);
    1456               0 :                 break;
    1457                 : 
    1458                 :               default:
    1459               0 :                 CPLAssert( FALSE );
    1460               0 :                 nResult = 0;
    1461                 :             }
    1462                 :         }
    1463              25 :         else if( poFDefn->GetType() == OFTInteger )
    1464                 :         {
    1465               0 :             if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
    1466               0 :                 nResult = -1;
    1467               0 :             else if( pasFirstTuple[iKey].Integer 
    1468               0 :                      > pasSecondTuple[iKey].Integer )
    1469               0 :                 nResult = 1;
    1470                 :         }
    1471              25 :         else if( poFDefn->GetType() == OFTString )
    1472               0 :             nResult = strcmp(pasFirstTuple[iKey].String,
    1473               0 :                              pasSecondTuple[iKey].String);
    1474              25 :         else if( poFDefn->GetType() == OFTReal )
    1475                 :         {
    1476              24 :             if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
    1477               4 :                 nResult = -1;
    1478              20 :             else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
    1479              20 :                 nResult = 1;
    1480                 :         }
    1481               1 :         else if( poFDefn->GetType() == OFTDate ||
    1482                 :                  poFDefn->GetType() == OFTTime ||
    1483                 :                  poFDefn->GetType() == OFTDateTime)
    1484                 :         {
    1485                 :             nResult = OGRCompareDate(&pasFirstTuple[iKey],
    1486               1 :                                      &pasSecondTuple[iKey]);
    1487                 :         }
    1488                 : 
    1489              25 :         if( psKeyDef->ascending_flag )
    1490              24 :             nResult *= -1;
    1491                 :     }
    1492                 : 
    1493              25 :     return nResult;
    1494                 : }
    1495                 : 
    1496                 : 
    1497                 : /************************************************************************/
    1498                 : /*                         AddFieldDefnToSet()                          */
    1499                 : /************************************************************************/
    1500                 : 
    1501            2678 : void OGRGenSQLResultsLayer::AddFieldDefnToSet(int iTable, int iColumn,
    1502                 :                                               CPLHashSet* hSet)
    1503                 : {
    1504            2678 :     if (iTable != -1 && iColumn != -1)
    1505                 :     {
    1506            1417 :         OGRLayer* poLayer = papoTableLayers[iTable];
    1507            1417 :         if (iColumn < poLayer->GetLayerDefn()->GetFieldCount())
    1508                 :         {
    1509                 :             OGRFieldDefn* poFDefn =
    1510            1401 :                 poLayer->GetLayerDefn()->GetFieldDefn(iColumn);
    1511            1401 :             CPLHashSetInsert(hSet, poFDefn);
    1512                 :         }
    1513                 :     }
    1514            2678 : }
    1515                 : 
    1516                 : /************************************************************************/
    1517                 : /*                   ExploreExprForIgnoredFields()                      */
    1518                 : /************************************************************************/
    1519                 : 
    1520            1424 : void OGRGenSQLResultsLayer::ExploreExprForIgnoredFields(swq_expr_node* expr,
    1521                 :                                                         CPLHashSet* hSet)
    1522                 : {
    1523            1424 :     if (expr->eNodeType == SNT_COLUMN)
    1524                 :     {
    1525            1230 :         AddFieldDefnToSet(expr->table_index, expr->field_index, hSet);
    1526                 :     }
    1527             194 :     else if (expr->eNodeType == SNT_OPERATION)
    1528                 :     {
    1529             273 :         for( int i = 0; i < expr->nSubExprCount; i++ )
    1530             184 :             ExploreExprForIgnoredFields(expr->papoSubExpr[i], hSet);
    1531                 :     }
    1532            1424 : }
    1533                 : 
    1534                 : /************************************************************************/
    1535                 : /*                     FindAndSetIgnoredFields()                        */
    1536                 : /************************************************************************/
    1537                 : 
    1538             183 : void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
    1539                 : {
    1540             183 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1541                 :     CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashPointer,
    1542                 :                                      CPLHashSetEqualPointer,
    1543             183 :                                      NULL);
    1544                 : 
    1545                 : /* -------------------------------------------------------------------- */
    1546                 : /*      1st phase : explore the whole select infos to determine which   */
    1547                 : /*      source fields are used                                          */
    1548                 : /* -------------------------------------------------------------------- */
    1549            1576 :     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
    1550                 :     {
    1551            1393 :         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
    1552            1393 :         AddFieldDefnToSet(psColDef->table_index, psColDef->field_index, hSet);
    1553            1393 :         if (psColDef->expr)
    1554            1188 :             ExploreExprForIgnoredFields(psColDef->expr, hSet);
    1555                 :     }
    1556                 : 
    1557             183 :     if (psSelectInfo->where_expr)
    1558              52 :         ExploreExprForIgnoredFields(psSelectInfo->where_expr, hSet);
    1559                 : 
    1560             200 :     for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
    1561                 :     {
    1562              17 :         swq_join_def *psJoinDef = psSelectInfo->join_defs + iJoin;
    1563              17 :         AddFieldDefnToSet(0, psJoinDef->primary_field, hSet);
    1564              17 :         AddFieldDefnToSet(psJoinDef->secondary_table, psJoinDef->secondary_field, hSet);
    1565                 :     }
    1566                 : 
    1567             204 :     for( int iOrder = 0; iOrder < psSelectInfo->order_specs; iOrder++ )
    1568                 :     {
    1569              21 :         swq_order_def *psOrderDef = psSelectInfo->order_defs + iOrder;
    1570              21 :         AddFieldDefnToSet(psOrderDef->table_index, psOrderDef->field_index, hSet);
    1571                 :     }
    1572                 : 
    1573                 : /* -------------------------------------------------------------------- */
    1574                 : /*      2nd phase : now, we can exclude the unused fields               */
    1575                 : /* -------------------------------------------------------------------- */
    1576             383 :     for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
    1577                 :     {
    1578             200 :         OGRLayer* poLayer = papoTableLayers[iTable];
    1579             200 :         OGRFeatureDefn *poSrcFDefn = poLayer->GetLayerDefn();
    1580                 :         int iSrcField;
    1581             200 :         char** papszIgnoredFields = NULL;
    1582            1182 :         for(iSrcField=0;iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
    1583                 :         {
    1584             982 :             OGRFieldDefn* poFDefn = poSrcFDefn->GetFieldDefn(iSrcField);
    1585             982 :             if (CPLHashSetLookup(hSet,poFDefn) == NULL)
    1586                 :             {
    1587             700 :                 papszIgnoredFields = CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
    1588                 :                 //CPLDebug("OGR", "Adding %s to the list of ignored fields of layer %s",
    1589                 :                 //         poFDefn->GetNameRef(), poLayer->GetName());
    1590                 :             }
    1591                 :         }
    1592             200 :         poLayer->SetIgnoredFields((const char**)papszIgnoredFields);
    1593             200 :         CSLDestroy(papszIgnoredFields);
    1594                 :     }
    1595                 : 
    1596             183 :     CPLHashSetDestroy(hSet);
    1597             183 : }

Generated by: LCOV version 1.7