LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogr_gensql.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 689 560 81.3 %
Date: 2012-04-28 Functions: 30 27 90.0 %

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

Generated by: LCOV version 1.7