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