LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogr_gensql.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 480 331 69.0 %
Date: 2010-01-09 Functions: 20 16 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr_gensql.cpp 17648 2009-09-17 15:11:18Z warmerdam $
       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 "ogr_p.h"
      31                 : #include "ogr_gensql.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogr_gensql.cpp 17648 2009-09-17 15:11:18Z warmerdam $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                       OGRGenSQLResultsLayer()                        */
      38                 : /************************************************************************/
      39                 : 
      40              49 : OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
      41                 :                                               void *pSelectInfo, 
      42              49 :                                               OGRGeometry *poSpatFilter )
      43                 : 
      44                 : {
      45              49 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
      46                 : 
      47              49 :     this->poSrcDS = poSrcDS;
      48              49 :     this->pSelectInfo = pSelectInfo;
      49              49 :     poDefn = NULL;
      50              49 :     poSummaryFeature = NULL;
      51              49 :     panFIDIndex = NULL;
      52              49 :     nIndexSize = 0;
      53              49 :     nNextIndexFID = 0;
      54              49 :     nExtraDSCount = 0;
      55              49 :     papoExtraDS = NULL;
      56                 : 
      57                 : /* -------------------------------------------------------------------- */
      58                 : /*      Identify all the layers involved in the SELECT.                 */
      59                 : /* -------------------------------------------------------------------- */
      60                 :     int iTable;
      61                 : 
      62                 :     papoTableLayers = (OGRLayer **) 
      63              49 :         CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count );
      64                 : 
      65             111 :     for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
      66                 :     {
      67              62 :         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
      68              62 :         OGRDataSource *poTableDS = poSrcDS;
      69                 : 
      70              62 :         if( psTableDef->data_source != NULL )
      71                 :         {
      72               4 :             OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
      73                 : 
      74                 :             poTableDS = 
      75               4 :                 poReg->OpenShared( psTableDef->data_source, FALSE, NULL );
      76               4 :             if( poTableDS == NULL )
      77                 :             {
      78               0 :                 if( strlen(CPLGetLastErrorMsg()) == 0 )
      79                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
      80                 :                               "Unable to open secondary datasource\n"
      81                 :                               "`%s' required by JOIN.",
      82               0 :                               psTableDef->data_source );
      83               0 :                 return;
      84                 :             }
      85                 : 
      86                 :             papoExtraDS = (OGRDataSource **)
      87               4 :                 CPLRealloc( papoExtraDS, sizeof(void*) * ++nExtraDSCount );
      88                 : 
      89               4 :             papoExtraDS[nExtraDSCount-1] = poTableDS;
      90                 :         }
      91                 : 
      92              62 :         papoTableLayers[iTable] = 
      93              62 :             poTableDS->GetLayerByName( psTableDef->table_name );
      94                 :         
      95                 :         CPLAssert( papoTableLayers[iTable] != NULL );
      96                 : 
      97              62 :         if( papoTableLayers[iTable] == NULL )
      98               0 :             return;
      99                 :     }
     100                 :     
     101              49 :     poSrcLayer = papoTableLayers[0];
     102                 : 
     103                 : /* -------------------------------------------------------------------- */
     104                 : /*      Now that we have poSrcLayer, we can install a spatial filter    */
     105                 : /*      if there is one.                                                */
     106                 : /* -------------------------------------------------------------------- */
     107              49 :     if( poSpatFilter != NULL )
     108               0 :         SetSpatialFilter( poSpatFilter );
     109                 : 
     110                 : /* -------------------------------------------------------------------- */
     111                 : /*      Prepare a feature definition based on the query.                */
     112                 : /* -------------------------------------------------------------------- */
     113              49 :     OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
     114                 : 
     115              49 :     poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias );
     116              49 :     poDefn->Reference();
     117                 : 
     118              49 :     iFIDFieldIndex = poSrcDefn->GetFieldCount();
     119                 : 
     120             184 :     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     121                 :     {
     122             135 :         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     123             135 :         OGRFieldDefn oFDefn( psColDef->field_name, OFTInteger );
     124             135 :         OGRFieldDefn *poSrcFDefn = NULL;
     125                 :         OGRFeatureDefn *poLayerDefn = 
     126             135 :             papoTableLayers[psColDef->table_index]->GetLayerDefn();
     127                 : 
     128             135 :         if( psColDef->field_index > -1 
     129                 :             && psColDef->field_index < poLayerDefn->GetFieldCount() )
     130             125 :             poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
     131                 : 
     132             135 :         if( psColDef->field_alias != NULL )
     133                 :         {
     134               0 :             oFDefn.SetName(psColDef->field_alias);
     135                 :         }
     136             135 :         else if( psColDef->col_func_name != NULL )
     137                 :         {
     138                 :             oFDefn.SetName( CPLSPrintf( "%s_%s",psColDef->col_func_name,
     139               3 :                                         psColDef->field_name) );
     140                 :         }
     141                 : 
     142             135 :         if( psColDef->col_func == SWQCF_COUNT )
     143               1 :             oFDefn.SetType( OFTInteger );
     144             134 :         else if( poSrcFDefn != NULL )
     145                 :         {
     146             125 :             oFDefn.SetType( poSrcFDefn->GetType() );
     147             125 :             oFDefn.SetWidth( poSrcFDefn->GetWidth() );
     148             125 :             oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
     149                 :         }
     150               9 :         else if ( psColDef->field_index >= iFIDFieldIndex )
     151                 :         {
     152               9 :             switch ( SpecialFieldTypes[psColDef->field_index-iFIDFieldIndex] )
     153                 :             {
     154                 :               case SWQ_INTEGER:
     155               6 :                 oFDefn.SetType( OFTInteger );
     156               6 :                 break;
     157                 :               case SWQ_FLOAT:
     158               1 :                 oFDefn.SetType( OFTReal );
     159               1 :                 break;
     160                 :               default:
     161               2 :                 oFDefn.SetType( OFTString );
     162                 :                 break;
     163                 :             }
     164                 :         }
     165                 : 
     166                 :         /* setting up the target_type */
     167             135 :         switch (psColDef->target_type)
     168                 :         {
     169                 :             case SWQ_OTHER:
     170             133 :               break;
     171                 :             case SWQ_INTEGER:
     172                 :             case SWQ_BOOLEAN:
     173               0 :               oFDefn.SetType( OFTInteger );
     174               0 :               break;
     175                 :             case SWQ_FLOAT:
     176               1 :               oFDefn.SetType( OFTReal );
     177               1 :               break;
     178                 :             case SWQ_STRING:
     179               1 :               oFDefn.SetType( OFTString );
     180               1 :               break;
     181                 :             case SWQ_TIMESTAMP:
     182               0 :               oFDefn.SetType( OFTDateTime );
     183               0 :               break;
     184                 :             case SWQ_DATE:
     185               0 :               oFDefn.SetType( OFTDate );
     186               0 :               break;
     187                 :             case SWQ_TIME:
     188               0 :               oFDefn.SetType( OFTTime );
     189                 :               break;
     190                 :         }
     191                 : 
     192             135 :         if (psColDef->field_length > 0)
     193                 :         {
     194               2 :             oFDefn.SetWidth( psColDef->field_length );
     195                 :         }
     196                 : 
     197             135 :         if (psColDef->field_precision >= 0)
     198                 :         {
     199               1 :             oFDefn.SetPrecision( psColDef->field_precision );
     200                 :         }
     201                 : 
     202             135 :         poDefn->AddFieldDefn( &oFDefn );
     203                 :     }
     204                 : 
     205              49 :     poDefn->SetGeomType( poSrcLayer->GetLayerDefn()->GetGeomType() );
     206                 : 
     207                 : /* -------------------------------------------------------------------- */
     208                 : /*      If an ORDER BY is in effect, apply it now.                      */
     209                 : /* -------------------------------------------------------------------- */
     210              49 :     if( psSelectInfo->order_specs > 0 
     211                 :         && psSelectInfo->query_mode == SWQM_RECORDSET )
     212               6 :         CreateOrderByIndex();
     213                 : 
     214              49 :     ResetReading();
     215               0 : }
     216                 : 
     217                 : /************************************************************************/
     218                 : /*                       ~OGRGenSQLResultsLayer()                       */
     219                 : /************************************************************************/
     220                 : 
     221              98 : OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
     222                 : 
     223                 : {
     224              49 :     if( m_nFeaturesRead > 0 && poDefn != NULL )
     225                 :     {
     226                 :         CPLDebug( "GenSQL", "%d features read on layer '%s'.",
     227                 :                   (int) m_nFeaturesRead, 
     228              33 :                   poDefn->GetName() );
     229                 :     }
     230                 : 
     231              49 :     ClearFilters();
     232                 : 
     233                 : /* -------------------------------------------------------------------- */
     234                 : /*      Free various datastructures.                                    */
     235                 : /* -------------------------------------------------------------------- */
     236              49 :     CPLFree( papoTableLayers );
     237              49 :     papoTableLayers = NULL;
     238                 :              
     239              49 :     if( panFIDIndex != NULL )
     240               6 :         CPLFree( panFIDIndex );
     241                 : 
     242              49 :     if( poSummaryFeature )
     243              11 :         delete poSummaryFeature;
     244                 : 
     245              49 :     if( pSelectInfo != NULL )
     246              49 :         swq_select_free( (swq_select *) pSelectInfo );
     247                 : 
     248              49 :     if( poDefn != NULL )
     249                 :     {
     250              49 :         poDefn->Release();
     251                 :     }
     252                 : 
     253                 : /* -------------------------------------------------------------------- */
     254                 : /*      Release any additional datasources being used in joins.         */
     255                 : /* -------------------------------------------------------------------- */
     256              49 :     OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
     257                 : 
     258              53 :     for( int iEDS = 0; iEDS < nExtraDSCount; iEDS++ )
     259               4 :         poReg->ReleaseDataSource( papoExtraDS[iEDS] );
     260                 : 
     261              49 :     CPLFree( papoExtraDS );
     262              98 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                            ClearFilters()                            */
     266                 : /*                                                                      */
     267                 : /*      Clear up all filters currently in place on the target layer,    */
     268                 : /*      and joined layers.  We try not to leave them installed          */
     269                 : /*      except when actively fetching features.                         */
     270                 : /************************************************************************/
     271                 : 
     272              59 : void OGRGenSQLResultsLayer::ClearFilters()
     273                 : 
     274                 : {
     275                 : /* -------------------------------------------------------------------- */
     276                 : /*      Clear any filters installed on the target layer.                */
     277                 : /* -------------------------------------------------------------------- */
     278              59 :     if( poSrcLayer != NULL )
     279                 :     {
     280              59 :         poSrcLayer->SetAttributeFilter( "" );
     281              59 :         poSrcLayer->SetSpatialFilter( NULL );
     282                 :     }
     283                 : 
     284                 : /* -------------------------------------------------------------------- */
     285                 : /*      Clear any attribute filter installed on the joined layers.      */
     286                 : /* -------------------------------------------------------------------- */
     287              59 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     288                 :     int iJoin;
     289                 : 
     290              59 :     if( psSelectInfo != NULL )
     291                 :     {
     292              72 :         for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
     293                 :         {
     294              13 :             swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
     295                 :             OGRLayer *poJoinLayer = 
     296              13 :                 papoTableLayers[psJoinInfo->secondary_table];
     297                 :             
     298              13 :             poJoinLayer->SetAttributeFilter( "" );
     299                 :         }
     300                 :     }
     301              59 : }
     302                 : 
     303                 : /************************************************************************/
     304                 : /*                            ResetReading()                            */
     305                 : /************************************************************************/
     306                 : 
     307              64 : void OGRGenSQLResultsLayer::ResetReading() 
     308                 : 
     309                 : {
     310              64 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     311                 : 
     312              64 :     if( psSelectInfo->query_mode == SWQM_RECORDSET )
     313                 :     {
     314              53 :         poSrcLayer->SetAttributeFilter( psSelectInfo->whole_where_clause );
     315                 :         
     316              53 :         poSrcLayer->SetSpatialFilter( m_poFilterGeom );
     317                 :         
     318              53 :         poSrcLayer->ResetReading();
     319                 :     }
     320                 : 
     321              64 :     nNextIndexFID = 0;
     322              64 : }
     323                 : 
     324                 : /************************************************************************/
     325                 : /*                           SetNextByIndex()                           */
     326                 : /*                                                                      */
     327                 : /*      If we already have an FID list, we can easily resposition       */
     328                 : /*      ourselves in it.                                                */
     329                 : /************************************************************************/
     330                 : 
     331               0 : OGRErr OGRGenSQLResultsLayer::SetNextByIndex( long nIndex )
     332                 : 
     333                 : {
     334               0 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     335                 : 
     336               0 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
     337                 :         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST 
     338                 :         || panFIDIndex != NULL )
     339                 :     {
     340               0 :         nNextIndexFID = nIndex;
     341               0 :         return OGRERR_NONE;
     342                 :     }
     343                 :     else
     344                 :     {
     345               0 :         return poSrcLayer->SetNextByIndex( nIndex );
     346                 :     }
     347                 : }
     348                 : 
     349                 : /************************************************************************/
     350                 : /*                             GetExtent()                              */
     351                 : /************************************************************************/
     352                 : 
     353               1 : OGRErr OGRGenSQLResultsLayer::GetExtent( OGREnvelope *psExtent, 
     354                 :                                          int bForce )
     355                 : 
     356                 : {
     357               1 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     358                 : 
     359               1 :     if( psSelectInfo->query_mode == SWQM_RECORDSET )
     360               1 :         return poSrcLayer->GetExtent( psExtent, bForce );
     361                 :     else
     362               0 :         return OGRERR_FAILURE;
     363                 : }
     364                 : 
     365                 : /************************************************************************/
     366                 : /*                           GetSpatialRef()                            */
     367                 : /************************************************************************/
     368                 : 
     369               7 : OGRSpatialReference *OGRGenSQLResultsLayer::GetSpatialRef() 
     370                 : 
     371                 : {
     372               7 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     373                 : 
     374               7 :     if( psSelectInfo->query_mode != SWQM_RECORDSET )
     375               0 :         return NULL;
     376                 :     else
     377               7 :         return poSrcLayer->GetSpatialRef();
     378                 : }
     379                 : 
     380                 : /************************************************************************/
     381                 : /*                          GetFeatureCount()                           */
     382                 : /************************************************************************/
     383                 : 
     384               9 : int OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
     385                 : 
     386                 : {
     387               9 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     388                 : 
     389               9 :     if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
     390                 :     {
     391               2 :         if( !PrepareSummary() )
     392               0 :             return 0;
     393                 : 
     394               2 :         swq_summary *psSummary = psSelectInfo->column_summary + 0;
     395                 : 
     396               2 :         if( psSummary == NULL )
     397               0 :             return 0;
     398                 : 
     399               2 :         return psSummary->count;
     400                 :     }
     401               7 :     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
     402               0 :         return 1;
     403               7 :     else if( m_poAttrQuery == NULL )
     404               7 :         return poSrcLayer->GetFeatureCount( bForce );
     405                 :     else
     406               0 :         return OGRLayer::GetFeatureCount( bForce );
     407                 : }
     408                 : 
     409                 : /************************************************************************/
     410                 : /*                           TestCapability()                           */
     411                 : /************************************************************************/
     412                 : 
     413               0 : int OGRGenSQLResultsLayer::TestCapability( const char *pszCap )
     414                 : 
     415                 : {
     416               0 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     417                 : 
     418               0 :     if( EQUAL(pszCap,OLCFastSetNextByIndex) )
     419                 :     {
     420               0 :         if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
     421                 :             || psSelectInfo->query_mode == SWQM_DISTINCT_LIST 
     422                 :             || panFIDIndex != NULL )
     423               0 :             return TRUE;
     424                 :         else 
     425               0 :             return poSrcLayer->TestCapability( pszCap );
     426                 :     }
     427                 : 
     428               0 :     if( psSelectInfo->query_mode == SWQM_RECORDSET
     429                 :         && (EQUAL(pszCap,OLCFastFeatureCount) 
     430                 :             || EQUAL(pszCap,OLCRandomRead) 
     431                 :             || EQUAL(pszCap,OLCFastGetExtent)) )
     432               0 :         return poSrcLayer->TestCapability( pszCap );
     433                 : 
     434               0 :     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
     435                 :     {
     436               0 :         if( EQUAL(pszCap,OLCFastFeatureCount) )
     437               0 :             return TRUE;
     438                 :     }
     439                 : 
     440               0 :     return FALSE;
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                           PrepareSummary()                           */
     445                 : /************************************************************************/
     446                 : 
     447              62 : int OGRGenSQLResultsLayer::PrepareSummary()
     448                 : 
     449                 : {
     450              62 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     451                 : 
     452              62 :     if( poSummaryFeature != NULL )
     453              51 :         return TRUE;
     454                 : 
     455              11 :     poSummaryFeature = new OGRFeature( poDefn );
     456              11 :     poSummaryFeature->SetFID( 0 );
     457                 : 
     458                 : /* -------------------------------------------------------------------- */
     459                 : /*      Ensure our query parameters are in place on the source          */
     460                 : /*      layer.  And initialize reading.                                 */
     461                 : /* -------------------------------------------------------------------- */
     462              11 :     poSrcLayer->SetAttributeFilter( psSelectInfo->whole_where_clause );
     463                 :     
     464              11 :     poSrcLayer->SetSpatialFilter( m_poFilterGeom );
     465                 :         
     466              11 :     poSrcLayer->ResetReading();
     467                 : 
     468                 : /* -------------------------------------------------------------------- */
     469                 : /*      We treat COUNT(*) (or COUNT of anything without distinct) as    */
     470                 : /*      a special case, and fill with GetFeatureCount().                */
     471                 : /* -------------------------------------------------------------------- */
     472                 : 
     473              23 :     if( psSelectInfo->result_columns == 1 
     474              11 :         && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
     475               1 :         && !psSelectInfo->column_defs[0].distinct_flag )
     476                 :     {
     477               1 :         poSummaryFeature->SetField( 0, poSrcLayer->GetFeatureCount( TRUE ) );
     478               1 :         return TRUE;
     479                 :     }
     480                 : 
     481                 : /* -------------------------------------------------------------------- */
     482                 : /*      Otherwise, process all source feature through the summary       */
     483                 : /*      building facilities of SWQ.                                     */
     484                 : /* -------------------------------------------------------------------- */
     485                 :     const char *pszError;
     486                 :     OGRFeature *poSrcFeature;
     487                 : 
     488             203 :     while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
     489                 :     {
     490             366 :         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     491                 :         {
     492             183 :             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     493                 : 
     494                 :             pszError = swq_select_summarize( psSelectInfo, iField, 
     495                 :                                           poSrcFeature->GetFieldAsString( 
     496             183 :                                               psColDef->field_index ) );
     497                 :             
     498             183 :             if( pszError != NULL )
     499                 :             {
     500               0 :                 delete poSummaryFeature;
     501               0 :                 poSummaryFeature = NULL;
     502                 : 
     503               0 :                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
     504               0 :                 return FALSE;
     505                 :             }
     506                 :         }
     507                 : 
     508             183 :         delete poSrcFeature;
     509                 :     }
     510                 : 
     511              10 :     pszError = swq_select_finish_summarize( psSelectInfo );
     512              10 :     if( pszError != NULL )
     513                 :     {
     514               0 :         delete poSummaryFeature;
     515               0 :         poSummaryFeature = NULL;
     516                 :         
     517               0 :         CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
     518               0 :         return FALSE;
     519                 :     }
     520                 : 
     521                 : /* -------------------------------------------------------------------- */
     522                 : /*      If we have run out of features on the source layer, clear       */
     523                 : /*      away the filters we have installed till a next run through      */
     524                 : /*      the features.                                                   */
     525                 : /* -------------------------------------------------------------------- */
     526              10 :     if( poSrcFeature == NULL )
     527              10 :         ClearFilters();
     528                 : 
     529                 : /* -------------------------------------------------------------------- */
     530                 : /*      Now apply the values to the summary feature.  If we are in      */
     531                 : /*      DISTINCT_LIST mode we don't do this step.                       */
     532                 : /* -------------------------------------------------------------------- */
     533              10 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
     534                 :         && psSelectInfo->column_summary != NULL )
     535                 :     {
     536               2 :         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     537                 :         {
     538               1 :             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     539               1 :             swq_summary *psSummary = psSelectInfo->column_summary + iField;
     540                 : 
     541               1 :             if( psColDef->col_func == SWQCF_AVG )
     542                 :                 poSummaryFeature->SetField( iField, 
     543               0 :                                         psSummary->sum / psSummary->count );
     544               1 :             else if( psColDef->col_func == SWQCF_MIN )
     545               0 :                 poSummaryFeature->SetField( iField, psSummary->min );
     546               1 :             else if( psColDef->col_func == SWQCF_MAX )
     547               1 :                 poSummaryFeature->SetField( iField, psSummary->max );
     548               0 :             else if( psColDef->col_func == SWQCF_COUNT )
     549               0 :                 poSummaryFeature->SetField( iField, psSummary->count );
     550               0 :             else if( psColDef->col_func == SWQCF_SUM )
     551               0 :                 poSummaryFeature->SetField( iField, psSummary->sum );
     552                 :         }
     553                 :     }
     554                 : 
     555              10 :     return TRUE;
     556                 : }
     557                 : 
     558                 : /************************************************************************/
     559                 : /*                          TranslateFeature()                          */
     560                 : /************************************************************************/
     561                 : 
     562             119 : OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
     563                 : 
     564                 : {
     565             119 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     566                 :     OGRFeature *poDstFeat;
     567                 : 
     568             119 :     if( poSrcFeat == NULL )
     569               0 :         return NULL;
     570                 : 
     571             119 :     m_nFeaturesRead++;
     572                 : 
     573                 : /* -------------------------------------------------------------------- */
     574                 : /*      Create destination feature.                                     */
     575                 : /* -------------------------------------------------------------------- */
     576             119 :     poDstFeat = new OGRFeature( poDefn );
     577                 : 
     578             119 :     poDstFeat->SetFID( poSrcFeat->GetFID() );
     579                 : 
     580             119 :     poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
     581                 : 
     582             119 :     poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
     583                 :     
     584                 : /* -------------------------------------------------------------------- */
     585                 : /*      Copy fields from primary record to the destination feature.     */
     586                 : /* -------------------------------------------------------------------- */
     587             567 :     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     588                 :     {
     589             448 :         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     590                 : 
     591             448 :         if( psColDef->table_index != 0 )
     592             130 :             continue;
     593                 : 
     594             337 :         if ( psColDef->field_index >= iFIDFieldIndex &&
     595                 :             psColDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
     596                 :         {
     597              19 :             switch (SpecialFieldTypes[psColDef->field_index - iFIDFieldIndex])
     598                 :             {
     599                 :               case SWQ_INTEGER:
     600               6 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
     601               6 :                 break;
     602                 :               case SWQ_FLOAT:
     603               1 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
     604               1 :                 break;
     605                 :               default:
     606              12 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
     607                 :             }
     608                 :         }
     609                 :         else
     610                 :         {
     611             299 :             switch (psColDef->target_type)
     612                 :             {
     613                 :               case SWQ_INTEGER:
     614               0 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
     615               0 :                 break;
     616                 : 
     617                 :               case SWQ_FLOAT:
     618               2 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
     619               2 :                 break;
     620                 :               
     621                 :               case SWQ_STRING:
     622                 :               case SWQ_TIMESTAMP:
     623                 :               case SWQ_DATE:
     624                 :               case SWQ_TIME:
     625               0 :                 poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
     626               0 :                 break;
     627                 : 
     628                 :               default:
     629                 :                 poDstFeat->SetField( iField,
     630             297 :                          poSrcFeat->GetRawFieldRef( psColDef->field_index ) );
     631                 :             }
     632                 :         }
     633                 :     }
     634                 : 
     635                 : /* -------------------------------------------------------------------- */
     636                 : /*      Copy values from any joined tables.                             */
     637                 : /* -------------------------------------------------------------------- */
     638                 :     int iJoin;
     639                 : 
     640             175 :     for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
     641                 :     {
     642                 :         char szFilter[512];
     643                 : 
     644              56 :         swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
     645              56 :         OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table];
     646                 :         
     647                 :         // if source key is null, we can't do join.
     648              56 :         if( !poSrcFeat->IsFieldSet( psJoinInfo->primary_field ) )
     649               0 :             continue;
     650                 : 
     651                 :         // Prepare attribute query to express fetching on the joined variable
     652                 :         sprintf( szFilter, "%s = ", 
     653              56 :                  poJoinLayer->GetLayerDefn()->GetFieldDefn( 
     654             112 :                      psJoinInfo->secondary_field )->GetNameRef() );
     655                 : 
     656                 :         OGRField *psSrcField = 
     657              56 :             poSrcFeat->GetRawFieldRef(psJoinInfo->primary_field);
     658                 : 
     659              56 :         switch( poSrcLayer->GetLayerDefn()->GetFieldDefn( 
     660                 :                     psJoinInfo->primary_field )->GetType() )
     661                 :         {
     662                 :           case OFTInteger:
     663              12 :             sprintf( szFilter+strlen(szFilter), "%d", psSrcField->Integer );
     664              12 :             break;
     665                 : 
     666                 :           case OFTReal:
     667              44 :             sprintf( szFilter+strlen(szFilter), "%.16g", psSrcField->Real );
     668              44 :             break;
     669                 : 
     670                 :           case OFTString:
     671                 :           {
     672                 :               char *pszEscaped = CPLEscapeString( psSrcField->String, 
     673                 :                                                   strlen(psSrcField->String),
     674               0 :                                                   CPLES_SQL );
     675               0 :               if( strlen(pszEscaped) + strlen(szFilter) < sizeof(szFilter)-3 )
     676                 :                   sprintf( szFilter+strlen(szFilter), "\'%s\'", 
     677               0 :                            pszEscaped );
     678                 :               else
     679                 :               {
     680               0 :                   strcat( szFilter, "' '" );
     681               0 :                   CPLDebug( "GenSQL", "Skip long join field value." );
     682                 :               }
     683               0 :               CPLFree( pszEscaped );
     684                 :           }
     685               0 :           break;
     686                 : 
     687                 :           default:
     688                 :             CPLAssert( FALSE );
     689               0 :             continue;
     690                 :         }
     691                 : 
     692              56 :         poJoinLayer->ResetReading();
     693              56 :         if( poJoinLayer->SetAttributeFilter( szFilter ) != OGRERR_NONE )
     694               0 :             continue;
     695                 : 
     696                 :         // Fetch first joined feature.
     697                 :         OGRFeature *poJoinFeature;
     698                 : 
     699              56 :         poJoinFeature = poJoinLayer->GetNextFeature();
     700                 : 
     701              56 :         if( poJoinFeature == NULL )
     702              24 :             continue;
     703                 : 
     704                 :         // Copy over selected field values. 
     705             150 :         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     706                 :         {
     707             118 :             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
     708                 :             
     709             118 :             if( psColDef->table_index == psJoinInfo->secondary_table )
     710                 :                 poDstFeat->SetField( iField,
     711                 :                                      poJoinFeature->GetRawFieldRef( 
     712              48 :                                          psColDef->field_index ) );
     713                 :         }
     714                 : 
     715              32 :         delete poJoinFeature;
     716                 :     }
     717                 : 
     718             119 :     return poDstFeat;
     719                 : }
     720                 : 
     721                 : /************************************************************************/
     722                 : /*                           GetNextFeature()                           */
     723                 : /************************************************************************/
     724                 : 
     725             210 : OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
     726                 : 
     727                 : {
     728             210 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     729                 : 
     730                 : /* -------------------------------------------------------------------- */
     731                 : /*      Handle summary sets.                                            */
     732                 : /* -------------------------------------------------------------------- */
     733             210 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
     734                 :         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
     735              60 :         return GetFeature( nNextIndexFID++ );
     736                 : 
     737                 : /* -------------------------------------------------------------------- */
     738                 : /*      Handle ordered sets.                                            */
     739                 : /* -------------------------------------------------------------------- */
     740               0 :     while( TRUE )
     741                 :     {
     742                 :         OGRFeature *poFeature;
     743                 : 
     744             150 :         if( panFIDIndex != NULL )
     745              25 :             poFeature =  GetFeature( nNextIndexFID++ );
     746                 :         else
     747                 :         {
     748             125 :             OGRFeature *poSrcFeat = poSrcLayer->GetNextFeature();
     749                 : 
     750             125 :             if( poSrcFeat == NULL )
     751              25 :                 return NULL;
     752                 :             
     753             100 :             poFeature = TranslateFeature( poSrcFeat );
     754             100 :             delete poSrcFeat;
     755                 :         }
     756                 : 
     757             125 :         if( poFeature == NULL )
     758               6 :             return NULL;
     759                 : 
     760             119 :         if( m_poAttrQuery == NULL
     761                 :             || m_poAttrQuery->Evaluate( poFeature ) )
     762             119 :             return poFeature;
     763                 : 
     764               0 :         delete poFeature;
     765                 :     }
     766                 : 
     767                 :     return NULL;
     768                 : }
     769                 : 
     770                 : /************************************************************************/
     771                 : /*                             GetFeature()                             */
     772                 : /************************************************************************/
     773                 : 
     774              85 : OGRFeature *OGRGenSQLResultsLayer::GetFeature( long nFID )
     775                 : 
     776                 : {
     777              85 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     778                 : 
     779                 : /* -------------------------------------------------------------------- */
     780                 : /*      Handle request for summary record.                              */
     781                 : /* -------------------------------------------------------------------- */
     782              85 :     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
     783                 :     {
     784               6 :         if( !PrepareSummary() || nFID != 0 || poSummaryFeature == NULL )
     785               3 :             return NULL;
     786                 :         else
     787               3 :             return poSummaryFeature->Clone();
     788                 :     }
     789                 : 
     790                 : /* -------------------------------------------------------------------- */
     791                 : /*      Handle request for distinct list record.                        */
     792                 : /* -------------------------------------------------------------------- */
     793              79 :     if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
     794                 :     {
     795              54 :         if( !PrepareSummary() )
     796               0 :             return NULL;
     797                 : 
     798              54 :         swq_summary *psSummary = psSelectInfo->column_summary + 0;
     799                 : 
     800              54 :         if( psSummary == NULL )
     801               1 :             return NULL;
     802                 : 
     803              53 :         if( nFID < 0 || nFID >= psSummary->count )
     804               6 :             return NULL;
     805                 : 
     806              47 :         poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
     807              47 :         poSummaryFeature->SetFID( nFID );
     808                 : 
     809              47 :         return poSummaryFeature->Clone();
     810                 :     }
     811                 : 
     812                 : /* -------------------------------------------------------------------- */
     813                 : /*      Are we running in sorted mode?  If so, run the fid through      */
     814                 : /*      the index.                                                      */
     815                 : /* -------------------------------------------------------------------- */
     816              25 :     if( panFIDIndex != NULL )
     817                 :     {
     818              25 :         if( nFID < 0 || nFID >= nIndexSize )
     819               6 :             return NULL;
     820                 :         else
     821              19 :             nFID = panFIDIndex[nFID];
     822                 :     }
     823                 : 
     824                 : /* -------------------------------------------------------------------- */
     825                 : /*      Handle request for random record.                               */
     826                 : /* -------------------------------------------------------------------- */
     827              19 :     OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
     828                 :     OGRFeature *poResult;
     829                 : 
     830              19 :     if( poSrcFeature == NULL )
     831               0 :         return NULL;
     832                 : 
     833              19 :     poResult = TranslateFeature( poSrcFeature );
     834              19 :     poResult->SetFID( nFID );
     835                 :     
     836              19 :     delete poSrcFeature;
     837                 : 
     838              19 :     return poResult;
     839                 : }
     840                 : 
     841                 : /************************************************************************/
     842                 : /*                          GetSpatialFilter()                          */
     843                 : /************************************************************************/
     844                 : 
     845               0 : OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter() 
     846                 : 
     847                 : {
     848               0 :     return NULL;
     849                 : }
     850                 : 
     851                 : /************************************************************************/
     852                 : /*                            GetLayerDefn()                            */
     853                 : /************************************************************************/
     854                 : 
     855             102 : OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
     856                 : 
     857                 : {
     858             102 :     return poDefn;
     859                 : }
     860                 : 
     861                 : /************************************************************************/
     862                 : /*                         CreateOrderByIndex()                         */
     863                 : /*                                                                      */
     864                 : /*      This method is responsible for creating an index providing      */
     865                 : /*      ordered access to the features according to the supplied        */
     866                 : /*      ORDER BY clauses.                                               */
     867                 : /*                                                                      */
     868                 : /*      This is accomplished by making one pass through all the         */
     869                 : /*      eligible source features, and capturing the order by fields     */
     870                 : /*      of all records in memory.  A quick sort is then applied to      */
     871                 : /*      this in memory copy of the order-by fields to create the        */
     872                 : /*      required index.                                                 */
     873                 : /*                                                                      */
     874                 : /*      Keeping all the key values in memory will *not* scale up to     */
     875                 : /*      very large input datasets.                                      */
     876                 : /************************************************************************/
     877                 : 
     878               6 : void OGRGenSQLResultsLayer::CreateOrderByIndex()
     879                 : 
     880                 : {
     881               6 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     882                 :     OGRField *pasIndexFields;
     883               6 :     int      i, nOrderItems = psSelectInfo->order_specs;
     884                 :     long     *panFIDList;
     885                 : 
     886               6 :     if( nOrderItems == 0 )
     887               0 :         return;
     888                 : 
     889               6 :     ResetReading();
     890                 : 
     891                 : /* -------------------------------------------------------------------- */
     892                 : /*      Allocate set of key values, and the output index.               */
     893                 : /* -------------------------------------------------------------------- */
     894               6 :     nIndexSize = poSrcLayer->GetFeatureCount();
     895                 : 
     896                 :     pasIndexFields = (OGRField *) 
     897               6 :         CPLCalloc(sizeof(OGRField), nOrderItems * nIndexSize);
     898               6 :     panFIDIndex = (long *) CPLCalloc(sizeof(long),nIndexSize);
     899               6 :     panFIDList = (long *) CPLCalloc(sizeof(long),nIndexSize);
     900                 : 
     901              25 :     for( i = 0; i < nIndexSize; i++ )
     902              19 :         panFIDIndex[i] = i;
     903                 : 
     904                 : /* -------------------------------------------------------------------- */
     905                 : /*      Read in all the key values.                                     */
     906                 : /* -------------------------------------------------------------------- */
     907                 :     OGRFeature *poSrcFeat;
     908               6 :     int         iFeature = 0;
     909                 : 
     910              31 :     while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
     911                 :     {
     912                 :         int iKey;
     913                 : 
     914              38 :         for( iKey = 0; iKey < nOrderItems; iKey++ )
     915                 :         {
     916              19 :             swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
     917                 :             OGRFieldDefn *poFDefn;
     918                 :             OGRField *psSrcField, *psDstField;
     919                 : 
     920              19 :             psDstField = pasIndexFields + iFeature * nOrderItems + iKey;
     921                 : 
     922              19 :             if ( psKeyDef->field_index >= iFIDFieldIndex)
     923                 :             {
     924               0 :                 if ( psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
     925                 :                 {
     926               0 :                     switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
     927                 :                     {
     928                 :                       case SWQ_INTEGER:
     929               0 :                         psDstField->Integer = poSrcFeat->GetFieldAsInteger(psKeyDef->field_index);
     930               0 :                         break;
     931                 : 
     932                 :                       case SWQ_FLOAT:
     933               0 :                         psDstField->Real = poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
     934               0 :                         break;
     935                 : 
     936                 :                       default:
     937               0 :                         psDstField->String = CPLStrdup( poSrcFeat->GetFieldAsString(psKeyDef->field_index) );
     938                 :                         break;
     939                 :                     }
     940                 :                 }
     941               0 :                 continue;
     942                 :             }
     943                 :             
     944              19 :             poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
     945              38 :                 psKeyDef->field_index );
     946                 : 
     947              19 :             psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
     948                 : 
     949              19 :             if( poFDefn->GetType() == OFTInteger 
     950                 :                 || poFDefn->GetType() == OFTReal
     951                 :                 || poFDefn->GetType() == OFTDate
     952                 :                 || poFDefn->GetType() == OFTTime
     953                 :                 || poFDefn->GetType() == OFTDateTime)
     954              19 :                 memcpy( psDstField, psSrcField, sizeof(OGRField) );
     955               0 :             else if( poFDefn->GetType() == OFTString )
     956                 :             {
     957               0 :                 if( poSrcFeat->IsFieldSet( psKeyDef->field_index ) )
     958               0 :                     psDstField->String = CPLStrdup( psSrcField->String );
     959                 :                 else
     960               0 :                     memcpy( psDstField, psSrcField, sizeof(OGRField) );
     961                 :             }
     962                 :         }
     963                 : 
     964              19 :         panFIDList[iFeature] = poSrcFeat->GetFID();
     965              19 :         delete poSrcFeat;
     966                 : 
     967              19 :         iFeature++;
     968                 :     }
     969                 : 
     970                 :     CPLAssert( nIndexSize == iFeature );
     971                 : 
     972                 : /* -------------------------------------------------------------------- */
     973                 : /*      Quick sort the records.                                         */
     974                 : /* -------------------------------------------------------------------- */
     975               6 :     SortIndexSection( pasIndexFields, 0, nIndexSize );
     976                 : 
     977                 : /* -------------------------------------------------------------------- */
     978                 : /*      Rework the FID map to map to real FIDs.                         */
     979                 : /* -------------------------------------------------------------------- */
     980              25 :     for( i = 0; i < nIndexSize; i++ )
     981              19 :         panFIDIndex[i] = panFIDList[panFIDIndex[i]];
     982                 : 
     983               6 :     CPLFree( panFIDList );
     984                 : 
     985                 : /* -------------------------------------------------------------------- */
     986                 : /*      Free the key field values.                                      */
     987                 : /* -------------------------------------------------------------------- */
     988              12 :     for( int iKey = 0; iKey < nOrderItems; iKey++ )
     989                 :     {
     990               6 :         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
     991                 :         OGRFieldDefn *poFDefn;
     992                 : 
     993               6 :         if ( psKeyDef->field_index >= iFIDFieldIndex &&
     994                 :             psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
     995                 :         {
     996                 :             /* warning: only special fields of type string should be deallocated */
     997               0 :             if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
     998                 :             {
     999               0 :                 for( i = 0; i < nIndexSize; i++ )
    1000                 :                 {
    1001               0 :                     OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
    1002               0 :                     CPLFree( psField->String );
    1003                 :                 }
    1004                 :             }
    1005               0 :             continue;
    1006                 :         }
    1007                 : 
    1008               6 :         poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
    1009              12 :             psKeyDef->field_index );
    1010                 : 
    1011               6 :         if( poFDefn->GetType() == OFTString )
    1012                 :         {
    1013               0 :             for( i = 0; i < nIndexSize; i++ )
    1014                 :             {
    1015               0 :                 OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
    1016                 :                 
    1017               0 :                 if( psField->Set.nMarker1 != OGRUnsetMarker 
    1018                 :                     || psField->Set.nMarker2 != OGRUnsetMarker )
    1019               0 :                     CPLFree( psField->String );
    1020                 :             }
    1021                 :         }
    1022                 :     }
    1023                 : 
    1024               6 :     CPLFree( pasIndexFields );
    1025                 : }
    1026                 : 
    1027                 : /************************************************************************/
    1028                 : /*                          SortIndexSection()                          */
    1029                 : /*                                                                      */
    1030                 : /*      Sort the records in a section of the index.                     */
    1031                 : /************************************************************************/
    1032                 : 
    1033              32 : void OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields, 
    1034                 :                                               int nStart, int nEntries )
    1035                 : 
    1036                 : {
    1037              32 :     if( nEntries < 2 )
    1038              19 :         return;
    1039                 : 
    1040              13 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1041              13 :     int      nOrderItems = psSelectInfo->order_specs;
    1042                 : 
    1043              13 :     int nFirstGroup = nEntries / 2;
    1044              13 :     int nFirstStart = nStart;
    1045              13 :     int nSecondGroup = nEntries - nFirstGroup;
    1046              13 :     int nSecondStart = nStart + nFirstGroup;
    1047              13 :     int iMerge = 0;
    1048                 :     long *panMerged;
    1049                 : 
    1050              13 :     SortIndexSection( pasIndexFields, nFirstStart, nFirstGroup );
    1051              13 :     SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup );
    1052                 : 
    1053              13 :     panMerged = (long *) CPLMalloc( sizeof(long) * nEntries );
    1054                 :         
    1055              59 :     while( iMerge < nEntries )
    1056                 :     {
    1057                 :         int  nResult;
    1058                 : 
    1059              33 :         if( nFirstGroup == 0 )
    1060               1 :             nResult = -1;
    1061              32 :         else if( nSecondGroup == 0 )
    1062              12 :             nResult = 1;
    1063                 :         else
    1064                 :             nResult = Compare( pasIndexFields 
    1065              20 :                                + panFIDIndex[nFirstStart] * nOrderItems, 
    1066                 :                                pasIndexFields 
    1067              40 :                                + panFIDIndex[nSecondStart] * nOrderItems );
    1068                 : 
    1069              33 :         if( nResult < 0 )
    1070                 :         {
    1071              17 :             panMerged[iMerge++] = panFIDIndex[nSecondStart++];
    1072              17 :             nSecondGroup--;
    1073                 :         }
    1074                 :         else
    1075                 :         {
    1076              16 :             panMerged[iMerge++] = panFIDIndex[nFirstStart++];
    1077              16 :             nFirstGroup--;
    1078                 :         }
    1079                 :     }
    1080                 : 
    1081                 :     /* Copy the merge list back into the main index */
    1082                 : 
    1083              13 :     memcpy( panFIDIndex + nStart, panMerged, sizeof(long) * nEntries );
    1084              13 :     CPLFree( panMerged );
    1085                 : }
    1086                 : 
    1087                 : 
    1088                 : /************************************************************************/
    1089                 : /*                    OGRGenSQLCompareDate()                            */
    1090                 : /************************************************************************/
    1091                 : 
    1092               0 : static int OGRGenSQLCompareDate(   OGRField *psFirstTuple,
    1093                 :                                    OGRField *psSecondTuple )
    1094                 : {
    1095                 :     /* FIXME? : We ignore TZFlag */
    1096                 : 
    1097               0 :     if (psFirstTuple->Date.Year < psSecondTuple->Date.Year)
    1098               0 :         return -1;
    1099               0 :     else if (psFirstTuple->Date.Year > psSecondTuple->Date.Year)
    1100               0 :         return 1;
    1101                 : 
    1102               0 :     if (psFirstTuple->Date.Month < psSecondTuple->Date.Month)
    1103               0 :         return -1;
    1104               0 :     else if (psFirstTuple->Date.Month > psSecondTuple->Date.Month)
    1105               0 :         return 1;
    1106                 : 
    1107               0 :     if (psFirstTuple->Date.Day < psSecondTuple->Date.Day)
    1108               0 :         return -1;
    1109               0 :     else if (psFirstTuple->Date.Day > psSecondTuple->Date.Day)
    1110               0 :         return 1;
    1111                 : 
    1112               0 :     if (psFirstTuple->Date.Hour < psSecondTuple->Date.Hour)
    1113               0 :         return -1;
    1114               0 :     else if (psFirstTuple->Date.Hour > psSecondTuple->Date.Hour)
    1115               0 :         return 1;
    1116                 : 
    1117               0 :     if (psFirstTuple->Date.Minute < psSecondTuple->Date.Minute)
    1118               0 :         return -1;
    1119               0 :     else if (psFirstTuple->Date.Minute > psSecondTuple->Date.Minute)
    1120               0 :         return 1;
    1121                 : 
    1122               0 :     if (psFirstTuple->Date.Second < psSecondTuple->Date.Second)
    1123               0 :         return -1;
    1124               0 :     else if (psFirstTuple->Date.Second > psSecondTuple->Date.Second)
    1125               0 :         return 1;
    1126                 : 
    1127               0 :     return 0;
    1128                 : }
    1129                 : 
    1130                 : /************************************************************************/
    1131                 : /*                              Compare()                               */
    1132                 : /************************************************************************/
    1133                 : 
    1134              20 : int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
    1135                 :                                     OGRField *pasSecondTuple )
    1136                 : 
    1137                 : {
    1138              20 :     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
    1139              20 :     int  nResult = 0, iKey;
    1140                 : 
    1141              40 :     for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
    1142                 :     {
    1143              20 :         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
    1144                 :         OGRFieldDefn *poFDefn;
    1145                 : 
    1146              20 :         if( psKeyDef->field_index >= iFIDFieldIndex )
    1147               0 :             poFDefn = NULL;
    1148                 :         else
    1149              20 :             poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
    1150              40 :                 psKeyDef->field_index );
    1151                 :         
    1152              40 :         if( (pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker 
    1153               0 :              && pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker)
    1154              20 :             || (pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker 
    1155               0 :                 && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker) )
    1156               0 :             nResult = 0;
    1157              20 :         else if ( poFDefn == NULL )
    1158                 :         {
    1159               0 :             switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
    1160                 :             {
    1161                 :               case SWQ_INTEGER:
    1162               0 :                 if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
    1163               0 :                     nResult = -1;
    1164               0 :                 else if( pasFirstTuple[iKey].Integer > pasSecondTuple[iKey].Integer )
    1165               0 :                     nResult = 1;
    1166               0 :                 break;
    1167                 :               case SWQ_FLOAT:
    1168               0 :                 if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
    1169               0 :                     nResult = -1;
    1170               0 :                 else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
    1171               0 :                     nResult = 1;
    1172               0 :                 break;
    1173                 :               case SWQ_STRING:
    1174               0 :                 nResult = strcmp(pasFirstTuple[iKey].String,
    1175               0 :                                  pasSecondTuple[iKey].String);
    1176               0 :                 break;
    1177                 : 
    1178                 :               default:
    1179                 :                 CPLAssert( FALSE );
    1180               0 :                 nResult = 0;
    1181                 :             }
    1182                 :         }
    1183              20 :         else if( poFDefn->GetType() == OFTInteger )
    1184                 :         {
    1185               0 :             if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
    1186               0 :                 nResult = -1;
    1187               0 :             else if( pasFirstTuple[iKey].Integer 
    1188               0 :                      > pasSecondTuple[iKey].Integer )
    1189               0 :                 nResult = 1;
    1190                 :         }
    1191              20 :         else if( poFDefn->GetType() == OFTString )
    1192               0 :             nResult = strcmp(pasFirstTuple[iKey].String,
    1193               0 :                              pasSecondTuple[iKey].String);
    1194              20 :         else if( poFDefn->GetType() == OFTReal )
    1195                 :         {
    1196              20 :             if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
    1197               4 :                 nResult = -1;
    1198              16 :             else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
    1199              16 :                 nResult = 1;
    1200                 :         }
    1201               0 :         else if( poFDefn->GetType() == OFTDate ||
    1202                 :                  poFDefn->GetType() == OFTTime ||
    1203                 :                  poFDefn->GetType() == OFTDateTime)
    1204                 :         {
    1205                 :             nResult = OGRGenSQLCompareDate(&pasFirstTuple[iKey],
    1206               0 :                                            &pasSecondTuple[iKey]);
    1207                 :         }
    1208                 : 
    1209              20 :         if( psKeyDef->ascending_flag )
    1210              20 :             nResult *= -1;
    1211                 :     }
    1212                 : 
    1213              20 :     return nResult;
    1214                 : }

Generated by: LCOV version 1.7