1 /******************************************************************************
2  *
3  * Project:  OpenGIS Simple Features Reference Implementation
4  * Purpose:  Implements OGRGenSQLResultsLayer.
5  * Author:   Frank Warmerdam, warmerdam@pobox.com
6  *
7  ******************************************************************************
8  * Copyright (c) 2002, Frank Warmerdam
9  * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
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_swq.h"
31 #include "ogr_p.h"
32 #include "ogr_gensql.h"
33 #include "cpl_string.h"
34 #include "ogr_api.h"
35 #include "cpl_time.h"
36 #include <algorithm>
37 #include <vector>
38 
39 //! @cond Doxygen_Suppress
40 
41 CPL_CVSID("$Id: ogr_gensql.cpp 9cb485b2fb43258aa1fd374c1983564064f32c5f 2020-11-30 20:41:37 +0100 Even Rouault $")
42 
43 class OGRGenSQLGeomFieldDefn final: public OGRGeomFieldDefn
44 {
45     public:
OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn * poGeomFieldDefn)46         explicit OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn* poGeomFieldDefn) :
47             OGRGeomFieldDefn(poGeomFieldDefn->GetNameRef(),
48                              poGeomFieldDefn->GetType()), bForceGeomType(FALSE)
49         {
50             SetSpatialRef(poGeomFieldDefn->GetSpatialRef());
51         }
52 
53         int bForceGeomType;
54 };
55 
56 /************************************************************************/
57 /*               OGRGenSQLResultsLayerHasSpecialField()                 */
58 /************************************************************************/
59 
60 static
OGRGenSQLResultsLayerHasSpecialField(swq_expr_node * expr,int nMinIndexForSpecialField)61 int OGRGenSQLResultsLayerHasSpecialField(swq_expr_node* expr,
62                                          int nMinIndexForSpecialField)
63 {
64     if (expr->eNodeType == SNT_COLUMN)
65     {
66         if (expr->table_index == 0)
67         {
68             return expr->field_index >= nMinIndexForSpecialField &&
69                    expr->field_index < nMinIndexForSpecialField + SPECIAL_FIELD_COUNT;
70         }
71     }
72     else if (expr->eNodeType == SNT_OPERATION)
73     {
74         for( int i = 0; i < expr->nSubExprCount; i++ )
75         {
76             if (OGRGenSQLResultsLayerHasSpecialField(expr->papoSubExpr[i],
77                                                      nMinIndexForSpecialField))
78                 return TRUE;
79         }
80     }
81     return FALSE;
82 }
83 
84 /************************************************************************/
85 /*                       OGRGenSQLResultsLayer()                        */
86 /************************************************************************/
87 
OGRGenSQLResultsLayer(GDALDataset * poSrcDSIn,void * pSelectInfoIn,OGRGeometry * poSpatFilter,const char * pszWHEREIn,const char * pszDialect)88 OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDSIn,
89                                               void *pSelectInfoIn,
90                                               OGRGeometry *poSpatFilter,
91                                               const char *pszWHEREIn,
92                                               const char *pszDialect ) :
93     poSrcDS(poSrcDSIn),
94     poSrcLayer(nullptr),
95     pSelectInfo(pSelectInfoIn),
96     pszWHERE(nullptr),
97     papoTableLayers(nullptr),
98     poDefn(nullptr),
99     panGeomFieldToSrcGeomField(nullptr),
100     nIndexSize(0),
101     panFIDIndex(nullptr),
102     bOrderByValid(FALSE),
103     nNextIndexFID(0),
104     poSummaryFeature(nullptr),
105     iFIDFieldIndex(),
106     nExtraDSCount(0),
107     papoExtraDS(nullptr),
108     nIteratedFeatures(-1),
109     m_oDistinctList{}
110 {
111     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfoIn);
112 
113 /* -------------------------------------------------------------------- */
114 /*      Identify all the layers involved in the SELECT.                 */
115 /* -------------------------------------------------------------------- */
116     papoTableLayers = static_cast<OGRLayer **>(
117         CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count ));
118 
119     for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
120     {
121         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
122         GDALDataset *poTableDS = poSrcDS;
123 
124         if( psTableDef->data_source != nullptr )
125         {
126             poTableDS = GDALDataset::Open( psTableDef->data_source,
127                             GDAL_OF_VECTOR | GDAL_OF_SHARED );
128             if( poTableDS == nullptr )
129             {
130                 if( strlen(CPLGetLastErrorMsg()) == 0 )
131                     CPLError( CE_Failure, CPLE_AppDefined,
132                               "Unable to open secondary datasource\n"
133                               "`%s' required by JOIN.",
134                               psTableDef->data_source );
135                 return;
136             }
137 
138             papoExtraDS = static_cast<GDALDataset **>(
139                 CPLRealloc( papoExtraDS, sizeof(void*) * ++nExtraDSCount ));
140 
141             papoExtraDS[nExtraDSCount-1] = poTableDS;
142         }
143 
144         papoTableLayers[iTable] =
145             poTableDS->GetLayerByName( psTableDef->table_name );
146 
147         CPLAssert( papoTableLayers[iTable] != nullptr );
148 
149         if( papoTableLayers[iTable] == nullptr )
150             return;
151     }
152 
153     poSrcLayer = papoTableLayers[0];
154     SetMetadata( poSrcLayer->GetMetadata( "NATIVE_DATA" ), "NATIVE_DATA" );
155 
156 /* -------------------------------------------------------------------- */
157 /*      If the user has explicitly requested a OGRSQL dialect, then    */
158 /*      we should avoid to forward the where clause to the source layer */
159 /*      when there is a risk it cannot understand it (#4022)            */
160 /* -------------------------------------------------------------------- */
161     int bForwardWhereToSourceLayer = TRUE;
162     if( pszWHEREIn )
163     {
164         if( psSelectInfo->where_expr && pszDialect != nullptr &&
165             EQUAL(pszDialect, "OGRSQL") )
166         {
167             int nMinIndexForSpecialField = poSrcLayer->GetLayerDefn()->GetFieldCount();
168             bForwardWhereToSourceLayer = !OGRGenSQLResultsLayerHasSpecialField
169                             (psSelectInfo->where_expr, nMinIndexForSpecialField);
170         }
171         if (bForwardWhereToSourceLayer)
172             pszWHERE = CPLStrdup(pszWHEREIn);
173         else
174             pszWHERE = nullptr;
175     }
176     else
177         pszWHERE = nullptr;
178 
179 /* -------------------------------------------------------------------- */
180 /*      Prepare a feature definition based on the query.                */
181 /* -------------------------------------------------------------------- */
182     OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
183 
184     poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias );
185     SetDescription( poDefn->GetName() );
186     poDefn->SetGeomType(wkbNone);
187     poDefn->Reference();
188 
189     iFIDFieldIndex = poSrcDefn->GetFieldCount();
190 
191     /* + 1 since we can add an implicit geometry field */
192     panGeomFieldToSrcGeomField = static_cast<int *>(
193         CPLMalloc(sizeof(int) * (1 + psSelectInfo->result_columns)));
194 
195     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
196     {
197         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
198         OGRFieldDefn oFDefn( "", OFTInteger );
199         OGRGeomFieldDefn oGFDefn( "", wkbUnknown );
200         OGRFieldDefn *poSrcFDefn = nullptr;
201         OGRGeomFieldDefn *poSrcGFDefn = nullptr;
202         int bIsGeometry = FALSE;
203         OGRFeatureDefn *poLayerDefn = nullptr;
204         int iSrcGeomField = -1;
205 
206         if( psColDef->table_index != -1 )
207             poLayerDefn =
208                 papoTableLayers[psColDef->table_index]->GetLayerDefn();
209 
210         if( psColDef->field_index > -1
211             && poLayerDefn != nullptr
212             && psColDef->field_index < poLayerDefn->GetFieldCount() )
213         {
214             poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
215         }
216 
217         if( poLayerDefn != nullptr &&
218             IS_GEOM_FIELD_INDEX(poLayerDefn, psColDef->field_index) )
219         {
220             bIsGeometry = TRUE;
221             iSrcGeomField =
222                 ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(poLayerDefn, psColDef->field_index);
223             poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
224         }
225 
226         if( psColDef->target_type == SWQ_GEOMETRY )
227             bIsGeometry = TRUE;
228 
229         if( psColDef->col_func == SWQCF_COUNT )
230             bIsGeometry = FALSE;
231 
232         if( strlen(psColDef->field_name) == 0 && !bIsGeometry )
233         {
234             CPLFree( psColDef->field_name );
235             psColDef->field_name = static_cast<char *>(CPLMalloc(40));
236             snprintf( psColDef->field_name, 40, "FIELD_%d", poDefn->GetFieldCount()+1 );
237         }
238 
239         if( psColDef->field_alias != nullptr )
240         {
241             if( bIsGeometry )
242                 oGFDefn.SetName(psColDef->field_alias);
243             else
244                 oFDefn.SetName(psColDef->field_alias);
245         }
246         else if( psColDef->col_func != SWQCF_NONE )
247         {
248             const swq_operation *op = swq_op_registrar::GetOperator(
249                 static_cast<swq_op>(psColDef->col_func) );
250 
251             oFDefn.SetName( CPLSPrintf( "%s_%s",
252                                         op->pszName,
253                                         psColDef->field_name ) );
254         }
255         else
256         {
257             CPLString osName;
258             if( psColDef->table_name[0] )
259             {
260                 osName = psColDef->table_name;
261                 osName += ".";
262             }
263             osName += psColDef->field_name;
264 
265             if( bIsGeometry )
266                 oGFDefn.SetName(osName);
267             else
268                 oFDefn.SetName(osName);
269         }
270 
271         if( psColDef->col_func == SWQCF_COUNT )
272             oFDefn.SetType( OFTInteger64 );
273         else if( poSrcFDefn != nullptr )
274         {
275             if( psColDef->col_func != SWQCF_AVG ||
276                 psColDef->field_type == SWQ_DATE ||
277                 psColDef->field_type == SWQ_TIME ||
278                 psColDef->field_type == SWQ_TIMESTAMP )
279             {
280                 oFDefn.SetType( poSrcFDefn->GetType() );
281                 if( psColDef->col_func == SWQCF_NONE ||
282                     psColDef->col_func == SWQCF_MIN ||
283                     psColDef->col_func == SWQCF_MAX )
284                 {
285                     oFDefn.SetSubType( poSrcFDefn->GetSubType() );
286                 }
287             }
288             else
289                 oFDefn.SetType( OFTReal );
290             if( psColDef->col_func != SWQCF_AVG &&
291                 psColDef->col_func != SWQCF_SUM )
292             {
293                 oFDefn.SetWidth( poSrcFDefn->GetWidth() );
294                 oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
295             }
296         }
297         else if( poSrcGFDefn != nullptr )
298         {
299             oGFDefn.SetType( poSrcGFDefn->GetType() );
300             oGFDefn.SetSpatialRef( poSrcGFDefn->GetSpatialRef() );
301         }
302         else if ( psColDef->field_index >= iFIDFieldIndex )
303         {
304             switch ( SpecialFieldTypes[psColDef->field_index-iFIDFieldIndex] )
305             {
306               case SWQ_INTEGER:
307                 oFDefn.SetType( OFTInteger );
308                 break;
309               case SWQ_INTEGER64:
310                 oFDefn.SetType( OFTInteger64 );
311                 break;
312               case SWQ_FLOAT:
313                 oFDefn.SetType( OFTReal );
314                 break;
315               default:
316                 oFDefn.SetType( OFTString );
317                 break;
318             }
319             if( psColDef->field_index-iFIDFieldIndex == SPF_FID &&
320                 poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
321                 EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") )
322             {
323                 oFDefn.SetType( OFTInteger64 );
324             }
325         }
326         else
327         {
328             switch( psColDef->field_type )
329             {
330               case SWQ_INTEGER:
331                 oFDefn.SetType( OFTInteger );
332                 break;
333 
334               case SWQ_INTEGER64:
335                 oFDefn.SetType( OFTInteger64 );
336                 break;
337 
338               case SWQ_BOOLEAN:
339                 oFDefn.SetType( OFTInteger );
340                 oFDefn.SetSubType( OFSTBoolean );
341                 break;
342 
343               case SWQ_FLOAT:
344                 oFDefn.SetType( OFTReal );
345                 break;
346 
347               default:
348                 oFDefn.SetType( OFTString );
349                 break;
350             }
351         }
352 
353         /* setting up the target_type */
354         switch (psColDef->target_type)
355         {
356           case SWQ_OTHER:
357             break;
358           case SWQ_INTEGER:
359             oFDefn.SetType( OFTInteger );
360             break;
361           case SWQ_INTEGER64:
362             oFDefn.SetType( OFTInteger64 );
363             break;
364           case SWQ_BOOLEAN:
365             oFDefn.SetType( OFTInteger );
366             oFDefn.SetSubType( OFSTBoolean );
367             break;
368           case SWQ_FLOAT:
369             oFDefn.SetType( OFTReal );
370             break;
371           case SWQ_STRING:
372             oFDefn.SetType( OFTString );
373             break;
374           case SWQ_TIMESTAMP:
375             oFDefn.SetType( OFTDateTime );
376             break;
377           case SWQ_DATE:
378             oFDefn.SetType( OFTDate );
379             break;
380           case SWQ_TIME:
381             oFDefn.SetType( OFTTime );
382             break;
383           case SWQ_GEOMETRY:
384             break;
385 
386           default:
387             CPLAssert( false );
388             oFDefn.SetType( OFTString );
389             break;
390         }
391         if( psColDef->target_subtype != OFSTNone )
392             oFDefn.SetSubType( psColDef->target_subtype );
393 
394         if (psColDef->field_length > 0)
395         {
396             oFDefn.SetWidth( psColDef->field_length );
397         }
398 
399         if (psColDef->field_precision >= 0)
400         {
401             oFDefn.SetPrecision( psColDef->field_precision );
402         }
403 
404         if( bIsGeometry )
405         {
406             panGeomFieldToSrcGeomField[poDefn->GetGeomFieldCount()] = iSrcGeomField;
407             /* Hack while drivers haven't been updated so that */
408             /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == poSrcLayer->GetSpatialRef() */
409             if( iSrcGeomField == 0 &&
410                 poSrcDefn->GetGeomFieldCount() == 1 &&
411                 oGFDefn.GetSpatialRef() == nullptr )
412             {
413                 oGFDefn.SetSpatialRef(poSrcLayer->GetSpatialRef());
414             }
415             int bForceGeomType = FALSE;
416             if( psColDef->eGeomType != wkbUnknown )
417             {
418                 oGFDefn.SetType( psColDef->eGeomType );
419                 bForceGeomType = TRUE;
420             }
421             if( psColDef->nSRID > 0 )
422             {
423                 OGRSpatialReference* poSRS = new OGRSpatialReference();
424                 poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
425                 if( poSRS->importFromEPSG( psColDef->nSRID ) == OGRERR_NONE )
426                 {
427                     oGFDefn.SetSpatialRef( poSRS );
428                 }
429                 poSRS->Release();
430             }
431 
432             OGRGenSQLGeomFieldDefn* poMyGeomFieldDefn =
433                 new OGRGenSQLGeomFieldDefn(&oGFDefn);
434             poMyGeomFieldDefn->bForceGeomType = bForceGeomType;
435             poDefn->AddGeomFieldDefn( poMyGeomFieldDefn, FALSE );
436         }
437         else
438             poDefn->AddFieldDefn( &oFDefn );
439     }
440 
441 /* -------------------------------------------------------------------- */
442 /*      Add implicit geometry field.                                    */
443 /* -------------------------------------------------------------------- */
444     if( psSelectInfo->query_mode == SWQM_RECORDSET &&
445         poDefn->GetGeomFieldCount() == 0 &&
446         poSrcDefn->GetGeomFieldCount() == 1 )
447     {
448         psSelectInfo->result_columns++;
449 
450         psSelectInfo->column_defs = static_cast<swq_col_def *>(
451             CPLRealloc( psSelectInfo->column_defs, sizeof(swq_col_def) * psSelectInfo->result_columns ));
452 
453         swq_col_def *col_def = psSelectInfo->column_defs + psSelectInfo->result_columns - 1;
454 
455         memset( col_def, 0, sizeof(swq_col_def) );
456         const char* pszName = poSrcDefn->GetGeomFieldDefn(0)->GetNameRef();
457         if( *pszName != '\0' )
458             col_def->field_name = CPLStrdup( pszName );
459         else
460             col_def->field_name = CPLStrdup( OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME );
461         col_def->field_alias = nullptr;
462         col_def->table_index = 0;
463         col_def->field_index = GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poSrcDefn, 0);
464         col_def->field_type = SWQ_GEOMETRY;
465         col_def->target_type = SWQ_GEOMETRY;
466 
467         panGeomFieldToSrcGeomField[poDefn->GetGeomFieldCount()] = 0;
468 
469         OGRGenSQLGeomFieldDefn* poMyGeomFieldDefn =
470             new OGRGenSQLGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
471         poDefn->AddGeomFieldDefn( poMyGeomFieldDefn, FALSE );
472 
473         /* Hack while drivers haven't been updated so that */
474         /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == poSrcLayer->GetSpatialRef() */
475         if( poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == nullptr )
476         {
477             poDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSrcLayer->GetSpatialRef());
478         }
479     }
480 
481 /* -------------------------------------------------------------------- */
482 /*      Now that we have poSrcLayer, we can install a spatial filter    */
483 /*      if there is one.                                                */
484 /* -------------------------------------------------------------------- */
485     if( poSpatFilter != nullptr )
486         OGRGenSQLResultsLayer::SetSpatialFilter( 0, poSpatFilter );
487 
488     OGRGenSQLResultsLayer::ResetReading();
489 
490     FindAndSetIgnoredFields();
491 
492     if( !bForwardWhereToSourceLayer )
493         OGRGenSQLResultsLayer::SetAttributeFilter( pszWHEREIn );
494 }
495 
496 /************************************************************************/
497 /*                       ~OGRGenSQLResultsLayer()                       */
498 /************************************************************************/
499 
~OGRGenSQLResultsLayer()500 OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
501 
502 {
503     if( m_nFeaturesRead > 0 && poDefn != nullptr )
504     {
505         CPLDebug( "GenSQL", CPL_FRMT_GIB " features read on layer '%s'.",
506                   m_nFeaturesRead,
507                   poDefn->GetName() );
508     }
509 
510     OGRGenSQLResultsLayer::ClearFilters();
511 
512 /* -------------------------------------------------------------------- */
513 /*      Free various datastructures.                                    */
514 /* -------------------------------------------------------------------- */
515     CPLFree( papoTableLayers );
516     papoTableLayers = nullptr;
517 
518     CPLFree( panFIDIndex );
519     CPLFree( panGeomFieldToSrcGeomField );
520 
521     delete poSummaryFeature;
522     delete static_cast<swq_select*>(pSelectInfo);
523 
524     if( poDefn != nullptr )
525     {
526         poDefn->Release();
527     }
528 
529 /* -------------------------------------------------------------------- */
530 /*      Release any additional datasources being used in joins.         */
531 /* -------------------------------------------------------------------- */
532     for( int iEDS = 0; iEDS < nExtraDSCount; iEDS++ )
533         GDALClose( GDALDataset::ToHandle(papoExtraDS[iEDS]) );
534 
535     CPLFree( papoExtraDS );
536     CPLFree( pszWHERE );
537 }
538 
539 /************************************************************************/
540 /*                            ClearFilters()                            */
541 /*                                                                      */
542 /*      Clear up all filters currently in place on the target layer,    */
543 /*      and joined layers.  We try not to leave them installed          */
544 /*      except when actively fetching features.                         */
545 /************************************************************************/
546 
ClearFilters()547 void OGRGenSQLResultsLayer::ClearFilters()
548 
549 {
550 /* -------------------------------------------------------------------- */
551 /*      Clear any filters installed on the target layer.                */
552 /* -------------------------------------------------------------------- */
553     if( poSrcLayer != nullptr )
554     {
555         poSrcLayer->ResetReading();
556         poSrcLayer->SetAttributeFilter( "" );
557         poSrcLayer->SetSpatialFilter( nullptr );
558     }
559 
560 /* -------------------------------------------------------------------- */
561 /*      Clear any attribute filter installed on the joined layers.      */
562 /* -------------------------------------------------------------------- */
563     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
564 
565     if( psSelectInfo != nullptr )
566     {
567         for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
568         {
569             swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
570             OGRLayer *poJoinLayer =
571                 papoTableLayers[psJoinInfo->secondary_table];
572 
573             poJoinLayer->SetAttributeFilter( "" );
574         }
575     }
576 
577 /* -------------------------------------------------------------------- */
578 /*      Clear any ignored field lists installed on source layers        */
579 /* -------------------------------------------------------------------- */
580     if( psSelectInfo != nullptr )
581     {
582         for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
583         {
584             OGRLayer* poLayer = papoTableLayers[iTable];
585             poLayer->SetIgnoredFields(nullptr);
586         }
587     }
588 }
589 
590 /************************************************************************/
591 /*                    MustEvaluateSpatialFilterOnGenSQL()               */
592 /************************************************************************/
593 
MustEvaluateSpatialFilterOnGenSQL()594 int OGRGenSQLResultsLayer::MustEvaluateSpatialFilterOnGenSQL()
595 {
596     int bEvaluateSpatialFilter = FALSE;
597     if( m_poFilterGeom != nullptr &&
598         m_iGeomFieldFilter >= 0 &&
599         m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount() )
600     {
601         int iSrcGeomField = panGeomFieldToSrcGeomField[m_iGeomFieldFilter];
602         if( iSrcGeomField < 0 )
603             bEvaluateSpatialFilter = TRUE;
604     }
605     return bEvaluateSpatialFilter;
606 }
607 
608 /************************************************************************/
609 /*                       ApplyFiltersToSource()                         */
610 /************************************************************************/
611 
ApplyFiltersToSource()612 void OGRGenSQLResultsLayer::ApplyFiltersToSource()
613 {
614     poSrcLayer->SetAttributeFilter( pszWHERE );
615     if( m_iGeomFieldFilter >= 0 &&
616         m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount() )
617     {
618         int iSrcGeomField = panGeomFieldToSrcGeomField[m_iGeomFieldFilter];
619         if( iSrcGeomField >= 0 )
620             poSrcLayer->SetSpatialFilter( iSrcGeomField, m_poFilterGeom );
621     }
622 
623     poSrcLayer->ResetReading();
624 }
625 
626 /************************************************************************/
627 /*                            ResetReading()                            */
628 /************************************************************************/
629 
ResetReading()630 void OGRGenSQLResultsLayer::ResetReading()
631 
632 {
633     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
634 
635     if( psSelectInfo->query_mode == SWQM_RECORDSET )
636     {
637         ApplyFiltersToSource();
638     }
639 
640     nNextIndexFID = psSelectInfo->offset;
641     nIteratedFeatures = -1;
642 }
643 
644 /************************************************************************/
645 /*                           SetNextByIndex()                           */
646 /*                                                                      */
647 /*      If we already have an FID list, we can easily reposition        */
648 /*      ourselves in it.                                                */
649 /************************************************************************/
650 
SetNextByIndex(GIntBig nIndex)651 OGRErr OGRGenSQLResultsLayer::SetNextByIndex( GIntBig nIndex )
652 
653 {
654     if( nIndex < 0 )
655         return OGRERR_FAILURE;
656 
657     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
658 
659     nIteratedFeatures = 0;
660 
661     CreateOrderByIndex();
662 
663     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
664         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
665         || panFIDIndex != nullptr )
666     {
667         nNextIndexFID = nIndex + psSelectInfo->offset;
668         return OGRERR_NONE;
669     }
670     else
671     {
672         return poSrcLayer->SetNextByIndex( nIndex + psSelectInfo->offset );
673     }
674 }
675 
676 /************************************************************************/
677 /*                             GetExtent()                              */
678 /************************************************************************/
679 
GetExtent(int iGeomField,OGREnvelope * psExtent,int bForce)680 OGRErr OGRGenSQLResultsLayer::GetExtent( int iGeomField,
681                                          OGREnvelope *psExtent,
682                                          int bForce )
683 
684 {
685     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
686 
687     if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
688         GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
689     {
690         if( iGeomField != 0 )
691         {
692             CPLError(CE_Failure, CPLE_AppDefined,
693                      "Invalid geometry field index : %d", iGeomField);
694         }
695         return OGRERR_FAILURE;
696     }
697 
698     if( psSelectInfo->query_mode == SWQM_RECORDSET )
699     {
700         int iSrcGeomField = panGeomFieldToSrcGeomField[iGeomField];
701         if( iSrcGeomField >= 0 )
702             return poSrcLayer->GetExtent( iSrcGeomField, psExtent, bForce );
703         else if( iGeomField == 0 )
704             return OGRLayer::GetExtent( psExtent, bForce );
705         else
706             return OGRLayer::GetExtent( iGeomField, psExtent, bForce );
707     }
708     else
709         return OGRERR_FAILURE;
710 }
711 
712 /************************************************************************/
713 /*                          GetFeatureCount()                           */
714 /************************************************************************/
715 
GetFeatureCount(int bForce)716 GIntBig OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
717 
718 {
719     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
720 
721     CreateOrderByIndex();
722 
723     GIntBig nRet = 0;
724     if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
725     {
726         if( !PrepareSummary() )
727             return 0;
728 
729         if( psSelectInfo->column_summary.empty() )
730             return 0;
731 
732         nRet = psSelectInfo->column_summary[0].count;
733     }
734     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
735         return 1;
736     else if( m_poAttrQuery == nullptr && !MustEvaluateSpatialFilterOnGenSQL() )
737     {
738         nRet = poSrcLayer->GetFeatureCount( bForce );
739     }
740     else
741     {
742         nRet = OGRLayer::GetFeatureCount( bForce );
743     }
744 
745     nRet = std::max(static_cast<GIntBig>(0), nRet - psSelectInfo->offset);
746     if( psSelectInfo->limit >= 0 )
747         nRet = std::min(nRet, psSelectInfo->limit);
748     return nRet;
749 }
750 
751 /************************************************************************/
752 /*                           TestCapability()                           */
753 /************************************************************************/
754 
TestCapability(const char * pszCap)755 int OGRGenSQLResultsLayer::TestCapability( const char *pszCap )
756 
757 {
758     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
759 
760     if( EQUAL(pszCap,OLCFastSetNextByIndex) )
761     {
762         if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
763             || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
764             || panFIDIndex != nullptr )
765             return TRUE;
766         else
767             return poSrcLayer->TestCapability( pszCap );
768     }
769 
770     if( psSelectInfo->query_mode == SWQM_RECORDSET
771         && (EQUAL(pszCap,OLCFastFeatureCount)
772             || EQUAL(pszCap,OLCRandomRead)
773             || EQUAL(pszCap,OLCFastGetExtent)) )
774         return poSrcLayer->TestCapability( pszCap );
775 
776     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
777     {
778         if( EQUAL(pszCap,OLCFastFeatureCount) )
779             return TRUE;
780     }
781     return FALSE;
782 }
783 
784 /************************************************************************/
785 /*                        ContainGeomSpecialField()                     */
786 /************************************************************************/
787 
ContainGeomSpecialField(swq_expr_node * expr)788 int OGRGenSQLResultsLayer::ContainGeomSpecialField(swq_expr_node* expr)
789 {
790     if (expr->eNodeType == SNT_COLUMN)
791     {
792         if( expr->table_index == 0 && expr->field_index != -1 )
793         {
794             OGRLayer* poLayer = papoTableLayers[expr->table_index];
795             int nSpecialFieldIdx = expr->field_index -
796                             poLayer->GetLayerDefn()->GetFieldCount();
797             if( nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
798                 nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
799                 nSpecialFieldIdx == SPF_OGR_GEOM_AREA )
800                 return TRUE;
801             if( expr->field_index ==
802                     GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(), 0) )
803                 return TRUE;
804             return FALSE;
805         }
806     }
807     else if (expr->eNodeType == SNT_OPERATION)
808     {
809         for( int i = 0; i < expr->nSubExprCount; i++ )
810         {
811             if (ContainGeomSpecialField(expr->papoSubExpr[i]))
812                 return TRUE;
813         }
814     }
815     return FALSE;
816 }
817 
818 /************************************************************************/
819 /*                           PrepareSummary()                           */
820 /************************************************************************/
821 
PrepareSummary()822 int OGRGenSQLResultsLayer::PrepareSummary()
823 
824 {
825     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
826 
827     if( poSummaryFeature != nullptr )
828         return TRUE;
829 
830     poSummaryFeature = new OGRFeature( poDefn );
831     poSummaryFeature->SetFID( 0 );
832 
833 /* -------------------------------------------------------------------- */
834 /*      Ensure our query parameters are in place on the source          */
835 /*      layer.  And initialize reading.                                 */
836 /* -------------------------------------------------------------------- */
837     ApplyFiltersToSource();
838 
839 /* -------------------------------------------------------------------- */
840 /*      Ignore geometry reading if no spatial filter in place and that  */
841 /*      the where clause and no column references OGR_GEOMETRY,         */
842 /*      OGR_GEOM_WKT or OGR_GEOM_AREA special fields.                   */
843 /* -------------------------------------------------------------------- */
844     int bSaveIsGeomIgnored = poSrcLayer->GetLayerDefn()->IsGeometryIgnored();
845     if ( m_poFilterGeom == nullptr && ( psSelectInfo->where_expr == nullptr ||
846                 !ContainGeomSpecialField(psSelectInfo->where_expr) ) )
847     {
848         int bFoundGeomExpr = FALSE;
849         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
850         {
851             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
852             if (psColDef->table_index == 0 && psColDef->field_index != -1)
853             {
854                 OGRLayer* poLayer = papoTableLayers[psColDef->table_index];
855                 int nSpecialFieldIdx = psColDef->field_index -
856                                 poLayer->GetLayerDefn()->GetFieldCount();
857                 if (nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
858                     nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
859                     nSpecialFieldIdx == SPF_OGR_GEOM_AREA)
860                 {
861                     bFoundGeomExpr = TRUE;
862                     break;
863                 }
864                 if( psColDef->field_index ==
865                         GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(), 0) )
866                 {
867                     bFoundGeomExpr = TRUE;
868                     break;
869                 }
870             }
871             if (psColDef->expr != nullptr && ContainGeomSpecialField(psColDef->expr))
872             {
873                 bFoundGeomExpr = TRUE;
874                 break;
875             }
876         }
877         if (!bFoundGeomExpr)
878             poSrcLayer->GetLayerDefn()->SetGeometryIgnored(TRUE);
879     }
880 
881 /* -------------------------------------------------------------------- */
882 /*      We treat COUNT(*) as a special case, and fill with              */
883 /*      GetFeatureCount().                                            */
884 /* -------------------------------------------------------------------- */
885 
886     if( psSelectInfo->result_columns == 1
887         && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
888         && psSelectInfo->column_defs[0].field_index < 0 )
889     {
890         GIntBig nRes = poSrcLayer->GetFeatureCount( TRUE );
891         poSummaryFeature->SetField( 0, nRes );
892 
893         if( CPL_INT64_FITS_ON_INT32(nRes) )
894         {
895             poDefn->GetFieldDefn(0)->SetType(OFTInteger);
896             delete poSummaryFeature;
897             poSummaryFeature = new OGRFeature( poDefn );
898             poSummaryFeature->SetFID( 0 );
899             poSummaryFeature->SetField( 0, static_cast<int>(nRes) );
900         }
901 
902         poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
903         return TRUE;
904     }
905 
906 /* -------------------------------------------------------------------- */
907 /*      Otherwise, process all source feature through the summary       */
908 /*      building facilities of SWQ.                                     */
909 /* -------------------------------------------------------------------- */
910     const char *pszError = nullptr;
911     OGRFeature *poSrcFeature = nullptr;
912 
913     while( (poSrcFeature = poSrcLayer->GetNextFeature()) != nullptr )
914     {
915         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
916         {
917             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
918 
919             if (psColDef->col_func == SWQCF_COUNT)
920             {
921                 /* psColDef->field_index can be -1 in the case of a COUNT(*) */
922                 if (psColDef->field_index < 0)
923                     pszError = swq_select_summarize( psSelectInfo, iField, "" );
924                 else if (IS_GEOM_FIELD_INDEX(poSrcLayer->GetLayerDefn(), psColDef->field_index) )
925                 {
926                     int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
927                             poSrcLayer->GetLayerDefn(), psColDef->field_index);
928                     OGRGeometry* poGeom = poSrcFeature->GetGeomFieldRef(iSrcGeomField);
929                     if( poGeom != nullptr )
930                         pszError = swq_select_summarize( psSelectInfo, iField, "" );
931                     else
932                         pszError = nullptr;
933                 }
934                 else if (poSrcFeature->IsFieldSetAndNotNull(psColDef->field_index))
935                     pszError = swq_select_summarize( psSelectInfo, iField, poSrcFeature->GetFieldAsString(
936                                                 psColDef->field_index ) );
937                 else
938                     pszError = nullptr;
939             }
940             else
941             {
942                 const char* pszVal = nullptr;
943                 if (poSrcFeature->IsFieldSetAndNotNull(psColDef->field_index))
944                     pszVal = poSrcFeature->GetFieldAsString(
945                                                 psColDef->field_index );
946                 pszError = swq_select_summarize( psSelectInfo, iField, pszVal );
947             }
948 
949             if( pszError != nullptr )
950             {
951                 delete poSrcFeature;
952                 delete poSummaryFeature;
953                 poSummaryFeature = nullptr;
954 
955                 poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
956 
957                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
958                 return FALSE;
959             }
960         }
961 
962         delete poSrcFeature;
963     }
964 
965     poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
966 
967 /* -------------------------------------------------------------------- */
968 /*      Clear away the filters we have installed till a next run through*/
969 /*      the features.                                                   */
970 /* -------------------------------------------------------------------- */
971     ClearFilters();
972 
973 /* -------------------------------------------------------------------- */
974 /*      Now apply the values to the summary feature.  If we are in      */
975 /*      DISTINCT_LIST mode we don't do this step.                       */
976 /* -------------------------------------------------------------------- */
977     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
978     {
979         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
980         {
981             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
982             if( !psSelectInfo->column_summary.empty() )
983             {
984                 swq_summary& oSummary = psSelectInfo->column_summary[iField];
985                 if( psColDef->col_func == SWQCF_COUNT )
986                 {
987                     if( CPL_INT64_FITS_ON_INT32(oSummary.count) )
988                     {
989                         delete poSummaryFeature;
990                         poSummaryFeature = nullptr;
991                         poDefn->GetFieldDefn(iField)->SetType(OFTInteger);
992                     }
993                 }
994             }
995         }
996 
997         if( poSummaryFeature == nullptr )
998         {
999             poSummaryFeature = new OGRFeature( poDefn );
1000             poSummaryFeature->SetFID( 0 );
1001         }
1002 
1003         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
1004         {
1005             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
1006             if (!psSelectInfo->column_summary.empty() )
1007             {
1008                 swq_summary& oSummary = psSelectInfo->column_summary[iField];
1009 
1010                 if( psColDef->col_func == SWQCF_AVG && oSummary.count > 0 )
1011                 {
1012                     if( psColDef->field_type == SWQ_DATE ||
1013                         psColDef->field_type == SWQ_TIME ||
1014                         psColDef->field_type == SWQ_TIMESTAMP)
1015                     {
1016                         struct tm brokendowntime;
1017                         double dfAvg = oSummary.sum / oSummary.count;
1018                         CPLUnixTimeToYMDHMS(static_cast<GIntBig>(dfAvg), &brokendowntime);
1019                         poSummaryFeature->SetField( iField,
1020                                                     brokendowntime.tm_year + 1900,
1021                                                     brokendowntime.tm_mon + 1,
1022                                                     brokendowntime.tm_mday,
1023                                                     brokendowntime.tm_hour,
1024                                                     brokendowntime.tm_min,
1025                                                     static_cast<float>(brokendowntime.tm_sec + fmod(dfAvg, 1)),
1026                                                     0);
1027                     }
1028                     else
1029                         poSummaryFeature->SetField( iField,
1030                                                     oSummary.sum / oSummary.count );
1031                 }
1032                 else if( psColDef->col_func == SWQCF_MIN && oSummary.count > 0 )
1033                 {
1034                     if( psColDef->field_type == SWQ_DATE ||
1035                         psColDef->field_type == SWQ_TIME ||
1036                         psColDef->field_type == SWQ_TIMESTAMP)
1037                         poSummaryFeature->SetField( iField, oSummary.osMin.c_str() );
1038                     else
1039                         poSummaryFeature->SetField( iField, oSummary.min );
1040                 }
1041                 else if( psColDef->col_func == SWQCF_MAX && oSummary.count > 0 )
1042                 {
1043                     if( psColDef->field_type == SWQ_DATE ||
1044                         psColDef->field_type == SWQ_TIME ||
1045                         psColDef->field_type == SWQ_TIMESTAMP)
1046                         poSummaryFeature->SetField( iField, oSummary.osMax.c_str() );
1047                     else
1048                         poSummaryFeature->SetField( iField, oSummary.max );
1049                 }
1050                 else if( psColDef->col_func == SWQCF_COUNT )
1051                     poSummaryFeature->SetField( iField, oSummary.count );
1052                 else if( psColDef->col_func == SWQCF_SUM && oSummary.count > 0 )
1053                     poSummaryFeature->SetField( iField, oSummary.sum );
1054             }
1055             else if ( psColDef->col_func == SWQCF_COUNT )
1056                 poSummaryFeature->SetField( iField, 0 );
1057         }
1058     }
1059 
1060     return TRUE;
1061 }
1062 
1063 /************************************************************************/
1064 /*                       OGRMultiFeatureFetcher()                       */
1065 /************************************************************************/
1066 
OGRMultiFeatureFetcher(swq_expr_node * op,void * pFeatureList)1067 static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
1068                                               void *pFeatureList )
1069 
1070 {
1071     std::vector<OGRFeature*> *papoFeatures =
1072         static_cast<std::vector<OGRFeature*> *>(pFeatureList);
1073     swq_expr_node *poRetNode = nullptr;
1074 
1075     CPLAssert( op->eNodeType == SNT_COLUMN );
1076 
1077 /* -------------------------------------------------------------------- */
1078 /*      What feature are we using?  The primary or one of the joined ones?*/
1079 /* -------------------------------------------------------------------- */
1080     if( op->table_index < 0 ||
1081         op->table_index >= static_cast<int>(papoFeatures->size()) )
1082     {
1083         CPLError( CE_Failure, CPLE_AppDefined,
1084                   "Request for unexpected table_index (%d) in field fetcher.",
1085                   op->table_index );
1086         return nullptr;
1087     }
1088 
1089     OGRFeature *poFeature = (*papoFeatures)[op->table_index];
1090 
1091 /* -------------------------------------------------------------------- */
1092 /*      Fetch the value.                                                */
1093 /* -------------------------------------------------------------------- */
1094     switch( op->field_type )
1095     {
1096       case SWQ_INTEGER:
1097       case SWQ_BOOLEAN:
1098         if( poFeature == nullptr
1099             || !poFeature->IsFieldSetAndNotNull(op->field_index) )
1100         {
1101             poRetNode = new swq_expr_node(0);
1102             poRetNode->is_null = TRUE;
1103         }
1104         else
1105             poRetNode = new swq_expr_node(
1106                 poFeature->GetFieldAsInteger(op->field_index) );
1107         break;
1108 
1109       case SWQ_INTEGER64:
1110         if( poFeature == nullptr
1111             || !poFeature->IsFieldSetAndNotNull(op->field_index) )
1112         {
1113             poRetNode = new swq_expr_node( static_cast<GIntBig>(0) );
1114             poRetNode->is_null = TRUE;
1115         }
1116         else
1117             poRetNode = new swq_expr_node(
1118                 poFeature->GetFieldAsInteger64(op->field_index) );
1119         break;
1120 
1121       case SWQ_FLOAT:
1122         if( poFeature == nullptr
1123             || !poFeature->IsFieldSetAndNotNull(op->field_index) )
1124         {
1125             poRetNode = new swq_expr_node( 0.0 );
1126             poRetNode->is_null = TRUE;
1127         }
1128         else
1129             poRetNode = new swq_expr_node(
1130                 poFeature->GetFieldAsDouble(op->field_index) );
1131         break;
1132 
1133       case SWQ_GEOMETRY:
1134         if( poFeature == nullptr )
1135         {
1136             poRetNode = new swq_expr_node( static_cast<OGRGeometry*>(nullptr) );
1137         }
1138         else
1139         {
1140             int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
1141                 poFeature->GetDefnRef(), op->field_index);
1142             poRetNode = new swq_expr_node(
1143                 poFeature->GetGeomFieldRef(iSrcGeomField) );
1144         }
1145         break;
1146 
1147       default:
1148         if( poFeature == nullptr
1149             || !poFeature->IsFieldSetAndNotNull(op->field_index) )
1150         {
1151             poRetNode = new swq_expr_node("");
1152             poRetNode->is_null = TRUE;
1153         }
1154         else
1155             poRetNode = new swq_expr_node(
1156                 poFeature->GetFieldAsString(op->field_index) );
1157         break;
1158     }
1159 
1160     return poRetNode;
1161 }
1162 
1163 /************************************************************************/
1164 /*                          GetFilterForJoin()                          */
1165 /************************************************************************/
1166 
GetFilterForJoin(swq_expr_node * poExpr,OGRFeature * poSrcFeat,OGRLayer * poJoinLayer,int secondary_table)1167 static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
1168                                   OGRLayer* poJoinLayer, int secondary_table)
1169 {
1170     if( poExpr->eNodeType == SNT_CONSTANT )
1171     {
1172         char* pszRes = poExpr->Unparse(nullptr, '"');
1173         CPLString osRes = pszRes;
1174         CPLFree(pszRes);
1175         return osRes;
1176     }
1177 
1178     if( poExpr->eNodeType == SNT_COLUMN )
1179     {
1180         CPLAssert( poExpr->field_index != -1 );
1181         CPLAssert( poExpr->table_index == 0 || poExpr->table_index == secondary_table );
1182 
1183         if( poExpr->table_index == 0 )
1184         {
1185             // if source key is null, we can't do join.
1186             if( !poSrcFeat->IsFieldSetAndNotNull( poExpr->field_index ) )
1187             {
1188                 return "";
1189             }
1190             OGRFieldType ePrimaryFieldType =
1191                     poSrcFeat->GetFieldDefnRef(poExpr->field_index)->GetType();
1192             OGRField *psSrcField =
1193                     poSrcFeat->GetRawFieldRef(poExpr->field_index);
1194 
1195             switch( ePrimaryFieldType )
1196             {
1197             case OFTInteger:
1198                 return CPLString().Printf("%d", psSrcField->Integer );
1199                 break;
1200 
1201             case OFTInteger64:
1202                 return CPLString().Printf(CPL_FRMT_GIB, psSrcField->Integer64 );
1203                 break;
1204 
1205             case OFTReal:
1206                 return CPLString().Printf("%.16g", psSrcField->Real );
1207                 break;
1208 
1209             case OFTString:
1210             {
1211                 char *pszEscaped = CPLEscapeString( psSrcField->String,
1212                                                     static_cast<int>(strlen(psSrcField->String)),
1213                                                     CPLES_SQL );
1214                 CPLString osRes = "'";
1215                 osRes += pszEscaped;
1216                 osRes += "'";
1217                 CPLFree( pszEscaped );
1218                 return osRes;
1219             }
1220             break;
1221 
1222             default:
1223                 CPLAssert( false );
1224                 return "";
1225             }
1226         }
1227 
1228         if(  poExpr->table_index == secondary_table )
1229         {
1230             OGRFieldDefn* poSecondaryFieldDefn =
1231                 poJoinLayer->GetLayerDefn()->GetFieldDefn(poExpr->field_index);
1232             return CPLSPrintf("\"%s\"", poSecondaryFieldDefn->GetNameRef());
1233         }
1234 
1235         CPLAssert(false);
1236         return "";
1237     }
1238 
1239     if( poExpr->eNodeType == SNT_OPERATION )
1240     {
1241         /* ----------------------------------------------------------------- */
1242         /*      Operation - start by unparsing all the subexpressions.       */
1243         /* ----------------------------------------------------------------- */
1244         std::vector<char*> apszSubExpr;
1245         for( int i = 0; i < poExpr->nSubExprCount; i++ )
1246         {
1247             CPLString osSubExpr = GetFilterForJoin(poExpr->papoSubExpr[i], poSrcFeat,
1248                                                    poJoinLayer, secondary_table);
1249             if( osSubExpr.empty() )
1250             {
1251                 for( --i; i >=0; i-- )
1252                     CPLFree( apszSubExpr[i] );
1253                 return "";
1254             }
1255             apszSubExpr.push_back( CPLStrdup(osSubExpr) );
1256         }
1257 
1258         CPLString osExpr = poExpr->UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
1259 
1260         /* ----------------------------------------------------------------- */
1261         /*      cleanup subexpressions.                                      */
1262         /* ----------------------------------------------------------------- */
1263         for( int i = 0; i < poExpr->nSubExprCount; i++ )
1264             CPLFree( apszSubExpr[i] );
1265 
1266         return osExpr;
1267     }
1268 
1269     return "";
1270 }
1271 
1272 /************************************************************************/
1273 /*                          TranslateFeature()                          */
1274 /************************************************************************/
1275 
TranslateFeature(OGRFeature * poSrcFeat)1276 OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
1277 
1278 {
1279     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
1280     std::vector<OGRFeature*> apoFeatures;
1281 
1282     if( poSrcFeat == nullptr )
1283         return nullptr;
1284 
1285     m_nFeaturesRead++;
1286 
1287     apoFeatures.push_back( poSrcFeat );
1288 
1289 /* -------------------------------------------------------------------- */
1290 /*      Fetch the corresponding features from any jointed tables.       */
1291 /* -------------------------------------------------------------------- */
1292     for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
1293     {
1294         CPLString osFilter;
1295 
1296         swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1297 
1298         /* OGRMultiFeatureFetcher assumes that the features are pushed in */
1299         /* apoFeatures with increasing secondary_table, so make sure */
1300         /* we have taken care of this */
1301         CPLAssert(psJoinInfo->secondary_table == iJoin + 1);
1302 
1303         OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table];
1304 
1305         osFilter = GetFilterForJoin(psJoinInfo->poExpr, poSrcFeat, poJoinLayer,
1306                                     psJoinInfo->secondary_table);
1307         //CPLDebug("OGR", "Filter = %s\n", osFilter.c_str());
1308 
1309         // if source key is null, we can't do join.
1310         if( osFilter.empty() )
1311         {
1312             apoFeatures.push_back( nullptr );
1313             continue;
1314         }
1315 
1316         OGRFeature *poJoinFeature = nullptr;
1317 
1318         poJoinLayer->ResetReading();
1319         if( poJoinLayer->SetAttributeFilter( osFilter.c_str() ) == OGRERR_NONE )
1320             poJoinFeature = poJoinLayer->GetNextFeature();
1321 
1322         apoFeatures.push_back( poJoinFeature );
1323     }
1324 
1325 /* -------------------------------------------------------------------- */
1326 /*      Create destination feature.                                     */
1327 /* -------------------------------------------------------------------- */
1328     OGRFeature *poDstFeat = new OGRFeature( poDefn );
1329 
1330     poDstFeat->SetFID( poSrcFeat->GetFID() );
1331 
1332     poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
1333     poDstFeat->SetNativeData( poSrcFeat->GetNativeData() );
1334     poDstFeat->SetNativeMediaType( poSrcFeat->GetNativeMediaType() );
1335 
1336 /* -------------------------------------------------------------------- */
1337 /*      Evaluate fields that are complex expressions.                   */
1338 /* -------------------------------------------------------------------- */
1339     int iRegularField = 0;
1340     int iGeomField = 0;
1341     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
1342     {
1343         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
1344         if( psColDef->field_index != -1 )
1345         {
1346             if( psColDef->field_type == SWQ_GEOMETRY ||
1347                 psColDef->target_type == SWQ_GEOMETRY )
1348                 iGeomField++;
1349             else
1350                 iRegularField++;
1351             continue;
1352         }
1353 
1354         swq_expr_node *poResult =
1355             psColDef->expr->Evaluate( OGRMultiFeatureFetcher,
1356                                       &apoFeatures );
1357 
1358         if( poResult == nullptr )
1359         {
1360             delete poDstFeat;
1361             return nullptr;
1362         }
1363 
1364         if( poResult->is_null )
1365         {
1366             if( poResult->field_type == SWQ_GEOMETRY )
1367                 iGeomField++;
1368             else
1369                 iRegularField++;
1370             delete poResult;
1371             continue;
1372         }
1373 
1374         switch( poResult->field_type )
1375         {
1376           case SWQ_BOOLEAN:
1377           case SWQ_INTEGER:
1378           case SWQ_INTEGER64:
1379             poDstFeat->SetField( iRegularField++, poResult->int_value );
1380             break;
1381 
1382           case SWQ_FLOAT:
1383             poDstFeat->SetField( iRegularField++, poResult->float_value );
1384             break;
1385 
1386           case SWQ_GEOMETRY:
1387           {
1388             OGRGenSQLGeomFieldDefn* poGeomFieldDefn =
1389                 cpl::down_cast<OGRGenSQLGeomFieldDefn*>(poDstFeat->GetGeomFieldDefnRef(iGeomField));
1390             if( poGeomFieldDefn->bForceGeomType &&
1391                 poResult->geometry_value != nullptr )
1392             {
1393                 OGRwkbGeometryType eCurType =
1394                     wkbFlatten(poResult->geometry_value->getGeometryType());
1395                 OGRwkbGeometryType eReqType =
1396                     wkbFlatten(poGeomFieldDefn->GetType());
1397                 if( eCurType == wkbPolygon && eReqType == wkbMultiPolygon )
1398                 {
1399                     poResult->geometry_value = OGRGeometry::FromHandle(
1400                         OGR_G_ForceToMultiPolygon( OGRGeometry::ToHandle(poResult->geometry_value) ));
1401                 }
1402                 else if( (eCurType == wkbMultiPolygon || eCurType == wkbGeometryCollection) &&
1403                          eReqType == wkbPolygon )
1404                 {
1405                     poResult->geometry_value = OGRGeometry::FromHandle(
1406                         OGR_G_ForceToPolygon( OGRGeometry::ToHandle(poResult->geometry_value) ));
1407                 }
1408                 else if( eCurType == wkbLineString && eReqType == wkbMultiLineString )
1409                 {
1410                     poResult->geometry_value = OGRGeometry::FromHandle(
1411                         OGR_G_ForceToMultiLineString( OGRGeometry::ToHandle(poResult->geometry_value) ));
1412                 }
1413                 else if( (eCurType == wkbMultiLineString || eCurType == wkbGeometryCollection) &&
1414                          eReqType == wkbLineString )
1415                 {
1416                     poResult->geometry_value = OGRGeometry::FromHandle(
1417                         OGR_G_ForceToLineString( OGRGeometry::ToHandle(poResult->geometry_value) ));
1418                 }
1419             }
1420             poDstFeat->SetGeomField( iGeomField++, poResult->geometry_value );
1421             break;
1422           }
1423 
1424           default:
1425             poDstFeat->SetField( iRegularField++, poResult->string_value );
1426             break;
1427         }
1428 
1429         delete poResult;
1430     }
1431 
1432 /* -------------------------------------------------------------------- */
1433 /*      Copy fields from primary record to the destination feature.     */
1434 /* -------------------------------------------------------------------- */
1435     iRegularField = 0;
1436     iGeomField = 0;
1437     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
1438     {
1439         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
1440 
1441         if( psColDef->table_index != 0 )
1442         {
1443             if( psColDef->field_type == SWQ_GEOMETRY ||
1444                 psColDef->target_type == SWQ_GEOMETRY )
1445                 iGeomField++;
1446             else
1447                 iRegularField++;
1448             continue;
1449         }
1450 
1451         if( IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(), psColDef->field_index) )
1452         {
1453             int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
1454                 poSrcFeat->GetDefnRef(), psColDef->field_index);
1455             poDstFeat->SetGeomField( iGeomField ++,
1456                                      poSrcFeat->GetGeomFieldRef(iSrcGeomField) );
1457         }
1458         else if( psColDef->field_index >= iFIDFieldIndex )
1459         {
1460             CPLAssert( psColDef->field_index <
1461                                     iFIDFieldIndex + SPECIAL_FIELD_COUNT );
1462             switch (SpecialFieldTypes[psColDef->field_index - iFIDFieldIndex])
1463             {
1464               case SWQ_INTEGER:
1465               case SWQ_INTEGER64:
1466                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsInteger64(psColDef->field_index) );
1467                 break;
1468               case SWQ_FLOAT:
1469                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
1470                 break;
1471               default:
1472                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
1473             }
1474             iRegularField ++;
1475         }
1476         else
1477         {
1478             switch (psColDef->target_type)
1479             {
1480               case SWQ_INTEGER:
1481                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
1482                 break;
1483 
1484               case SWQ_INTEGER64:
1485                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsInteger64(psColDef->field_index) );
1486                 break;
1487 
1488               case SWQ_FLOAT:
1489                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
1490                 break;
1491 
1492               case SWQ_STRING:
1493               case SWQ_TIMESTAMP:
1494               case SWQ_DATE:
1495               case SWQ_TIME:
1496                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
1497                 break;
1498 
1499               case SWQ_GEOMETRY:
1500                   CPLAssert(false);
1501                   break;
1502 
1503               default:
1504                 poDstFeat->SetField( iRegularField,
1505                          poSrcFeat->GetRawFieldRef( psColDef->field_index ) );
1506             }
1507             iRegularField ++;
1508         }
1509     }
1510 
1511 /* -------------------------------------------------------------------- */
1512 /*      Copy values from any joined tables.                             */
1513 /* -------------------------------------------------------------------- */
1514     for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
1515     {
1516         CPLString osFilter;
1517 
1518         swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1519         OGRFeature *poJoinFeature = apoFeatures[iJoin+1];
1520 
1521         if( poJoinFeature == nullptr )
1522             continue;
1523 
1524         // Copy over selected field values.
1525         iRegularField = 0;
1526         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
1527         {
1528             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
1529 
1530             if( psColDef->field_type == SWQ_GEOMETRY ||
1531                 psColDef->target_type == SWQ_GEOMETRY )
1532                 continue;
1533 
1534             if( psColDef->table_index == psJoinInfo->secondary_table )
1535                 poDstFeat->SetField( iRegularField,
1536                                      poJoinFeature->GetRawFieldRef(
1537                                          psColDef->field_index ) );
1538 
1539             iRegularField ++;
1540         }
1541 
1542         delete poJoinFeature;
1543     }
1544 
1545     return poDstFeat;
1546 }
1547 
1548 /************************************************************************/
1549 /*                           GetNextFeature()                           */
1550 /************************************************************************/
1551 
GetNextFeature()1552 OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
1553 
1554 {
1555     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
1556 
1557     if( psSelectInfo->limit >= 0 &&
1558         (nIteratedFeatures < 0 ? 0 : nIteratedFeatures) >= psSelectInfo->limit )
1559         return nullptr;
1560 
1561     CreateOrderByIndex();
1562     if( panFIDIndex == nullptr &&
1563         nIteratedFeatures < 0 && psSelectInfo->offset > 0 &&
1564         psSelectInfo->query_mode == SWQM_RECORDSET )
1565     {
1566         poSrcLayer->SetNextByIndex(psSelectInfo->offset);
1567     }
1568     if( nIteratedFeatures < 0 )
1569         nIteratedFeatures = 0;
1570 
1571 /* -------------------------------------------------------------------- */
1572 /*      Handle summary sets.                                            */
1573 /* -------------------------------------------------------------------- */
1574     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
1575         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
1576     {
1577         nIteratedFeatures ++;
1578         return GetFeature( nNextIndexFID++ );
1579     }
1580 
1581     int bEvaluateSpatialFilter = MustEvaluateSpatialFilterOnGenSQL();
1582 
1583 /* -------------------------------------------------------------------- */
1584 /*      Handle ordered sets.                                            */
1585 /* -------------------------------------------------------------------- */
1586     while( true )
1587     {
1588         OGRFeature *poFeature = nullptr;
1589 
1590         if( panFIDIndex != nullptr )
1591             poFeature = GetFeature( nNextIndexFID++ );
1592         else
1593         {
1594             OGRFeature *poSrcFeat = poSrcLayer->GetNextFeature();
1595 
1596             if( poSrcFeat == nullptr )
1597                 return nullptr;
1598 
1599             poFeature = TranslateFeature( poSrcFeat );
1600             delete poSrcFeat;
1601         }
1602 
1603         if( poFeature == nullptr )
1604             return nullptr;
1605 
1606         if( (m_poAttrQuery == nullptr
1607             || m_poAttrQuery->Evaluate( poFeature )) &&
1608             (!bEvaluateSpatialFilter ||
1609              FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) )) )
1610         {
1611             nIteratedFeatures ++;
1612             return poFeature;
1613         }
1614 
1615         delete poFeature;
1616     }
1617 
1618     return nullptr;
1619 }
1620 
1621 /************************************************************************/
1622 /*                             GetFeature()                             */
1623 /************************************************************************/
1624 
GetFeature(GIntBig nFID)1625 OGRFeature *OGRGenSQLResultsLayer::GetFeature( GIntBig nFID )
1626 
1627 {
1628     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
1629 
1630     CreateOrderByIndex();
1631 
1632 /* -------------------------------------------------------------------- */
1633 /*      Handle request for summary record.                              */
1634 /* -------------------------------------------------------------------- */
1635     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
1636     {
1637         if( !PrepareSummary() || nFID != 0 || poSummaryFeature == nullptr )
1638             return nullptr;
1639         else
1640             return poSummaryFeature->Clone();
1641     }
1642 
1643 /* -------------------------------------------------------------------- */
1644 /*      Handle request for distinct list record.                        */
1645 /* -------------------------------------------------------------------- */
1646     if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
1647     {
1648         if( !PrepareSummary() )
1649             return nullptr;
1650 
1651         if( psSelectInfo->column_summary.empty() )
1652             return nullptr;
1653 
1654         swq_summary& oSummary = psSelectInfo->column_summary[0];
1655         if( psSelectInfo->order_specs == 0 )
1656         {
1657             if( nFID < 0 || nFID >= static_cast<GIntBig>(
1658                                     oSummary.oVectorDistinctValues.size()) )
1659             {
1660                 return nullptr;
1661             }
1662             const size_t nIdx = static_cast<size_t>(nFID);
1663             if( oSummary.oVectorDistinctValues[nIdx] != SZ_OGR_NULL )
1664             {
1665                 poSummaryFeature->SetField( 0,
1666                             oSummary. oVectorDistinctValues[nIdx].c_str() );
1667             }
1668             else
1669                 poSummaryFeature->SetFieldNull( 0 );
1670         }
1671         else
1672         {
1673             if( m_oDistinctList.empty() )
1674             {
1675                 std::set<CPLString, swq_summary::Comparator>::const_iterator
1676                     oIter = oSummary.oSetDistinctValues.begin();
1677                 std::set<CPLString, swq_summary::Comparator>::const_iterator
1678                     oEnd = oSummary.oSetDistinctValues.end();
1679                 try
1680                 {
1681                     m_oDistinctList.reserve(
1682                                         oSummary.oSetDistinctValues.size() );
1683                     for( ; oIter != oEnd; ++oIter )
1684                     {
1685                         m_oDistinctList.push_back( *oIter );
1686                     }
1687                 }
1688                 catch( std::bad_alloc& )
1689                 {
1690                     return nullptr;
1691                 }
1692                 oSummary.oSetDistinctValues.clear();
1693             }
1694 
1695             if( nFID < 0 ||
1696                 nFID >= static_cast<GIntBig>(m_oDistinctList.size()) )
1697                 return nullptr;
1698 
1699             const size_t nIdx = static_cast<size_t>(nFID);
1700             if( m_oDistinctList[nIdx] != SZ_OGR_NULL )
1701                 poSummaryFeature->SetField( 0, m_oDistinctList[nIdx].c_str() );
1702             else
1703                 poSummaryFeature->SetFieldNull( 0 );
1704         }
1705 
1706         poSummaryFeature->SetFID( nFID );
1707 
1708         return poSummaryFeature->Clone();
1709     }
1710 
1711 /* -------------------------------------------------------------------- */
1712 /*      Are we running in sorted mode?  If so, run the fid through      */
1713 /*      the index.                                                      */
1714 /* -------------------------------------------------------------------- */
1715     if( panFIDIndex != nullptr )
1716     {
1717         if( nFID < 0 || nFID >= static_cast<GIntBig>(nIndexSize) )
1718             return nullptr;
1719         else
1720             nFID = panFIDIndex[nFID];
1721     }
1722 
1723 /* -------------------------------------------------------------------- */
1724 /*      Handle request for random record.                               */
1725 /* -------------------------------------------------------------------- */
1726     OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
1727 
1728     if( poSrcFeature == nullptr )
1729         return nullptr;
1730 
1731     OGRFeature *poResult = TranslateFeature( poSrcFeature );
1732     poResult->SetFID( nFID );
1733 
1734     delete poSrcFeature;
1735 
1736     return poResult;
1737 }
1738 
1739 /************************************************************************/
1740 /*                          GetSpatialFilter()                          */
1741 /************************************************************************/
1742 
GetSpatialFilter()1743 OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
1744 
1745 {
1746     return nullptr;
1747 }
1748 
1749 /************************************************************************/
1750 /*                            GetLayerDefn()                            */
1751 /************************************************************************/
1752 
GetLayerDefn()1753 OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
1754 
1755 {
1756     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
1757     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD &&
1758         poSummaryFeature == nullptr )
1759     {
1760         // Run PrepareSummary() is we have a COUNT column so as to be
1761         // able to downcast it from OFTInteger64 to OFTInteger
1762         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
1763         {
1764             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
1765             if( psColDef->col_func == SWQCF_COUNT )
1766             {
1767                 PrepareSummary();
1768                 break;
1769             }
1770         }
1771     }
1772 
1773     return poDefn;
1774 }
1775 
1776 /************************************************************************/
1777 /*                         FreeIndexFields()                            */
1778 /************************************************************************/
1779 
FreeIndexFields(OGRField * pasIndexFields,size_t l_nIndexSize,bool bFreeArray)1780 void OGRGenSQLResultsLayer::FreeIndexFields(OGRField *pasIndexFields,
1781                                             size_t l_nIndexSize,
1782                                             bool bFreeArray)
1783 {
1784     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
1785     const int nOrderItems = psSelectInfo->order_specs;
1786 
1787 /* -------------------------------------------------------------------- */
1788 /*      Free the key field values.                                      */
1789 /* -------------------------------------------------------------------- */
1790     for( int iKey = 0; iKey < nOrderItems; iKey++ )
1791     {
1792         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
1793 
1794         if ( psKeyDef->field_index >= iFIDFieldIndex )
1795         {
1796             CPLAssert( psKeyDef->field_index <
1797                                     iFIDFieldIndex + SPECIAL_FIELD_COUNT );
1798             /* warning: only special fields of type string should be deallocated */
1799             if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
1800             {
1801                 for( size_t i = 0; i < l_nIndexSize; i++ )
1802                 {
1803                     OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
1804                     CPLFree( psField->String );
1805                 }
1806             }
1807             continue;
1808         }
1809 
1810         OGRFieldDefn *poFDefn =
1811             poSrcLayer->GetLayerDefn()->GetFieldDefn( psKeyDef->field_index );
1812 
1813         if( poFDefn->GetType() == OFTString )
1814         {
1815             for( size_t i = 0; i < l_nIndexSize; i++ )
1816             {
1817                 OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
1818 
1819                 if( !OGR_RawField_IsUnset(psField) &&
1820                     !OGR_RawField_IsNull(psField) )
1821                     CPLFree( psField->String );
1822             }
1823         }
1824     }
1825 
1826     if( bFreeArray )
1827         VSIFree(pasIndexFields);
1828 }
1829 
1830 /************************************************************************/
1831 /*                         ReadIndexFields()                            */
1832 /************************************************************************/
1833 
ReadIndexFields(OGRFeature * poSrcFeat,int nOrderItems,OGRField * pasIndexFields)1834 void OGRGenSQLResultsLayer::ReadIndexFields( OGRFeature* poSrcFeat,
1835                                              int nOrderItems,
1836                                              OGRField *pasIndexFields )
1837 {
1838     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
1839     for( int iKey = 0; iKey < nOrderItems; iKey++ )
1840     {
1841         const swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
1842         OGRField *psDstField = pasIndexFields + iKey;
1843 
1844         if ( psKeyDef->field_index >= iFIDFieldIndex)
1845         {
1846             CPLAssert( psKeyDef->field_index <
1847                                 iFIDFieldIndex + SPECIAL_FIELD_COUNT );
1848 
1849             switch (SpecialFieldTypes[
1850                             psKeyDef->field_index - iFIDFieldIndex])
1851             {
1852                 case SWQ_INTEGER:
1853                 case SWQ_INTEGER64:
1854                 // Yes, store Integer as Integer64.
1855                 // This is consistent with the test in Compare()
1856                 psDstField->Integer64 =
1857                     poSrcFeat->GetFieldAsInteger64(
1858                         psKeyDef->field_index);
1859                 break;
1860 
1861                 case SWQ_FLOAT:
1862                 psDstField->Real =
1863                     poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
1864                 break;
1865 
1866                 default:
1867                 psDstField->String = CPLStrdup(
1868                     poSrcFeat->GetFieldAsString(
1869                         psKeyDef->field_index) );
1870                 break;
1871             }
1872 
1873             continue;
1874         }
1875 
1876         OGRFieldDefn *poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1877             psKeyDef->field_index );
1878 
1879         OGRField *psSrcField =
1880             poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
1881 
1882         if( poFDefn->GetType() == OFTInteger
1883             || poFDefn->GetType() == OFTInteger64
1884             || poFDefn->GetType() == OFTReal
1885             || poFDefn->GetType() == OFTDate
1886             || poFDefn->GetType() == OFTTime
1887             || poFDefn->GetType() == OFTDateTime)
1888             memcpy( psDstField, psSrcField, sizeof(OGRField) );
1889         else if( poFDefn->GetType() == OFTString )
1890         {
1891             if( poSrcFeat->IsFieldSetAndNotNull( psKeyDef->field_index ) )
1892                 psDstField->String = CPLStrdup( psSrcField->String );
1893             else
1894                 memcpy( psDstField, psSrcField, sizeof(OGRField) );
1895         }
1896     }
1897 }
1898 
1899 /************************************************************************/
1900 /*                         CreateOrderByIndex()                         */
1901 /*                                                                      */
1902 /*      This method is responsible for creating an index providing      */
1903 /*      ordered access to the features according to the supplied        */
1904 /*      ORDER BY clauses.                                               */
1905 /*                                                                      */
1906 /*      This is accomplished by making one pass through all the         */
1907 /*      eligible source features, and capturing the order by fields     */
1908 /*      of all records in memory.  A quick sort is then applied to      */
1909 /*      this in memory copy of the order-by fields to create the        */
1910 /*      required index.                                                 */
1911 /*                                                                      */
1912 /*      Keeping all the key values in memory will *not* scale up to     */
1913 /*      very large input datasets.                                      */
1914 /************************************************************************/
1915 
CreateOrderByIndex()1916 void OGRGenSQLResultsLayer::CreateOrderByIndex()
1917 
1918 {
1919     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
1920     const int nOrderItems = psSelectInfo->order_specs;
1921 
1922     if( ! (psSelectInfo->order_specs > 0
1923            && psSelectInfo->query_mode == SWQM_RECORDSET
1924            && nOrderItems != 0 ) )
1925         return;
1926 
1927     if( bOrderByValid )
1928         return;
1929 
1930     bOrderByValid = TRUE;
1931 
1932     ResetReading();
1933 
1934 /* -------------------------------------------------------------------- */
1935 /*      Optimize (memory-wise) ORDER BY ... LIMIT 1 [OFFSET 0] case.    */
1936 /* -------------------------------------------------------------------- */
1937     if( psSelectInfo->offset == 0 && psSelectInfo->limit == 1 )
1938     {
1939         OGRFeature* poSrcFeat = poSrcLayer->GetNextFeature();
1940         if( poSrcFeat == nullptr )
1941         {
1942             panFIDIndex = nullptr;
1943             nIndexSize = 0;
1944             return;
1945         }
1946 
1947         OGRField *pasCurrentFields = static_cast<OGRField *>(
1948                                     CPLCalloc(sizeof(OGRField), nOrderItems));
1949         OGRField *pasBestFields = static_cast<OGRField *>(
1950                                     CPLCalloc(sizeof(OGRField), nOrderItems));
1951         GIntBig nBestFID = poSrcFeat->GetFID();
1952         ReadIndexFields( poSrcFeat, nOrderItems, pasBestFields);
1953         delete poSrcFeat;
1954         while( (poSrcFeat = poSrcLayer->GetNextFeature()) != nullptr )
1955         {
1956             ReadIndexFields( poSrcFeat, nOrderItems, pasCurrentFields);
1957             if( Compare( pasCurrentFields, pasBestFields ) < 0 )
1958             {
1959                 nBestFID = poSrcFeat->GetFID();
1960                 FreeIndexFields( pasBestFields, 1, false);
1961                 memcpy( pasBestFields, pasCurrentFields,
1962                         sizeof(OGRField) * nOrderItems );
1963             }
1964             else
1965             {
1966                 FreeIndexFields( pasCurrentFields, 1, false);
1967             }
1968             memset( pasCurrentFields, 0, sizeof(OGRField) * nOrderItems );
1969             delete poSrcFeat;
1970         }
1971         VSIFree( pasCurrentFields );
1972         FreeIndexFields( pasBestFields, 1 );
1973         panFIDIndex = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
1974         panFIDIndex[0] = nBestFID;
1975         nIndexSize = 1;
1976         return;
1977     }
1978 
1979 /* -------------------------------------------------------------------- */
1980 /*      Allocate set of key values, and the output index.               */
1981 /* -------------------------------------------------------------------- */
1982     size_t nFeaturesAlloc = 100;
1983 
1984     panFIDIndex = nullptr;
1985     OGRField *pasIndexFields = static_cast<OGRField *>(
1986         CPLCalloc(sizeof(OGRField), nOrderItems * nFeaturesAlloc));
1987     GIntBig *panFIDList = static_cast<GIntBig *>(
1988         CPLMalloc(sizeof(GIntBig) * nFeaturesAlloc));
1989 
1990 /* -------------------------------------------------------------------- */
1991 /*      Read in all the key values.                                     */
1992 /* -------------------------------------------------------------------- */
1993     OGRFeature *poSrcFeat = nullptr;
1994     nIndexSize = 0;
1995 
1996     while( (poSrcFeat = poSrcLayer->GetNextFeature()) != nullptr )
1997     {
1998         if (nIndexSize == nFeaturesAlloc)
1999         {
2000             GUIntBig nNewFeaturesAlloc = static_cast<GUIntBig>(nFeaturesAlloc)
2001                                                         + nFeaturesAlloc / 3;
2002             if( static_cast<size_t>(nNewFeaturesAlloc) != nNewFeaturesAlloc ||
2003                 static_cast<size_t>(sizeof(OGRField) * nOrderItems *
2004                                     nNewFeaturesAlloc) !=
2005                 static_cast<GUIntBig>(sizeof(OGRField)) * nOrderItems *
2006                 nNewFeaturesAlloc )
2007             {
2008                 CPLError(CE_Failure, CPLE_AppDefined,
2009                          "Cannot allocate pasIndexFields");
2010                 FreeIndexFields( pasIndexFields, nIndexSize );
2011                 VSIFree(panFIDList);
2012                 nIndexSize = 0;
2013                 delete poSrcFeat;
2014                 return;
2015             }
2016             OGRField* pasNewIndexFields = static_cast<OGRField *>(
2017                 VSI_REALLOC_VERBOSE(pasIndexFields,
2018                            sizeof(OGRField) * nOrderItems *
2019                            static_cast<size_t>(nNewFeaturesAlloc)));
2020             if (pasNewIndexFields == nullptr)
2021             {
2022                 CPLError(CE_Failure, CPLE_AppDefined,
2023                          "Cannot allocate pasIndexFields");
2024                 FreeIndexFields( pasIndexFields, nIndexSize );
2025                 VSIFree(panFIDList);
2026                 nIndexSize = 0;
2027                 delete poSrcFeat;
2028                 return;
2029             }
2030             pasIndexFields = pasNewIndexFields;
2031 
2032             GIntBig* panNewFIDList = static_cast<GIntBig *>(
2033                 VSI_REALLOC_VERBOSE(panFIDList, sizeof(GIntBig) *
2034                                     static_cast<size_t>(nNewFeaturesAlloc)));
2035             if (panNewFIDList == nullptr)
2036             {
2037                 FreeIndexFields( pasIndexFields, nIndexSize );
2038                 VSIFree(panFIDList);
2039                 nIndexSize = 0;
2040                 delete poSrcFeat;
2041                 return;
2042             }
2043             panFIDList = panNewFIDList;
2044 
2045             memset(pasIndexFields + nFeaturesAlloc * nOrderItems, 0,
2046                    sizeof(OGRField) * nOrderItems *
2047                    static_cast<size_t>(nNewFeaturesAlloc - nFeaturesAlloc));
2048 
2049             nFeaturesAlloc = static_cast<size_t>(nNewFeaturesAlloc);
2050         }
2051 
2052         ReadIndexFields( poSrcFeat, nOrderItems,
2053                          pasIndexFields + nIndexSize * nOrderItems );
2054 
2055         panFIDList[nIndexSize] = poSrcFeat->GetFID();
2056         delete poSrcFeat;
2057 
2058         nIndexSize++;
2059     }
2060 
2061     //CPLDebug("GenSQL", "CreateOrderByIndex() = %d features", nIndexSize);
2062 
2063 /* -------------------------------------------------------------------- */
2064 /*      Initialize panFIDIndex                                          */
2065 /* -------------------------------------------------------------------- */
2066     panFIDIndex = static_cast<GIntBig *>(
2067         VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nIndexSize));
2068     if( panFIDIndex == nullptr )
2069     {
2070         FreeIndexFields( pasIndexFields, nIndexSize );
2071         VSIFree(panFIDList);
2072         nIndexSize = 0;
2073         return;
2074     }
2075     for( size_t i = 0; i < nIndexSize; i++ )
2076         panFIDIndex[i] = static_cast<GIntBig>(i);
2077 
2078 /* -------------------------------------------------------------------- */
2079 /*      Quick sort the records.                                         */
2080 /* -------------------------------------------------------------------- */
2081 
2082     GIntBig *panMerged = static_cast<GIntBig *>(
2083         VSI_MALLOC_VERBOSE( sizeof(GIntBig) * nIndexSize ));
2084     if( panMerged == nullptr )
2085     {
2086         FreeIndexFields( pasIndexFields, nIndexSize );
2087         VSIFree(panFIDList);
2088         nIndexSize = 0;
2089         VSIFree(panFIDIndex);
2090         panFIDIndex = nullptr;
2091         return;
2092     }
2093 
2094     SortIndexSection( pasIndexFields, panMerged, 0, nIndexSize );
2095     VSIFree( panMerged );
2096 
2097 /* -------------------------------------------------------------------- */
2098 /*      Rework the FID map to map to real FIDs.                         */
2099 /* -------------------------------------------------------------------- */
2100     bool bAlreadySorted = true;
2101     for( size_t i = 0; i < nIndexSize; i++ )
2102     {
2103         if (panFIDIndex[i] != static_cast<GIntBig>(i))
2104             bAlreadySorted = false;
2105         panFIDIndex[i] = panFIDList[panFIDIndex[i]];
2106     }
2107 
2108     CPLFree( panFIDList );
2109     FreeIndexFields( pasIndexFields, nIndexSize );
2110 
2111     /* If it is already sorted, then free than panFIDIndex array */
2112     /* so that GetNextFeature() can call a sequential GetNextFeature() */
2113     /* on the source array. Very useful for layers where random access */
2114     /* is slow. */
2115     /* Use case: the GML result of a WFS GetFeature with a SORTBY */
2116     if (bAlreadySorted)
2117     {
2118         CPLFree( panFIDIndex );
2119         panFIDIndex = nullptr;
2120 
2121         nIndexSize = 0;
2122     }
2123 
2124     ResetReading();
2125 }
2126 
2127 /************************************************************************/
2128 /*                          SortIndexSection()                          */
2129 /*                                                                      */
2130 /*      Sort the records in a section of the index.                     */
2131 /************************************************************************/
2132 
SortIndexSection(const OGRField * pasIndexFields,GIntBig * panMerged,size_t nStart,size_t nEntries)2133 void OGRGenSQLResultsLayer::SortIndexSection( const OGRField *pasIndexFields,
2134                                               GIntBig *panMerged,
2135                                               size_t nStart, size_t nEntries )
2136 
2137 {
2138     if( nEntries < 2 )
2139         return;
2140 
2141     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
2142     const int   nOrderItems = psSelectInfo->order_specs;
2143 
2144     size_t nFirstGroup = nEntries / 2;
2145     size_t nFirstStart = nStart;
2146     size_t nSecondGroup = nEntries - nFirstGroup;
2147     size_t nSecondStart = nStart + nFirstGroup;
2148 
2149     SortIndexSection( pasIndexFields, panMerged, nFirstStart,
2150                       nFirstGroup );
2151     SortIndexSection( pasIndexFields, panMerged, nSecondStart,
2152                       nSecondGroup );
2153 
2154     for( size_t iMerge = 0; iMerge < nEntries; ++iMerge )
2155     {
2156         int  nResult = 0;
2157 
2158         if( nFirstGroup == 0 )
2159             nResult = 1;
2160         else if( nSecondGroup == 0 )
2161             nResult = -1;
2162         else
2163             nResult = Compare( pasIndexFields
2164                                + panFIDIndex[nFirstStart] * nOrderItems,
2165                                pasIndexFields
2166                                + panFIDIndex[nSecondStart] * nOrderItems );
2167 
2168         if( nResult > 0 )
2169         {
2170             panMerged[iMerge] = panFIDIndex[nSecondStart];
2171             nSecondStart++;
2172             nSecondGroup--;
2173         }
2174         else
2175         {
2176             panMerged[iMerge] = panFIDIndex[nFirstStart];
2177             nFirstStart++;
2178             nFirstGroup--;
2179         }
2180     }
2181 
2182     /* Copy the merge list back into the main index */
2183     memcpy( panFIDIndex + nStart, panMerged, sizeof(GIntBig) * nEntries );
2184 }
2185 
2186 /************************************************************************/
2187 /*                           ComparePrimitive()                         */
2188 /************************************************************************/
2189 
ComparePrimitive(const T & a,const T & b)2190 template<class T> static inline int ComparePrimitive(const T& a, const T& b)
2191 {
2192     if( a < b )
2193         return -1;
2194     if( a > b )
2195         return 1;
2196     return 0;
2197 }
2198 
2199 /************************************************************************/
2200 /*                              Compare()                               */
2201 /************************************************************************/
2202 
Compare(const OGRField * pasFirstTuple,const OGRField * pasSecondTuple)2203 int OGRGenSQLResultsLayer::Compare( const OGRField *pasFirstTuple,
2204                                     const OGRField *pasSecondTuple )
2205 
2206 {
2207     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
2208     int  nResult = 0, iKey;
2209 
2210     for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
2211     {
2212         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2213         OGRFieldDefn *poFDefn = nullptr;
2214 
2215         if( psKeyDef->field_index >= iFIDFieldIndex )
2216             poFDefn = nullptr;
2217         else
2218             poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
2219                 psKeyDef->field_index );
2220 
2221         if( OGR_RawField_IsUnset(&pasFirstTuple[iKey]) ||
2222             OGR_RawField_IsNull(&pasFirstTuple[iKey]) )
2223         {
2224             if( OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2225                 OGR_RawField_IsNull(&pasSecondTuple[iKey]) )
2226                 nResult = 0;
2227             else
2228                 nResult = -1;
2229         }
2230         else if ( OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2231                   OGR_RawField_IsNull(&pasSecondTuple[iKey]) )
2232         {
2233             nResult = 1;
2234         }
2235         else if ( poFDefn == nullptr )
2236         {
2237             CPLAssert( psKeyDef->field_index <
2238                                     iFIDFieldIndex + SPECIAL_FIELD_COUNT );
2239             switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
2240             {
2241               case SWQ_INTEGER:
2242                   // Yes, read Integer in Integer64.
2243                   // This is consistent with what is done ReadIndexFields()
2244               case SWQ_INTEGER64:
2245                 nResult = ComparePrimitive( pasFirstTuple[iKey].Integer64,
2246                                             pasSecondTuple[iKey].Integer64 );
2247                 break;
2248               case SWQ_FLOAT:
2249                 nResult = ComparePrimitive( pasFirstTuple[iKey].Real,
2250                                             pasSecondTuple[iKey].Real );
2251                 break;
2252               case SWQ_STRING:
2253                 nResult = strcmp(pasFirstTuple[iKey].String,
2254                                  pasSecondTuple[iKey].String);
2255                 break;
2256 
2257               default:
2258                 CPLAssert( false );
2259                 nResult = 0;
2260             }
2261         }
2262         else if( poFDefn->GetType() == OFTInteger )
2263         {
2264             nResult = ComparePrimitive( pasFirstTuple[iKey].Integer,
2265                                         pasSecondTuple[iKey].Integer );
2266         }
2267         else if( poFDefn->GetType() == OFTInteger64 )
2268         {
2269             nResult = ComparePrimitive( pasFirstTuple[iKey].Integer64,
2270                                         pasSecondTuple[iKey].Integer64 );
2271         }
2272         else if( poFDefn->GetType() == OFTString )
2273         {
2274             nResult = strcmp(pasFirstTuple[iKey].String,
2275                              pasSecondTuple[iKey].String);
2276         }
2277         else if( poFDefn->GetType() == OFTReal )
2278         {
2279             nResult = ComparePrimitive( pasFirstTuple[iKey].Real,
2280                                         pasSecondTuple[iKey].Real );
2281         }
2282         else if( poFDefn->GetType() == OFTDate ||
2283                  poFDefn->GetType() == OFTTime ||
2284                  poFDefn->GetType() == OFTDateTime)
2285         {
2286             nResult = OGRCompareDate(&pasFirstTuple[iKey],
2287                                      &pasSecondTuple[iKey]);
2288         }
2289 
2290         if( !(psKeyDef->ascending_flag) )
2291             nResult *= -1;
2292     }
2293 
2294     return nResult;
2295 }
2296 
2297 /************************************************************************/
2298 /*                         AddFieldDefnToSet()                          */
2299 /************************************************************************/
2300 
AddFieldDefnToSet(int iTable,int iColumn,CPLHashSet * hSet)2301 void OGRGenSQLResultsLayer::AddFieldDefnToSet(int iTable, int iColumn,
2302                                               CPLHashSet* hSet)
2303 {
2304     if (iTable != -1 && iColumn != -1)
2305     {
2306         OGRLayer* poLayer = papoTableLayers[iTable];
2307         if (iColumn < poLayer->GetLayerDefn()->GetFieldCount())
2308         {
2309             OGRFieldDefn* poFDefn =
2310                 poLayer->GetLayerDefn()->GetFieldDefn(iColumn);
2311             CPLHashSetInsert(hSet, poFDefn);
2312         }
2313     }
2314 }
2315 
2316 /************************************************************************/
2317 /*                   ExploreExprForIgnoredFields()                      */
2318 /************************************************************************/
2319 
ExploreExprForIgnoredFields(swq_expr_node * expr,CPLHashSet * hSet)2320 void OGRGenSQLResultsLayer::ExploreExprForIgnoredFields(swq_expr_node* expr,
2321                                                         CPLHashSet* hSet)
2322 {
2323     if (expr->eNodeType == SNT_COLUMN)
2324     {
2325         AddFieldDefnToSet(expr->table_index, expr->field_index, hSet);
2326     }
2327     else if (expr->eNodeType == SNT_OPERATION)
2328     {
2329         for( int i = 0; i < expr->nSubExprCount; i++ )
2330             ExploreExprForIgnoredFields(expr->papoSubExpr[i], hSet);
2331     }
2332 }
2333 
2334 /************************************************************************/
2335 /*                     FindAndSetIgnoredFields()                        */
2336 /************************************************************************/
2337 
FindAndSetIgnoredFields()2338 void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
2339 {
2340     swq_select *psSelectInfo = static_cast<swq_select*>(pSelectInfo);
2341     CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashPointer,
2342                                      CPLHashSetEqualPointer,
2343                                      nullptr);
2344 
2345 /* -------------------------------------------------------------------- */
2346 /*      1st phase : explore the whole select infos to determine which   */
2347 /*      source fields are used                                          */
2348 /* -------------------------------------------------------------------- */
2349     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
2350     {
2351         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
2352         AddFieldDefnToSet(psColDef->table_index, psColDef->field_index, hSet);
2353         if (psColDef->expr)
2354             ExploreExprForIgnoredFields(psColDef->expr, hSet);
2355     }
2356 
2357     if (psSelectInfo->where_expr)
2358         ExploreExprForIgnoredFields(psSelectInfo->where_expr, hSet);
2359 
2360     for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
2361     {
2362         swq_join_def *psJoinDef = psSelectInfo->join_defs + iJoin;
2363         ExploreExprForIgnoredFields(psJoinDef->poExpr, hSet);
2364     }
2365 
2366     for( int iOrder = 0; iOrder < psSelectInfo->order_specs; iOrder++ )
2367     {
2368         swq_order_def *psOrderDef = psSelectInfo->order_defs + iOrder;
2369         AddFieldDefnToSet(psOrderDef->table_index, psOrderDef->field_index, hSet);
2370     }
2371 
2372 /* -------------------------------------------------------------------- */
2373 /*      2nd phase : now, we can exclude the unused fields               */
2374 /* -------------------------------------------------------------------- */
2375     for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
2376     {
2377         OGRLayer* poLayer = papoTableLayers[iTable];
2378         OGRFeatureDefn *poSrcFDefn = poLayer->GetLayerDefn();
2379         char** papszIgnoredFields = nullptr;
2380         for( int iSrcField = 0;
2381              iSrcField<poSrcFDefn->GetFieldCount();
2382              iSrcField++ )
2383         {
2384             OGRFieldDefn* poFDefn = poSrcFDefn->GetFieldDefn(iSrcField);
2385             if (CPLHashSetLookup(hSet,poFDefn) == nullptr)
2386             {
2387                 papszIgnoredFields = CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
2388                 //CPLDebug("OGR", "Adding %s to the list of ignored fields of layer %s",
2389                 //         poFDefn->GetNameRef(), poLayer->GetName());
2390             }
2391         }
2392         poLayer->SetIgnoredFields(const_cast<const char**>(papszIgnoredFields));
2393         CSLDestroy(papszIgnoredFields);
2394     }
2395 
2396     CPLHashSetDestroy(hSet);
2397 }
2398 
2399 /************************************************************************/
2400 /*                       InvalidateOrderByIndex()                       */
2401 /************************************************************************/
2402 
InvalidateOrderByIndex()2403 void OGRGenSQLResultsLayer::InvalidateOrderByIndex()
2404 {
2405     CPLFree( panFIDIndex );
2406     panFIDIndex = nullptr;
2407 
2408     nIndexSize = 0;
2409     bOrderByValid = FALSE;
2410 }
2411 
2412 /************************************************************************/
2413 /*                       SetAttributeFilter()                           */
2414 /************************************************************************/
2415 
SetAttributeFilter(const char * pszAttributeFilter)2416 OGRErr OGRGenSQLResultsLayer::SetAttributeFilter( const char* pszAttributeFilter )
2417 {
2418     InvalidateOrderByIndex();
2419     return OGRLayer::SetAttributeFilter(pszAttributeFilter);
2420 }
2421 
2422 /************************************************************************/
2423 /*                       SetSpatialFilter()                             */
2424 /************************************************************************/
2425 
SetSpatialFilter(int iGeomField,OGRGeometry * poGeom)2426 void OGRGenSQLResultsLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeom )
2427 {
2428     InvalidateOrderByIndex();
2429     if( iGeomField == 0 )
2430         OGRLayer::SetSpatialFilter(poGeom);
2431     else
2432         OGRLayer::SetSpatialFilter(iGeomField, poGeom);
2433 }
2434 
2435 //! @endcond
2436