Line data Source code
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 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "ogr_swq.h"
15 : #include "ogr_p.h"
16 : #include "ogr_gensql.h"
17 : #include "cpl_string.h"
18 : #include "ogr_api.h"
19 : #include "ogr_recordbatch.h"
20 : #include "ogrlayerarrow.h"
21 : #include "cpl_time.h"
22 : #include <algorithm>
23 : #include <limits>
24 : #include <map>
25 : #include <set>
26 : #include <vector>
27 :
28 : //! @cond Doxygen_Suppress
29 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
30 :
31 : class OGRGenSQLGeomFieldDefn final : public OGRGeomFieldDefn
32 : {
33 : public:
34 1509 : explicit OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn *poGeomFieldDefn)
35 1509 : : OGRGeomFieldDefn(poGeomFieldDefn->GetNameRef(),
36 : poGeomFieldDefn->GetType()),
37 1509 : bForceGeomType(FALSE)
38 : {
39 1509 : SetSpatialRef(poGeomFieldDefn->GetSpatialRef());
40 1509 : }
41 :
42 : int bForceGeomType;
43 : };
44 :
45 : /************************************************************************/
46 : /* OGRGenSQLResultsLayerHasSpecialField() */
47 : /************************************************************************/
48 :
49 11 : static bool OGRGenSQLResultsLayerHasSpecialField(swq_expr_node *expr,
50 : int nMinIndexForSpecialField)
51 : {
52 11 : if (expr->eNodeType == SNT_COLUMN)
53 : {
54 5 : if (expr->table_index == 0)
55 : {
56 9 : return expr->field_index >= nMinIndexForSpecialField &&
57 4 : expr->field_index <
58 9 : nMinIndexForSpecialField + SPECIAL_FIELD_COUNT;
59 : }
60 : }
61 6 : else if (expr->eNodeType == SNT_OPERATION)
62 : {
63 7 : for (int i = 0; i < expr->nSubExprCount; i++)
64 : {
65 6 : if (OGRGenSQLResultsLayerHasSpecialField(expr->papoSubExpr[i],
66 : nMinIndexForSpecialField))
67 4 : return true;
68 : }
69 : }
70 2 : return false;
71 : }
72 :
73 : /************************************************************************/
74 : /* OGRGenSQLResultsLayer() */
75 : /************************************************************************/
76 :
77 2155 : OGRGenSQLResultsLayer::OGRGenSQLResultsLayer(
78 : GDALDataset *poSrcDSIn, std::unique_ptr<swq_select> &&pSelectInfo,
79 : const OGRGeometry *poSpatFilter, const char *pszWHEREIn,
80 2155 : const char *pszDialect)
81 2155 : : m_poSrcDS(poSrcDSIn), m_pSelectInfo(std::move(pSelectInfo))
82 : {
83 2155 : swq_select *psSelectInfo = m_pSelectInfo.get();
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Identify all the layers involved in the SELECT. */
87 : /* -------------------------------------------------------------------- */
88 2155 : m_apoTableLayers.reserve(psSelectInfo->table_count);
89 :
90 4340 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
91 : {
92 2185 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
93 2185 : GDALDataset *poTableDS = m_poSrcDS;
94 :
95 2185 : if (psTableDef->data_source != nullptr)
96 : {
97 : std::unique_ptr<GDALDataset, GDALDatasetUniquePtrReleaser> poNewDS(
98 6 : GDALDataset::Open(psTableDef->data_source,
99 6 : GDAL_OF_VECTOR | GDAL_OF_SHARED));
100 6 : if (!poNewDS)
101 : {
102 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
103 0 : CPLError(CE_Failure, CPLE_AppDefined,
104 : "Unable to open secondary datasource\n"
105 : "`%s' required by JOIN.",
106 : psTableDef->data_source);
107 0 : return;
108 : }
109 :
110 6 : m_apoExtraDS.emplace_back(std::move(poNewDS));
111 6 : poTableDS = m_apoExtraDS.back().get();
112 : }
113 :
114 4370 : m_apoTableLayers.push_back(
115 2185 : poTableDS->GetLayerByName(psTableDef->table_name));
116 2185 : if (!m_apoTableLayers.back())
117 0 : return;
118 : }
119 :
120 2155 : m_poSrcLayer = m_apoTableLayers[0];
121 2155 : SetMetadata(m_poSrcLayer->GetMetadata("NATIVE_DATA"), "NATIVE_DATA");
122 :
123 : /* -------------------------------------------------------------------- */
124 : /* If the user has explicitly requested a OGRSQL dialect, then */
125 : /* we should avoid to forward the where clause to the source layer */
126 : /* when there is a risk it cannot understand it (#4022) */
127 : /* -------------------------------------------------------------------- */
128 2155 : m_bForwardWhereToSourceLayer = true;
129 2155 : if (pszWHEREIn)
130 : {
131 946 : if (psSelectInfo->where_expr && pszDialect != nullptr &&
132 274 : EQUAL(pszDialect, "OGRSQL"))
133 : {
134 : const int nMinIndexForSpecialField =
135 5 : m_poSrcLayer->GetLayerDefn()->GetFieldCount();
136 5 : m_bForwardWhereToSourceLayer =
137 5 : !OGRGenSQLResultsLayerHasSpecialField(psSelectInfo->where_expr,
138 : nMinIndexForSpecialField);
139 : }
140 946 : m_osInitialWHERE = pszWHEREIn;
141 : }
142 :
143 : /* -------------------------------------------------------------------- */
144 : /* Prepare a feature definition based on the query. */
145 : /* -------------------------------------------------------------------- */
146 2155 : OGRFeatureDefn *poSrcDefn = m_poSrcLayer->GetLayerDefn();
147 :
148 2155 : m_poDefn = new OGRFeatureDefn(psSelectInfo->table_defs[0].table_alias);
149 2155 : SetDescription(m_poDefn->GetName());
150 2155 : m_poDefn->SetGeomType(wkbNone);
151 2155 : m_poDefn->Reference();
152 :
153 2155 : m_iFIDFieldIndex = poSrcDefn->GetFieldCount();
154 :
155 16988 : for (std::size_t iField = 0; iField < psSelectInfo->column_defs.size();
156 : iField++)
157 : {
158 14833 : swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
159 14833 : OGRFieldDefn oFDefn("", OFTInteger);
160 14833 : OGRGeomFieldDefn oGFDefn("", wkbUnknown);
161 14833 : OGRFieldDefn *poSrcFDefn = nullptr;
162 14833 : OGRGeomFieldDefn *poSrcGFDefn = nullptr;
163 14833 : int bIsGeometry = FALSE;
164 14833 : OGRFeatureDefn *poLayerDefn = nullptr;
165 14833 : int iSrcGeomField = -1;
166 :
167 14833 : if (psColDef->bHidden)
168 7 : continue;
169 :
170 14826 : if (psColDef->table_index != -1)
171 : poLayerDefn =
172 14541 : m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
173 :
174 29057 : if (psColDef->field_index > -1 && poLayerDefn != nullptr &&
175 14231 : psColDef->field_index < poLayerDefn->GetFieldCount())
176 : {
177 13003 : poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
178 : }
179 :
180 29367 : if (poLayerDefn != nullptr &&
181 14541 : IS_GEOM_FIELD_INDEX(poLayerDefn, psColDef->field_index))
182 : {
183 1211 : bIsGeometry = TRUE;
184 1211 : iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
185 : poLayerDefn, psColDef->field_index);
186 1211 : poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
187 : }
188 :
189 14826 : if (psColDef->target_type == SWQ_GEOMETRY)
190 12 : bIsGeometry = TRUE;
191 :
192 14826 : if (psColDef->col_func == SWQCF_COUNT)
193 327 : bIsGeometry = FALSE;
194 :
195 14826 : if (strlen(psColDef->field_name) == 0 && !bIsGeometry)
196 : {
197 271 : CPLFree(psColDef->field_name);
198 271 : psColDef->field_name = static_cast<char *>(CPLMalloc(40));
199 271 : snprintf(psColDef->field_name, 40, "FIELD_%d",
200 271 : m_poDefn->GetFieldCount() + 1);
201 : }
202 :
203 14826 : if (psColDef->field_alias != nullptr)
204 : {
205 13008 : if (bIsGeometry)
206 1205 : oGFDefn.SetName(psColDef->field_alias);
207 : else
208 11803 : oFDefn.SetName(psColDef->field_alias);
209 : }
210 1818 : else if (psColDef->col_func != SWQCF_NONE)
211 : {
212 758 : const swq_operation *op = swq_op_registrar::GetOperator(
213 379 : static_cast<swq_op>(psColDef->col_func));
214 :
215 379 : oFDefn.SetName(
216 379 : CPLSPrintf("%s_%s", op->pszName, psColDef->field_name));
217 : }
218 : else
219 : {
220 2878 : CPLString osName;
221 1439 : if (psColDef->table_name[0])
222 : {
223 60 : osName = psColDef->table_name;
224 60 : osName += ".";
225 : }
226 1439 : osName += psColDef->field_name;
227 :
228 1439 : if (bIsGeometry)
229 17 : oGFDefn.SetName(osName);
230 : else
231 1422 : oFDefn.SetName(osName);
232 : }
233 :
234 14826 : if (psColDef->col_func == SWQCF_COUNT)
235 327 : oFDefn.SetType(OFTInteger64);
236 14499 : else if (poSrcFDefn != nullptr)
237 : {
238 12988 : if (psColDef->col_func == SWQCF_STDDEV_POP ||
239 12985 : psColDef->col_func == SWQCF_STDDEV_SAMP)
240 : {
241 5 : oFDefn.SetType(OFTReal);
242 : }
243 12983 : else if (psColDef->col_func != SWQCF_AVG ||
244 6 : psColDef->field_type == SWQ_DATE ||
245 6 : psColDef->field_type == SWQ_TIME ||
246 6 : psColDef->field_type == SWQ_TIMESTAMP)
247 : {
248 12978 : oFDefn.SetType(poSrcFDefn->GetType());
249 12978 : if (psColDef->col_func == SWQCF_NONE ||
250 42 : psColDef->col_func == SWQCF_MIN ||
251 24 : psColDef->col_func == SWQCF_MAX)
252 : {
253 12968 : oFDefn.SetSubType(poSrcFDefn->GetSubType());
254 : }
255 : }
256 : else
257 : {
258 5 : oFDefn.SetType(OFTReal);
259 : }
260 :
261 12988 : if (psColDef->col_func != SWQCF_AVG &&
262 12982 : psColDef->col_func != SWQCF_STDDEV_POP &&
263 12979 : psColDef->col_func != SWQCF_STDDEV_SAMP &&
264 12977 : psColDef->col_func != SWQCF_SUM)
265 : {
266 12968 : oFDefn.SetWidth(poSrcFDefn->GetWidth());
267 12968 : oFDefn.SetPrecision(poSrcFDefn->GetPrecision());
268 : }
269 :
270 12988 : if (psColDef->col_func == SWQCF_NONE)
271 12936 : oFDefn.SetDomainName(poSrcFDefn->GetDomainName());
272 : }
273 1511 : else if (poSrcGFDefn != nullptr)
274 : {
275 1210 : oGFDefn.SetType(poSrcGFDefn->GetType());
276 1210 : oGFDefn.SetSpatialRef(poSrcGFDefn->GetSpatialRef());
277 : }
278 301 : else if (psColDef->field_index >= m_iFIDFieldIndex)
279 : {
280 16 : switch (SpecialFieldTypes[psColDef->field_index - m_iFIDFieldIndex])
281 : {
282 9 : case SWQ_INTEGER:
283 9 : oFDefn.SetType(OFTInteger);
284 9 : break;
285 0 : case SWQ_INTEGER64:
286 0 : oFDefn.SetType(OFTInteger64);
287 0 : break;
288 2 : case SWQ_FLOAT:
289 2 : oFDefn.SetType(OFTReal);
290 2 : break;
291 5 : default:
292 5 : oFDefn.SetType(OFTString);
293 5 : break;
294 : }
295 41 : if (psColDef->field_index - m_iFIDFieldIndex == SPF_FID &&
296 17 : m_poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
297 1 : EQUAL(m_poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
298 : {
299 1 : oFDefn.SetType(OFTInteger64);
300 : }
301 : }
302 : else
303 : {
304 285 : switch (psColDef->field_type)
305 : {
306 23 : case SWQ_INTEGER:
307 23 : oFDefn.SetType(OFTInteger);
308 23 : break;
309 :
310 40 : case SWQ_INTEGER64:
311 40 : oFDefn.SetType(OFTInteger64);
312 40 : break;
313 :
314 126 : case SWQ_BOOLEAN:
315 126 : oFDefn.SetType(OFTInteger);
316 126 : oFDefn.SetSubType(OFSTBoolean);
317 126 : break;
318 :
319 39 : case SWQ_FLOAT:
320 39 : oFDefn.SetType(OFTReal);
321 39 : break;
322 :
323 57 : default:
324 57 : oFDefn.SetType(OFTString);
325 57 : break;
326 : }
327 : }
328 :
329 : /* setting up the target_type */
330 14826 : switch (psColDef->target_type)
331 : {
332 14802 : case SWQ_OTHER:
333 14802 : break;
334 3 : case SWQ_INTEGER:
335 3 : oFDefn.SetType(OFTInteger);
336 3 : break;
337 4 : case SWQ_INTEGER64:
338 4 : oFDefn.SetType(OFTInteger64);
339 4 : break;
340 1 : case SWQ_BOOLEAN:
341 1 : oFDefn.SetType(OFTInteger);
342 1 : oFDefn.SetSubType(OFSTBoolean);
343 1 : break;
344 3 : case SWQ_FLOAT:
345 3 : oFDefn.SetType(OFTReal);
346 3 : break;
347 1 : case SWQ_STRING:
348 1 : oFDefn.SetType(OFTString);
349 1 : break;
350 0 : case SWQ_TIMESTAMP:
351 0 : oFDefn.SetType(OFTDateTime);
352 0 : break;
353 0 : case SWQ_DATE:
354 0 : oFDefn.SetType(OFTDate);
355 0 : break;
356 0 : case SWQ_TIME:
357 0 : oFDefn.SetType(OFTTime);
358 0 : break;
359 12 : case SWQ_GEOMETRY:
360 12 : break;
361 :
362 0 : default:
363 0 : CPLAssert(false);
364 : oFDefn.SetType(OFTString);
365 : break;
366 : }
367 14826 : if (psColDef->target_subtype != OFSTNone)
368 1 : oFDefn.SetSubType(psColDef->target_subtype);
369 :
370 14826 : if (psColDef->field_length > 0)
371 : {
372 3 : oFDefn.SetWidth(psColDef->field_length);
373 : }
374 :
375 14826 : if (psColDef->field_precision >= 0)
376 : {
377 2 : oFDefn.SetPrecision(psColDef->field_precision);
378 : }
379 :
380 14826 : if (bIsGeometry)
381 : {
382 1222 : m_anGeomFieldToSrcGeomField.push_back(iSrcGeomField);
383 : /* Hack while drivers haven't been updated so that */
384 : /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() ==
385 : * m_poSrcLayer->GetSpatialRef() */
386 2330 : if (iSrcGeomField == 0 && poSrcDefn->GetGeomFieldCount() == 1 &&
387 1108 : oGFDefn.GetSpatialRef() == nullptr)
388 : {
389 252 : oGFDefn.SetSpatialRef(m_poSrcLayer->GetSpatialRef());
390 : }
391 1222 : int bForceGeomType = FALSE;
392 1222 : if (psColDef->eGeomType != wkbUnknown)
393 : {
394 6 : oGFDefn.SetType(psColDef->eGeomType);
395 6 : bForceGeomType = TRUE;
396 : }
397 1222 : if (psColDef->nSRID > 0)
398 : {
399 1 : OGRSpatialReference *poSRS = new OGRSpatialReference();
400 1 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
401 1 : if (poSRS->importFromEPSG(psColDef->nSRID) == OGRERR_NONE)
402 : {
403 1 : oGFDefn.SetSpatialRef(poSRS);
404 : }
405 1 : poSRS->Release();
406 : }
407 :
408 : auto poMyGeomFieldDefn =
409 1222 : std::make_unique<OGRGenSQLGeomFieldDefn>(&oGFDefn);
410 1222 : poMyGeomFieldDefn->bForceGeomType = bForceGeomType;
411 1222 : m_poDefn->AddGeomFieldDefn(std::move(poMyGeomFieldDefn));
412 : }
413 : else
414 13604 : m_poDefn->AddFieldDefn(&oFDefn);
415 : }
416 :
417 : /* -------------------------------------------------------------------- */
418 : /* Add implicit geometry field. */
419 : /* -------------------------------------------------------------------- */
420 6095 : if (psSelectInfo->query_mode == SWQM_RECORDSET &&
421 1785 : m_poDefn->GetGeomFieldCount() == 0 &&
422 3940 : poSrcDefn->GetGeomFieldCount() == 1 && !psSelectInfo->bExcludedGeometry)
423 : {
424 287 : psSelectInfo->column_defs.emplace_back();
425 :
426 287 : swq_col_def *col_def = &psSelectInfo->column_defs.back();
427 :
428 287 : memset(col_def, 0, sizeof(swq_col_def));
429 287 : const char *pszName = poSrcDefn->GetGeomFieldDefn(0)->GetNameRef();
430 287 : if (*pszName != '\0')
431 11 : col_def->field_name = CPLStrdup(pszName);
432 : else
433 276 : col_def->field_name =
434 276 : CPLStrdup(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
435 287 : col_def->field_alias = nullptr;
436 287 : col_def->table_index = 0;
437 287 : col_def->field_index =
438 287 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poSrcDefn, 0);
439 287 : col_def->field_type = SWQ_GEOMETRY;
440 287 : col_def->target_type = SWQ_GEOMETRY;
441 :
442 287 : m_anGeomFieldToSrcGeomField.push_back(0);
443 :
444 287 : m_poDefn->AddGeomFieldDefn(std::make_unique<OGRGenSQLGeomFieldDefn>(
445 287 : poSrcDefn->GetGeomFieldDefn(0)));
446 :
447 : /* Hack while drivers haven't been updated so that */
448 : /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() ==
449 : * m_poSrcLayer->GetSpatialRef() */
450 287 : if (poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == nullptr)
451 : {
452 68 : m_poDefn->GetGeomFieldDefn(0)->SetSpatialRef(
453 68 : m_poSrcLayer->GetSpatialRef());
454 : }
455 : }
456 :
457 : /* -------------------------------------------------------------------- */
458 : /* Now that we have m_poSrcLayer, we can install a spatial filter */
459 : /* if there is one. */
460 : /* -------------------------------------------------------------------- */
461 2155 : if (poSpatFilter)
462 301 : OGRGenSQLResultsLayer::SetSpatialFilter(
463 : 0, const_cast<OGRGeometry *>(poSpatFilter));
464 :
465 2155 : OGRGenSQLResultsLayer::ResetReading();
466 :
467 2155 : FindAndSetIgnoredFields();
468 :
469 2155 : if (!m_bForwardWhereToSourceLayer)
470 4 : OGRLayer::SetAttributeFilter(m_osInitialWHERE.c_str());
471 : }
472 :
473 : /************************************************************************/
474 : /* ~OGRGenSQLResultsLayer() */
475 : /************************************************************************/
476 :
477 4306 : OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
478 :
479 : {
480 2153 : if (m_nFeaturesRead > 0 && m_poDefn != nullptr)
481 : {
482 974 : CPLDebug("GenSQL", CPL_FRMT_GIB " features read on layer '%s'.",
483 974 : m_nFeaturesRead, m_poDefn->GetName());
484 : }
485 :
486 2153 : OGRGenSQLResultsLayer::ClearFilters();
487 :
488 2153 : if (m_poDefn != nullptr)
489 : {
490 2153 : m_poDefn->Release();
491 : }
492 4306 : }
493 :
494 : /************************************************************************/
495 : /* ClearFilters() */
496 : /* */
497 : /* Clear up all filters currently in place on the target layer, */
498 : /* and joined layers. We try not to leave them installed */
499 : /* except when actively fetching features. */
500 : /************************************************************************/
501 :
502 2211 : void OGRGenSQLResultsLayer::ClearFilters()
503 :
504 : {
505 : /* -------------------------------------------------------------------- */
506 : /* Clear any filters installed on the target layer. */
507 : /* -------------------------------------------------------------------- */
508 2211 : if (m_poSrcLayer != nullptr)
509 : {
510 2211 : m_poSrcLayer->ResetReading();
511 2211 : m_poSrcLayer->SetAttributeFilter("");
512 2211 : m_poSrcLayer->SetSpatialFilter(nullptr);
513 : }
514 :
515 : /* -------------------------------------------------------------------- */
516 : /* Clear any attribute filter installed on the joined layers. */
517 : /* -------------------------------------------------------------------- */
518 2211 : swq_select *psSelectInfo = m_pSelectInfo.get();
519 :
520 2211 : if (psSelectInfo != nullptr)
521 : {
522 2241 : for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
523 : {
524 30 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
525 : OGRLayer *poJoinLayer =
526 30 : m_apoTableLayers[psJoinInfo->secondary_table];
527 :
528 30 : poJoinLayer->SetAttributeFilter("");
529 : }
530 : }
531 :
532 : /* -------------------------------------------------------------------- */
533 : /* Clear any ignored field lists installed on source layers */
534 : /* -------------------------------------------------------------------- */
535 2211 : if (psSelectInfo != nullptr)
536 : {
537 4452 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
538 : {
539 2241 : OGRLayer *poLayer = m_apoTableLayers[iTable];
540 2241 : poLayer->SetIgnoredFields(nullptr);
541 : }
542 : }
543 2211 : }
544 :
545 : /************************************************************************/
546 : /* MustEvaluateSpatialFilterOnGenSQL() */
547 : /************************************************************************/
548 :
549 3698 : int OGRGenSQLResultsLayer::MustEvaluateSpatialFilterOnGenSQL()
550 : {
551 3698 : int bEvaluateSpatialFilter = FALSE;
552 3992 : if (m_poFilterGeom != nullptr && m_iGeomFieldFilter >= 0 &&
553 294 : m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
554 : {
555 294 : int iSrcGeomField = m_anGeomFieldToSrcGeomField[m_iGeomFieldFilter];
556 294 : if (iSrcGeomField < 0)
557 0 : bEvaluateSpatialFilter = TRUE;
558 : }
559 3698 : return bEvaluateSpatialFilter;
560 : }
561 :
562 : /************************************************************************/
563 : /* ApplyFiltersToSource() */
564 : /************************************************************************/
565 :
566 3206 : void OGRGenSQLResultsLayer::ApplyFiltersToSource()
567 : {
568 3206 : if (m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty())
569 : {
570 1200 : m_poSrcLayer->SetAttributeFilter(m_osInitialWHERE.c_str());
571 : }
572 : else
573 : {
574 2006 : m_poSrcLayer->SetAttributeFilter(nullptr);
575 : }
576 6412 : if (m_iGeomFieldFilter >= 0 &&
577 3206 : m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
578 : {
579 2323 : int iSrcGeomField = m_anGeomFieldToSrcGeomField[m_iGeomFieldFilter];
580 2323 : if (iSrcGeomField >= 0)
581 2313 : m_poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
582 : }
583 :
584 3206 : m_poSrcLayer->ResetReading();
585 3206 : }
586 :
587 : /************************************************************************/
588 : /* ResetReading() */
589 : /************************************************************************/
590 :
591 3213 : void OGRGenSQLResultsLayer::ResetReading()
592 :
593 : {
594 3213 : swq_select *psSelectInfo = m_pSelectInfo.get();
595 :
596 3213 : if (psSelectInfo->query_mode == SWQM_RECORDSET)
597 : {
598 2842 : ApplyFiltersToSource();
599 : }
600 :
601 3213 : m_nNextIndexFID = psSelectInfo->offset;
602 3213 : m_nIteratedFeatures = -1;
603 3213 : m_bEOF = false;
604 3213 : }
605 :
606 : /************************************************************************/
607 : /* SetNextByIndex() */
608 : /* */
609 : /* If we already have an FID list, we can easily reposition */
610 : /* ourselves in it. */
611 : /************************************************************************/
612 :
613 13 : OGRErr OGRGenSQLResultsLayer::SetNextByIndex(GIntBig nIndex)
614 :
615 : {
616 13 : if (nIndex < 0)
617 1 : return OGRERR_FAILURE;
618 :
619 12 : swq_select *psSelectInfo = m_pSelectInfo.get();
620 :
621 12 : if (psSelectInfo->limit >= 0)
622 : {
623 7 : m_nIteratedFeatures = nIndex;
624 7 : if (m_nIteratedFeatures >= psSelectInfo->limit)
625 : {
626 3 : return OGRERR_FAILURE;
627 : }
628 : }
629 :
630 9 : CreateOrderByIndex();
631 :
632 9 : if (nIndex > std::numeric_limits<GIntBig>::max() - psSelectInfo->offset)
633 : {
634 1 : m_bEOF = true;
635 1 : return OGRERR_FAILURE;
636 : }
637 24 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD ||
638 8 : psSelectInfo->query_mode == SWQM_DISTINCT_LIST || !m_anFIDIndex.empty())
639 : {
640 0 : m_nNextIndexFID = nIndex + psSelectInfo->offset;
641 0 : return OGRERR_NONE;
642 : }
643 : else
644 : {
645 : OGRErr eErr =
646 8 : m_poSrcLayer->SetNextByIndex(nIndex + psSelectInfo->offset);
647 8 : if (eErr != OGRERR_NONE)
648 1 : m_bEOF = true;
649 8 : return eErr;
650 : }
651 : }
652 :
653 : /************************************************************************/
654 : /* GetExtent() */
655 : /************************************************************************/
656 :
657 12 : OGRErr OGRGenSQLResultsLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
658 : int bForce)
659 :
660 : {
661 12 : swq_select *psSelectInfo = m_pSelectInfo.get();
662 :
663 21 : if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
664 9 : GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone)
665 : {
666 3 : if (iGeomField != 0)
667 : {
668 3 : CPLError(CE_Failure, CPLE_AppDefined,
669 : "Invalid geometry field index : %d", iGeomField);
670 : }
671 3 : return OGRERR_FAILURE;
672 : }
673 :
674 9 : if (psSelectInfo->query_mode == SWQM_RECORDSET)
675 : {
676 9 : int iSrcGeomField = m_anGeomFieldToSrcGeomField[iGeomField];
677 9 : if (iSrcGeomField >= 0)
678 9 : return m_poSrcLayer->GetExtent(iSrcGeomField, psExtent, bForce);
679 0 : else if (iGeomField == 0)
680 0 : return OGRLayer::GetExtent(psExtent, bForce);
681 : else
682 0 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
683 : }
684 : else
685 0 : return OGRERR_FAILURE;
686 : }
687 :
688 : /************************************************************************/
689 : /* GetFeatureCount() */
690 : /************************************************************************/
691 :
692 180 : GIntBig OGRGenSQLResultsLayer::GetFeatureCount(int bForce)
693 :
694 : {
695 180 : swq_select *psSelectInfo = m_pSelectInfo.get();
696 :
697 180 : CreateOrderByIndex();
698 :
699 180 : GIntBig nRet = 0;
700 180 : if (psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
701 : {
702 3 : if (!PrepareSummary())
703 0 : return 0;
704 :
705 3 : if (psSelectInfo->column_summary.empty())
706 0 : return 0;
707 :
708 3 : nRet = psSelectInfo->column_summary[0].count;
709 : }
710 177 : else if (psSelectInfo->query_mode != SWQM_RECORDSET)
711 0 : return 1;
712 177 : else if (m_poAttrQuery == nullptr && !MustEvaluateSpatialFilterOnGenSQL())
713 : {
714 168 : nRet = m_poSrcLayer->GetFeatureCount(bForce);
715 : }
716 : else
717 : {
718 9 : nRet = OGRLayer::GetFeatureCount(bForce);
719 : }
720 180 : if (nRet < 0)
721 1 : return nRet;
722 :
723 179 : nRet = std::max(static_cast<GIntBig>(0), nRet - psSelectInfo->offset);
724 179 : if (psSelectInfo->limit >= 0)
725 5 : nRet = std::min(nRet, psSelectInfo->limit);
726 179 : return nRet;
727 : }
728 :
729 : /************************************************************************/
730 : /* TestCapability() */
731 : /************************************************************************/
732 :
733 93 : int OGRGenSQLResultsLayer::TestCapability(const char *pszCap)
734 :
735 : {
736 93 : const swq_select *psSelectInfo = m_pSelectInfo.get();
737 :
738 93 : if (EQUAL(pszCap, OLCFastSetNextByIndex))
739 : {
740 0 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD ||
741 0 : psSelectInfo->query_mode == SWQM_DISTINCT_LIST ||
742 0 : !m_anFIDIndex.empty())
743 0 : return TRUE;
744 : else
745 0 : return m_poSrcLayer->TestCapability(pszCap);
746 : }
747 :
748 93 : if (psSelectInfo->query_mode == SWQM_RECORDSET &&
749 90 : (EQUAL(pszCap, OLCFastFeatureCount) || EQUAL(pszCap, OLCRandomRead) ||
750 90 : EQUAL(pszCap, OLCFastGetExtent)))
751 2 : return m_poSrcLayer->TestCapability(pszCap);
752 :
753 91 : else if (psSelectInfo->query_mode != SWQM_RECORDSET)
754 : {
755 3 : if (EQUAL(pszCap, OLCFastFeatureCount))
756 0 : return TRUE;
757 : }
758 :
759 91 : if (EQUAL(pszCap, OLCStringsAsUTF8) || EQUAL(pszCap, OLCCurveGeometries) ||
760 66 : EQUAL(pszCap, OLCMeasuredGeometries) || EQUAL(pszCap, OLCZGeometries))
761 : {
762 32 : return m_poSrcLayer->TestCapability(pszCap);
763 : }
764 :
765 59 : else if (EQUAL(pszCap, OLCFastGetArrowStream))
766 : {
767 : // Make sure the SQL is something as simple as
768 : // "SELECT field1 [AS renamed], ... FROM ... WHERE ....", without
769 : // duplicated fields
770 40 : if (m_bForwardWhereToSourceLayer &&
771 40 : psSelectInfo->query_mode == SWQM_RECORDSET &&
772 37 : psSelectInfo->offset == 0 && psSelectInfo->join_count == 0 &&
773 35 : psSelectInfo->order_specs == 0)
774 : {
775 68 : std::set<int> oSetFieldIndex;
776 34 : int nLastIdxRegularField = -1;
777 141 : for (std::size_t iField = 0;
778 141 : iField < psSelectInfo->column_defs.size(); iField++)
779 : {
780 : const swq_col_def *psColDef =
781 117 : &psSelectInfo->column_defs[iField];
782 117 : if (psColDef->bHidden || psColDef->table_index < 0 ||
783 345 : psColDef->col_func != SWQCF_NONE ||
784 111 : cpl::contains(oSetFieldIndex, psColDef->field_index))
785 : {
786 8 : return false;
787 : }
788 :
789 109 : oSetFieldIndex.insert(psColDef->field_index);
790 :
791 : const auto poLayerDefn =
792 109 : m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
793 :
794 218 : if (psColDef->field_index >= 0 && poLayerDefn != nullptr &&
795 109 : psColDef->field_index < poLayerDefn->GetFieldCount())
796 : {
797 : // We do not support re-ordered fields
798 86 : if (psColDef->field_index <= nLastIdxRegularField)
799 1 : return false;
800 85 : nLastIdxRegularField = psColDef->field_index;
801 : }
802 46 : else if (poLayerDefn != nullptr &&
803 23 : IS_GEOM_FIELD_INDEX(poLayerDefn,
804 : psColDef->field_index))
805 : {
806 : // ok
807 : }
808 : else
809 : {
810 1 : return false;
811 : }
812 : }
813 24 : return m_poSrcLayer->TestCapability(pszCap);
814 : }
815 : }
816 :
817 25 : return FALSE;
818 : }
819 :
820 : /************************************************************************/
821 : /* ContainGeomSpecialField() */
822 : /************************************************************************/
823 :
824 427 : int OGRGenSQLResultsLayer::ContainGeomSpecialField(swq_expr_node *expr)
825 : {
826 427 : if (expr->eNodeType == SNT_COLUMN)
827 : {
828 405 : if (expr->table_index == 0 && expr->field_index != -1)
829 : {
830 9 : OGRLayer *poLayer = m_apoTableLayers[expr->table_index];
831 : int nSpecialFieldIdx =
832 9 : expr->field_index - poLayer->GetLayerDefn()->GetFieldCount();
833 9 : if (nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
834 9 : nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
835 : nSpecialFieldIdx == SPF_OGR_GEOM_AREA)
836 0 : return TRUE;
837 18 : if (expr->field_index ==
838 9 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(), 0))
839 2 : return TRUE;
840 7 : return FALSE;
841 : }
842 : }
843 22 : else if (expr->eNodeType == SNT_OPERATION)
844 : {
845 29 : for (int i = 0; i < expr->nSubExprCount; i++)
846 : {
847 20 : if (ContainGeomSpecialField(expr->papoSubExpr[i]))
848 3 : return TRUE;
849 : }
850 : }
851 415 : return FALSE;
852 : }
853 :
854 : /************************************************************************/
855 : /* PrepareSummary() */
856 : /************************************************************************/
857 :
858 454 : bool OGRGenSQLResultsLayer::PrepareSummary()
859 :
860 : {
861 454 : swq_select *psSelectInfo = m_pSelectInfo.get();
862 :
863 454 : if (m_poSummaryFeature)
864 90 : return true;
865 :
866 364 : m_poSummaryFeature = std::make_unique<OGRFeature>(m_poDefn);
867 364 : m_poSummaryFeature->SetFID(0);
868 :
869 : /* -------------------------------------------------------------------- */
870 : /* Ensure our query parameters are in place on the source */
871 : /* layer. And initialize reading. */
872 : /* -------------------------------------------------------------------- */
873 364 : ApplyFiltersToSource();
874 :
875 : /* -------------------------------------------------------------------- */
876 : /* Ignore geometry reading if no spatial filter in place and that */
877 : /* the where clause and no column references OGR_GEOMETRY, */
878 : /* OGR_GEOM_WKT or OGR_GEOM_AREA special fields. */
879 : /* -------------------------------------------------------------------- */
880 :
881 : struct TempGeomIgnoredSetter
882 : {
883 : OGRFeatureDefn &m_oDefn;
884 : const int m_bSaveIsGeomIgnored;
885 :
886 359 : explicit TempGeomIgnoredSetter(OGRFeatureDefn *poDefn)
887 359 : : m_oDefn(*poDefn),
888 359 : m_bSaveIsGeomIgnored(poDefn->IsGeometryIgnored())
889 : {
890 359 : m_oDefn.SetGeometryIgnored(true);
891 359 : }
892 :
893 359 : ~TempGeomIgnoredSetter()
894 359 : {
895 359 : m_oDefn.SetGeometryIgnored(m_bSaveIsGeomIgnored);
896 359 : }
897 : };
898 :
899 364 : auto poSrcLayerDefn = m_poSrcLayer->GetLayerDefn();
900 364 : std::unique_ptr<TempGeomIgnoredSetter> oTempGeomIgnoredSetter;
901 :
902 728 : if (m_poFilterGeom == nullptr &&
903 364 : (psSelectInfo->where_expr == nullptr ||
904 11 : !ContainGeomSpecialField(psSelectInfo->where_expr)))
905 : {
906 362 : bool bFoundGeomExpr = false;
907 758 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
908 : {
909 399 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
910 399 : if (psColDef->table_index == 0 && psColDef->field_index != -1)
911 : {
912 93 : OGRLayer *poLayer = m_apoTableLayers[psColDef->table_index];
913 : const int nSpecialFieldIdx =
914 93 : psColDef->field_index -
915 93 : poLayer->GetLayerDefn()->GetFieldCount();
916 93 : if (nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
917 92 : nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
918 : nSpecialFieldIdx == SPF_OGR_GEOM_AREA)
919 : {
920 2 : bFoundGeomExpr = true;
921 2 : break;
922 : }
923 182 : if (psColDef->field_index ==
924 91 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(),
925 : 0))
926 : {
927 1 : bFoundGeomExpr = true;
928 1 : break;
929 : }
930 : }
931 792 : if (psColDef->expr != nullptr &&
932 396 : ContainGeomSpecialField(psColDef->expr))
933 : {
934 0 : bFoundGeomExpr = true;
935 0 : break;
936 : }
937 : }
938 362 : if (!bFoundGeomExpr)
939 : {
940 : // cppcheck-suppress unreadVariable
941 : oTempGeomIgnoredSetter =
942 359 : std::make_unique<TempGeomIgnoredSetter>(poSrcLayerDefn);
943 : }
944 : }
945 :
946 : /* -------------------------------------------------------------------- */
947 : /* We treat COUNT(*) as a special case, and fill with */
948 : /* GetFeatureCount(). */
949 : /* -------------------------------------------------------------------- */
950 :
951 364 : if (psSelectInfo->result_columns() == 1 &&
952 673 : psSelectInfo->column_defs[0].col_func == SWQCF_COUNT &&
953 309 : psSelectInfo->column_defs[0].field_index < 0)
954 : {
955 304 : GIntBig nRes = m_poSrcLayer->GetFeatureCount(TRUE);
956 304 : m_poSummaryFeature->SetField(0, nRes);
957 :
958 304 : if (CPL_INT64_FITS_ON_INT32(nRes))
959 : {
960 303 : m_poSummaryFeature.reset();
961 303 : m_poDefn->GetFieldDefn(0)->SetType(OFTInteger);
962 303 : m_poSummaryFeature = std::make_unique<OGRFeature>(m_poDefn);
963 303 : m_poSummaryFeature->SetFID(0);
964 303 : m_poSummaryFeature->SetField(0, static_cast<int>(nRes));
965 : }
966 :
967 304 : return TRUE;
968 : }
969 :
970 : /* -------------------------------------------------------------------- */
971 : /* Otherwise, process all source feature through the summary */
972 : /* building facilities of SWQ. */
973 : /* -------------------------------------------------------------------- */
974 :
975 464 : for (auto &&poSrcFeature : *m_poSrcLayer)
976 : {
977 949 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
978 : {
979 545 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
980 545 : const char *pszError = nullptr;
981 :
982 545 : if (psColDef->col_func == SWQCF_COUNT)
983 : {
984 : /* psColDef->field_index can be -1 in the case of a COUNT(*) */
985 90 : if (psColDef->field_index < 0)
986 : pszError =
987 22 : swq_select_summarize(psSelectInfo, iField, "", nullptr);
988 68 : else if (IS_GEOM_FIELD_INDEX(poSrcLayerDefn,
989 : psColDef->field_index))
990 : {
991 : const int iSrcGeomField =
992 2 : ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
993 : poSrcLayerDefn, psColDef->field_index);
994 : const OGRGeometry *poGeom =
995 2 : poSrcFeature->GetGeomFieldRef(iSrcGeomField);
996 2 : if (poGeom != nullptr)
997 1 : pszError = swq_select_summarize(psSelectInfo, iField,
998 : "", nullptr);
999 : }
1000 132 : else if (poSrcFeature->IsFieldSetAndNotNull(
1001 66 : psColDef->field_index))
1002 : {
1003 49 : if (!psColDef->distinct_flag)
1004 : {
1005 27 : pszError = swq_select_summarize(psSelectInfo, iField,
1006 : "", nullptr);
1007 : }
1008 : else
1009 : {
1010 22 : const char *pszVal = poSrcFeature->GetFieldAsString(
1011 22 : psColDef->field_index);
1012 22 : pszError = swq_select_summarize(psSelectInfo, iField,
1013 : pszVal, nullptr);
1014 : }
1015 : }
1016 : }
1017 : else
1018 : {
1019 455 : if (poSrcFeature->IsFieldSetAndNotNull(psColDef->field_index))
1020 : {
1021 415 : if (!psColDef->distinct_flag &&
1022 144 : (psColDef->field_type == SWQ_BOOLEAN ||
1023 138 : psColDef->field_type == SWQ_INTEGER ||
1024 78 : psColDef->field_type == SWQ_INTEGER64 ||
1025 62 : psColDef->field_type == SWQ_FLOAT))
1026 : {
1027 104 : const double dfValue = poSrcFeature->GetFieldAsDouble(
1028 104 : psColDef->field_index);
1029 104 : pszError = swq_select_summarize(psSelectInfo, iField,
1030 104 : nullptr, &dfValue);
1031 : }
1032 : else
1033 : {
1034 311 : const char *pszVal = poSrcFeature->GetFieldAsString(
1035 311 : psColDef->field_index);
1036 311 : pszError = swq_select_summarize(psSelectInfo, iField,
1037 : pszVal, nullptr);
1038 : }
1039 : }
1040 : else
1041 : {
1042 40 : pszError = swq_select_summarize(psSelectInfo, iField,
1043 : nullptr, nullptr);
1044 : }
1045 : }
1046 :
1047 545 : if (pszError)
1048 : {
1049 2 : m_poSummaryFeature.reset();
1050 :
1051 2 : CPLError(CE_Failure, CPLE_AppDefined, "%s", pszError);
1052 2 : return false;
1053 : }
1054 : }
1055 : }
1056 :
1057 : /* -------------------------------------------------------------------- */
1058 : /* Clear away the filters we have installed till a next run through*/
1059 : /* the features. */
1060 : /* -------------------------------------------------------------------- */
1061 58 : ClearFilters();
1062 :
1063 : /* -------------------------------------------------------------------- */
1064 : /* Now apply the values to the summary feature. If we are in */
1065 : /* DISTINCT_LIST mode we don't do this step. */
1066 : /* -------------------------------------------------------------------- */
1067 58 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD)
1068 : {
1069 107 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1070 : {
1071 72 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1072 72 : if (!psSelectInfo->column_summary.empty())
1073 : {
1074 : const swq_summary &oSummary =
1075 65 : psSelectInfo->column_summary[iField];
1076 65 : if (psColDef->col_func == SWQCF_COUNT)
1077 : {
1078 20 : if (CPL_INT64_FITS_ON_INT32(oSummary.count))
1079 : {
1080 20 : m_poSummaryFeature.reset();
1081 20 : m_poDefn->GetFieldDefn(iField)->SetType(OFTInteger);
1082 : }
1083 : }
1084 : }
1085 : }
1086 :
1087 35 : if (!m_poSummaryFeature)
1088 : {
1089 12 : m_poSummaryFeature = std::make_unique<OGRFeature>(m_poDefn);
1090 12 : m_poSummaryFeature->SetFID(0);
1091 : }
1092 :
1093 107 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1094 : {
1095 72 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1096 72 : if (!psSelectInfo->column_summary.empty())
1097 : {
1098 : const swq_summary &oSummary =
1099 65 : psSelectInfo->column_summary[iField];
1100 :
1101 65 : switch (psColDef->col_func)
1102 : {
1103 0 : case SWQCF_NONE:
1104 : case SWQCF_CUSTOM:
1105 0 : break;
1106 :
1107 6 : case SWQCF_AVG:
1108 : {
1109 6 : if (oSummary.count > 0)
1110 : {
1111 : const double dfAvg =
1112 4 : oSummary.sum() / oSummary.count;
1113 4 : if (psColDef->field_type == SWQ_DATE ||
1114 4 : psColDef->field_type == SWQ_TIME ||
1115 4 : psColDef->field_type == SWQ_TIMESTAMP)
1116 : {
1117 : struct tm brokendowntime;
1118 1 : CPLUnixTimeToYMDHMS(static_cast<GIntBig>(dfAvg),
1119 : &brokendowntime);
1120 1 : m_poSummaryFeature->SetField(
1121 1 : iField, brokendowntime.tm_year + 1900,
1122 1 : brokendowntime.tm_mon + 1,
1123 : brokendowntime.tm_mday,
1124 : brokendowntime.tm_hour,
1125 : brokendowntime.tm_min,
1126 1 : static_cast<float>(brokendowntime.tm_sec +
1127 1 : fmod(dfAvg, 1)),
1128 1 : 0);
1129 : }
1130 : else
1131 : {
1132 3 : m_poSummaryFeature->SetField(iField, dfAvg);
1133 : }
1134 : }
1135 6 : break;
1136 : }
1137 :
1138 12 : case SWQCF_MIN:
1139 : {
1140 12 : if (oSummary.count > 0)
1141 : {
1142 11 : if (psColDef->field_type == SWQ_DATE ||
1143 10 : psColDef->field_type == SWQ_TIME ||
1144 9 : psColDef->field_type == SWQ_TIMESTAMP ||
1145 6 : psColDef->field_type == SWQ_STRING)
1146 6 : m_poSummaryFeature->SetField(
1147 : iField, oSummary.osMin.c_str());
1148 : else
1149 5 : m_poSummaryFeature->SetField(iField,
1150 5 : oSummary.min);
1151 : }
1152 12 : break;
1153 : }
1154 :
1155 13 : case SWQCF_MAX:
1156 : {
1157 13 : if (oSummary.count > 0)
1158 : {
1159 12 : if (psColDef->field_type == SWQ_DATE ||
1160 11 : psColDef->field_type == SWQ_TIME ||
1161 10 : psColDef->field_type == SWQ_TIMESTAMP ||
1162 7 : psColDef->field_type == SWQ_STRING)
1163 6 : m_poSummaryFeature->SetField(
1164 : iField, oSummary.osMax.c_str());
1165 : else
1166 6 : m_poSummaryFeature->SetField(iField,
1167 6 : oSummary.max);
1168 : }
1169 13 : break;
1170 : }
1171 :
1172 20 : case SWQCF_COUNT:
1173 : {
1174 20 : m_poSummaryFeature->SetField(iField, oSummary.count);
1175 20 : break;
1176 : }
1177 :
1178 9 : case SWQCF_SUM:
1179 : {
1180 9 : if (oSummary.count > 0)
1181 8 : m_poSummaryFeature->SetField(iField,
1182 : oSummary.sum());
1183 9 : break;
1184 : }
1185 :
1186 3 : case SWQCF_STDDEV_POP:
1187 : {
1188 3 : if (oSummary.count > 0)
1189 : {
1190 2 : const double dfVariance =
1191 2 : oSummary.sq_dist_from_mean_acc / oSummary.count;
1192 2 : m_poSummaryFeature->SetField(iField,
1193 : sqrt(dfVariance));
1194 : }
1195 3 : break;
1196 : }
1197 :
1198 2 : case SWQCF_STDDEV_SAMP:
1199 : {
1200 2 : if (oSummary.count > 1)
1201 : {
1202 2 : const double dfSampleVariance =
1203 2 : oSummary.sq_dist_from_mean_acc /
1204 2 : (oSummary.count - 1);
1205 2 : m_poSummaryFeature->SetField(
1206 : iField, sqrt(dfSampleVariance));
1207 : }
1208 2 : break;
1209 : }
1210 : }
1211 : }
1212 7 : else if (psColDef->col_func == SWQCF_COUNT)
1213 1 : m_poSummaryFeature->SetField(iField, 0);
1214 : }
1215 : }
1216 :
1217 58 : return TRUE;
1218 : }
1219 :
1220 : /************************************************************************/
1221 : /* OGRMultiFeatureFetcher() */
1222 : /************************************************************************/
1223 :
1224 : typedef std::vector<std::unique_ptr<OGRFeature>> VectorOfUniquePtrFeature;
1225 :
1226 34 : static swq_expr_node *OGRMultiFeatureFetcher(swq_expr_node *op,
1227 : void *pFeatureList)
1228 :
1229 : {
1230 34 : auto &apoFeatures =
1231 : *(static_cast<VectorOfUniquePtrFeature *>(pFeatureList));
1232 34 : swq_expr_node *poRetNode = nullptr;
1233 :
1234 34 : CPLAssert(op->eNodeType == SNT_COLUMN);
1235 :
1236 : /* -------------------------------------------------------------------- */
1237 : /* What feature are we using? The primary or one of the joined ones?*/
1238 : /* -------------------------------------------------------------------- */
1239 68 : if (op->table_index < 0 ||
1240 34 : op->table_index >= static_cast<int>(apoFeatures.size()))
1241 : {
1242 0 : CPLError(CE_Failure, CPLE_AppDefined,
1243 : "Request for unexpected table_index (%d) in field fetcher.",
1244 : op->table_index);
1245 0 : return nullptr;
1246 : }
1247 :
1248 34 : OGRFeature *poFeature = apoFeatures[op->table_index].get();
1249 :
1250 : /* -------------------------------------------------------------------- */
1251 : /* Fetch the value. */
1252 : /* -------------------------------------------------------------------- */
1253 34 : switch (op->field_type)
1254 : {
1255 15 : case SWQ_INTEGER:
1256 : case SWQ_BOOLEAN:
1257 30 : if (poFeature == nullptr ||
1258 15 : !poFeature->IsFieldSetAndNotNull(op->field_index))
1259 : {
1260 2 : poRetNode = new swq_expr_node(0);
1261 2 : poRetNode->is_null = TRUE;
1262 : }
1263 : else
1264 13 : poRetNode = new swq_expr_node(
1265 13 : poFeature->GetFieldAsInteger(op->field_index));
1266 15 : break;
1267 :
1268 4 : case SWQ_INTEGER64:
1269 8 : if (poFeature == nullptr ||
1270 4 : !poFeature->IsFieldSetAndNotNull(op->field_index))
1271 : {
1272 0 : poRetNode = new swq_expr_node(static_cast<GIntBig>(0));
1273 0 : poRetNode->is_null = TRUE;
1274 : }
1275 : else
1276 4 : poRetNode = new swq_expr_node(
1277 4 : poFeature->GetFieldAsInteger64(op->field_index));
1278 4 : break;
1279 :
1280 1 : case SWQ_FLOAT:
1281 2 : if (poFeature == nullptr ||
1282 1 : !poFeature->IsFieldSetAndNotNull(op->field_index))
1283 : {
1284 0 : poRetNode = new swq_expr_node(0.0);
1285 0 : poRetNode->is_null = TRUE;
1286 : }
1287 : else
1288 1 : poRetNode = new swq_expr_node(
1289 1 : poFeature->GetFieldAsDouble(op->field_index));
1290 1 : break;
1291 :
1292 4 : case SWQ_GEOMETRY:
1293 4 : if (poFeature == nullptr)
1294 : {
1295 0 : poRetNode =
1296 0 : new swq_expr_node(static_cast<OGRGeometry *>(nullptr));
1297 : }
1298 : else
1299 : {
1300 4 : int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
1301 : poFeature->GetDefnRef(), op->field_index);
1302 4 : poRetNode = new swq_expr_node(
1303 4 : poFeature->GetGeomFieldRef(iSrcGeomField));
1304 : }
1305 4 : break;
1306 :
1307 10 : default:
1308 20 : if (poFeature == nullptr ||
1309 10 : !poFeature->IsFieldSetAndNotNull(op->field_index))
1310 : {
1311 1 : poRetNode = new swq_expr_node("");
1312 1 : poRetNode->is_null = TRUE;
1313 : }
1314 : else
1315 9 : poRetNode = new swq_expr_node(
1316 9 : poFeature->GetFieldAsString(op->field_index));
1317 10 : break;
1318 : }
1319 :
1320 34 : return poRetNode;
1321 : }
1322 :
1323 : /************************************************************************/
1324 : /* GetFilterForJoin() */
1325 : /************************************************************************/
1326 :
1327 334 : static CPLString GetFilterForJoin(swq_expr_node *poExpr, OGRFeature *poSrcFeat,
1328 : OGRLayer *poJoinLayer, int secondary_table)
1329 : {
1330 334 : if (poExpr->eNodeType == SNT_CONSTANT)
1331 : {
1332 29 : char *pszRes = poExpr->Unparse(nullptr, '"');
1333 58 : CPLString osRes = pszRes;
1334 29 : CPLFree(pszRes);
1335 29 : return osRes;
1336 : }
1337 :
1338 305 : if (poExpr->eNodeType == SNT_COLUMN)
1339 : {
1340 183 : CPLAssert(poExpr->field_index != -1);
1341 183 : CPLAssert(poExpr->table_index == 0 ||
1342 : poExpr->table_index == secondary_table);
1343 :
1344 183 : if (poExpr->table_index == 0)
1345 : {
1346 : // if source key is null, we can't do join.
1347 94 : if (!poSrcFeat->IsFieldSetAndNotNull(poExpr->field_index))
1348 : {
1349 3 : return "";
1350 : }
1351 91 : const auto poSrcFDefn = poSrcFeat->GetDefnRef();
1352 91 : if (poExpr->field_index >= poSrcFDefn->GetFieldCount())
1353 : {
1354 4 : CPLAssert(poExpr->field_index <
1355 : poSrcFDefn->GetFieldCount() + SPECIAL_FIELD_COUNT);
1356 8 : switch (SpecialFieldTypes[poExpr->field_index -
1357 4 : poSrcFDefn->GetFieldCount()])
1358 : {
1359 2 : case SWQ_INTEGER:
1360 : case SWQ_INTEGER64:
1361 4 : return CPLString().Printf(
1362 : CPL_FRMT_GIB, poSrcFeat->GetFieldAsInteger64(
1363 2 : poExpr->field_index));
1364 : break;
1365 1 : case SWQ_FLOAT:
1366 2 : return CPLString().Printf(
1367 : "%.17g",
1368 1 : poSrcFeat->GetFieldAsDouble(poExpr->field_index));
1369 : break;
1370 1 : default:
1371 : {
1372 1 : char *pszEscaped = CPLEscapeString(
1373 : poSrcFeat->GetFieldAsString(poExpr->field_index),
1374 : -1, CPLES_SQL);
1375 2 : CPLString osRes = "'";
1376 1 : osRes += pszEscaped;
1377 1 : osRes += "'";
1378 1 : CPLFree(pszEscaped);
1379 1 : return osRes;
1380 : }
1381 : }
1382 : }
1383 : else
1384 : {
1385 : const OGRFieldType ePrimaryFieldType =
1386 87 : poSrcFeat->GetFieldDefnRef(poExpr->field_index)->GetType();
1387 : const OGRField *psSrcField =
1388 87 : poSrcFeat->GetRawFieldRef(poExpr->field_index);
1389 :
1390 174 : CPLString osRet;
1391 87 : switch (ePrimaryFieldType)
1392 : {
1393 13 : case OFTInteger:
1394 13 : osRet.Printf("%d", psSrcField->Integer);
1395 13 : break;
1396 :
1397 55 : case OFTInteger64:
1398 55 : osRet.Printf(CPL_FRMT_GIB, psSrcField->Integer64);
1399 55 : break;
1400 :
1401 0 : case OFTReal:
1402 0 : osRet.Printf("%.17g", psSrcField->Real);
1403 0 : break;
1404 :
1405 19 : case OFTString:
1406 : {
1407 38 : char *pszEscaped = CPLEscapeString(
1408 19 : psSrcField->String,
1409 19 : static_cast<int>(strlen(psSrcField->String)),
1410 : CPLES_SQL);
1411 19 : osRet = "'";
1412 19 : osRet += pszEscaped;
1413 19 : osRet += "'";
1414 19 : CPLFree(pszEscaped);
1415 19 : break;
1416 : }
1417 :
1418 0 : default:
1419 0 : CPLAssert(false);
1420 : break;
1421 : }
1422 :
1423 87 : return osRet;
1424 : }
1425 : }
1426 :
1427 89 : if (poExpr->table_index == secondary_table)
1428 : {
1429 89 : const auto poJoinFDefn = poJoinLayer->GetLayerDefn();
1430 89 : if (poExpr->field_index >= poJoinFDefn->GetFieldCount())
1431 : {
1432 2 : CPLAssert(poExpr->field_index <
1433 : poJoinFDefn->GetFieldCount() + SPECIAL_FIELD_COUNT);
1434 4 : return SpecialFieldNames[poExpr->field_index -
1435 2 : poJoinFDefn->GetFieldCount()];
1436 : }
1437 : else
1438 : {
1439 : const OGRFieldDefn *poSecondaryFieldDefn =
1440 87 : poJoinFDefn->GetFieldDefn(poExpr->field_index);
1441 87 : return CPLSPrintf("\"%s\"", poSecondaryFieldDefn->GetNameRef());
1442 : }
1443 : }
1444 :
1445 0 : CPLAssert(false);
1446 : return "";
1447 : }
1448 :
1449 122 : if (poExpr->eNodeType == SNT_OPERATION)
1450 : {
1451 : /* ----------------------------------------------------------------- */
1452 : /* Operation - start by unparsing all the subexpressions. */
1453 : /* ----------------------------------------------------------------- */
1454 244 : std::vector<char *> apszSubExpr;
1455 360 : for (int i = 0; i < poExpr->nSubExprCount; i++)
1456 : {
1457 : CPLString osSubExpr =
1458 241 : GetFilterForJoin(poExpr->papoSubExpr[i], poSrcFeat, poJoinLayer,
1459 241 : secondary_table);
1460 241 : if (osSubExpr.empty())
1461 : {
1462 3 : for (--i; i >= 0; i--)
1463 0 : CPLFree(apszSubExpr[i]);
1464 3 : return "";
1465 : }
1466 238 : apszSubExpr.push_back(CPLStrdup(osSubExpr));
1467 : }
1468 :
1469 : CPLString osExpr =
1470 238 : poExpr->UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
1471 :
1472 : /* ----------------------------------------------------------------- */
1473 : /* cleanup subexpressions. */
1474 : /* ----------------------------------------------------------------- */
1475 357 : for (int i = 0; i < poExpr->nSubExprCount; i++)
1476 238 : CPLFree(apszSubExpr[i]);
1477 :
1478 119 : return osExpr;
1479 : }
1480 :
1481 0 : return "";
1482 : }
1483 :
1484 : /************************************************************************/
1485 : /* TranslateFeature() */
1486 : /************************************************************************/
1487 :
1488 3862 : std::unique_ptr<OGRFeature> OGRGenSQLResultsLayer::TranslateFeature(
1489 : std::unique_ptr<OGRFeature> poSrcFeatUniquePtr)
1490 :
1491 : {
1492 3862 : swq_select *psSelectInfo = m_pSelectInfo.get();
1493 7724 : VectorOfUniquePtrFeature apoFeatures;
1494 :
1495 3862 : if (poSrcFeatUniquePtr == nullptr)
1496 0 : return nullptr;
1497 :
1498 3862 : m_nFeaturesRead++;
1499 :
1500 3862 : apoFeatures.push_back(std::move(poSrcFeatUniquePtr));
1501 3862 : auto poSrcFeat = apoFeatures.front().get();
1502 :
1503 : /* -------------------------------------------------------------------- */
1504 : /* Fetch the corresponding features from any jointed tables. */
1505 : /* -------------------------------------------------------------------- */
1506 3955 : for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
1507 : {
1508 93 : const swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1509 :
1510 : /* OGRMultiFeatureFetcher assumes that the features are pushed in */
1511 : /* apoFeatures with increasing secondary_table, so make sure */
1512 : /* we have taken care of this */
1513 93 : CPLAssert(psJoinInfo->secondary_table == iJoin + 1);
1514 :
1515 93 : OGRLayer *poJoinLayer = m_apoTableLayers[psJoinInfo->secondary_table];
1516 :
1517 : const std::string osFilter =
1518 186 : GetFilterForJoin(psJoinInfo->poExpr, poSrcFeat, poJoinLayer,
1519 93 : psJoinInfo->secondary_table);
1520 : // CPLDebug("OGR", "Filter = %s\n", osFilter.c_str());
1521 :
1522 : // if source key is null, we can't do join.
1523 93 : if (osFilter.empty())
1524 : {
1525 3 : apoFeatures.push_back(nullptr);
1526 3 : continue;
1527 : }
1528 :
1529 90 : std::unique_ptr<OGRFeature> poJoinFeature;
1530 :
1531 90 : poJoinLayer->ResetReading();
1532 90 : if (poJoinLayer->SetAttributeFilter(osFilter.c_str()) == OGRERR_NONE)
1533 90 : poJoinFeature.reset(poJoinLayer->GetNextFeature());
1534 :
1535 90 : apoFeatures.push_back(std::move(poJoinFeature));
1536 : }
1537 :
1538 : /* -------------------------------------------------------------------- */
1539 : /* Create destination feature. */
1540 : /* -------------------------------------------------------------------- */
1541 7724 : auto poDstFeat = std::make_unique<OGRFeature>(m_poDefn);
1542 :
1543 3862 : poDstFeat->SetFID(poSrcFeat->GetFID());
1544 :
1545 3862 : poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
1546 3862 : poDstFeat->SetNativeData(poSrcFeat->GetNativeData());
1547 3862 : poDstFeat->SetNativeMediaType(poSrcFeat->GetNativeMediaType());
1548 :
1549 : /* -------------------------------------------------------------------- */
1550 : /* Evaluate fields that are complex expressions. */
1551 : /* -------------------------------------------------------------------- */
1552 3862 : int iRegularField = 0;
1553 3862 : int iGeomField = 0;
1554 3862 : swq_evaluation_context sContext;
1555 18097 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1556 : {
1557 14235 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1558 :
1559 14235 : if (psColDef->bHidden)
1560 : {
1561 10 : const char *pszDstFieldName = psColDef->field_alias
1562 : ? psColDef->field_alias
1563 : : psColDef->field_name;
1564 10 : if (EQUAL(pszDstFieldName, "OGR_STYLE"))
1565 : {
1566 10 : if (psColDef->field_type == SWQ_STRING)
1567 : {
1568 : // Does this column definition directly references a
1569 : // source field ?
1570 7 : if (psColDef->field_index >= 0)
1571 : {
1572 4 : if (!IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(),
1573 : psColDef->field_index))
1574 : {
1575 4 : if (poSrcFeat->IsFieldSetAndNotNull(
1576 4 : psColDef->field_index))
1577 : {
1578 : const char *pszVal =
1579 4 : poSrcFeat->GetFieldAsString(
1580 2 : psColDef->field_index);
1581 2 : poDstFeat->SetStyleString(pszVal);
1582 : }
1583 : else
1584 : {
1585 2 : poDstFeat->SetStyleString(nullptr);
1586 : }
1587 : }
1588 : else
1589 : {
1590 0 : CPLError(CE_Warning, CPLE_AppDefined,
1591 : "OGR_STYLE HIDDEN field should reference "
1592 : "a column of type String");
1593 : }
1594 : }
1595 : else
1596 : {
1597 : auto poResult = std::unique_ptr<swq_expr_node>(
1598 3 : psColDef->expr->Evaluate(OGRMultiFeatureFetcher,
1599 3 : &apoFeatures, sContext));
1600 :
1601 3 : if (!poResult)
1602 : {
1603 0 : return nullptr;
1604 : }
1605 :
1606 8 : poDstFeat->SetStyleString(poResult->is_null
1607 : ? nullptr
1608 5 : : poResult->string_value);
1609 : }
1610 : }
1611 : else
1612 : {
1613 3 : CPLError(CE_Warning, CPLE_AppDefined,
1614 : "OGR_STYLE HIDDEN field should be of type String");
1615 : }
1616 : }
1617 13924 : continue;
1618 : }
1619 :
1620 : // Does this column definition directly references a
1621 : // source field ?
1622 : // If so, skip it for now, as it will be taken into account in the
1623 : // next loop.
1624 14225 : if (psColDef->field_index >= 0)
1625 : {
1626 13881 : if (psColDef->field_type == SWQ_GEOMETRY ||
1627 12261 : psColDef->target_type == SWQ_GEOMETRY)
1628 1620 : iGeomField++;
1629 : else
1630 12261 : iRegularField++;
1631 13881 : continue;
1632 : }
1633 :
1634 344 : auto poResult = std::unique_ptr<swq_expr_node>(psColDef->expr->Evaluate(
1635 344 : OGRMultiFeatureFetcher, &apoFeatures, sContext));
1636 :
1637 344 : if (!poResult)
1638 : {
1639 0 : return nullptr;
1640 : }
1641 :
1642 344 : if (poResult->is_null)
1643 : {
1644 33 : if (poResult->field_type == SWQ_GEOMETRY)
1645 2 : iGeomField++;
1646 : else
1647 31 : iRegularField++;
1648 33 : continue;
1649 : }
1650 :
1651 311 : switch (poResult->field_type)
1652 : {
1653 193 : case SWQ_BOOLEAN:
1654 : case SWQ_INTEGER:
1655 : case SWQ_INTEGER64:
1656 193 : poDstFeat->SetField(iRegularField++,
1657 193 : static_cast<GIntBig>(poResult->int_value));
1658 193 : break;
1659 :
1660 51 : case SWQ_FLOAT:
1661 51 : poDstFeat->SetField(iRegularField++, poResult->float_value);
1662 51 : break;
1663 :
1664 10 : case SWQ_GEOMETRY:
1665 : {
1666 : OGRGenSQLGeomFieldDefn *poGeomFieldDefn =
1667 10 : cpl::down_cast<OGRGenSQLGeomFieldDefn *>(
1668 : poDstFeat->GetGeomFieldDefnRef(iGeomField));
1669 16 : if (poGeomFieldDefn->bForceGeomType &&
1670 6 : poResult->geometry_value != nullptr)
1671 : {
1672 : OGRwkbGeometryType eCurType =
1673 6 : wkbFlatten(poResult->geometry_value->getGeometryType());
1674 : OGRwkbGeometryType eReqType =
1675 6 : wkbFlatten(poGeomFieldDefn->GetType());
1676 6 : if (eCurType == wkbPolygon && eReqType == wkbMultiPolygon)
1677 : {
1678 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1679 : OGR_G_ForceToMultiPolygon(OGRGeometry::ToHandle(
1680 1 : poResult->geometry_value)));
1681 : }
1682 5 : else if ((eCurType == wkbMultiPolygon ||
1683 1 : eCurType == wkbGeometryCollection) &&
1684 : eReqType == wkbPolygon)
1685 : {
1686 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1687 : OGR_G_ForceToPolygon(OGRGeometry::ToHandle(
1688 1 : poResult->geometry_value)));
1689 : }
1690 4 : else if (eCurType == wkbLineString &&
1691 : eReqType == wkbMultiLineString)
1692 : {
1693 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1694 : OGR_G_ForceToMultiLineString(OGRGeometry::ToHandle(
1695 1 : poResult->geometry_value)));
1696 : }
1697 3 : else if ((eCurType == wkbMultiLineString ||
1698 1 : eCurType == wkbGeometryCollection) &&
1699 : eReqType == wkbLineString)
1700 : {
1701 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1702 : OGR_G_ForceToLineString(OGRGeometry::ToHandle(
1703 1 : poResult->geometry_value)));
1704 : }
1705 : }
1706 10 : poDstFeat->SetGeomField(iGeomField++, poResult->geometry_value);
1707 10 : break;
1708 : }
1709 :
1710 57 : default:
1711 57 : poDstFeat->SetField(iRegularField++, poResult->string_value);
1712 57 : break;
1713 : }
1714 : }
1715 :
1716 : /* -------------------------------------------------------------------- */
1717 : /* Copy fields from primary record to the destination feature. */
1718 : /* -------------------------------------------------------------------- */
1719 3862 : iRegularField = 0;
1720 3862 : iGeomField = 0;
1721 18097 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1722 : {
1723 14235 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1724 :
1725 14235 : if (psColDef->bHidden)
1726 : {
1727 10 : continue;
1728 : }
1729 :
1730 : // Skip this column definition if it doesn't reference a field from
1731 : // the main feature
1732 14225 : if (psColDef->table_index != 0)
1733 : {
1734 626 : if (psColDef->field_type == SWQ_GEOMETRY ||
1735 614 : psColDef->target_type == SWQ_GEOMETRY)
1736 12 : iGeomField++;
1737 : else
1738 614 : iRegularField++;
1739 626 : continue;
1740 : }
1741 :
1742 13599 : if (IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(), psColDef->field_index))
1743 : {
1744 1620 : int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
1745 : poSrcFeat->GetDefnRef(), psColDef->field_index);
1746 1620 : poDstFeat->SetGeomField(iGeomField++,
1747 1620 : poSrcFeat->GetGeomFieldRef(iSrcGeomField));
1748 : }
1749 11979 : else if (psColDef->field_index >= m_iFIDFieldIndex)
1750 : {
1751 26 : CPLAssert(psColDef->field_index <
1752 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
1753 26 : switch (SpecialFieldTypes[psColDef->field_index - m_iFIDFieldIndex])
1754 : {
1755 7 : case SWQ_INTEGER:
1756 : case SWQ_INTEGER64:
1757 14 : poDstFeat->SetField(
1758 : iRegularField,
1759 7 : poSrcFeat->GetFieldAsInteger64(psColDef->field_index));
1760 7 : break;
1761 1 : case SWQ_FLOAT:
1762 2 : poDstFeat->SetField(
1763 : iRegularField,
1764 1 : poSrcFeat->GetFieldAsDouble(psColDef->field_index));
1765 1 : break;
1766 18 : default:
1767 36 : poDstFeat->SetField(
1768 : iRegularField,
1769 18 : poSrcFeat->GetFieldAsString(psColDef->field_index));
1770 : }
1771 26 : iRegularField++;
1772 : }
1773 : else
1774 : {
1775 11953 : switch (psColDef->target_type)
1776 : {
1777 0 : case SWQ_INTEGER:
1778 0 : poDstFeat->SetField(
1779 : iRegularField,
1780 0 : poSrcFeat->GetFieldAsInteger(psColDef->field_index));
1781 0 : break;
1782 :
1783 0 : case SWQ_INTEGER64:
1784 0 : poDstFeat->SetField(
1785 : iRegularField,
1786 0 : poSrcFeat->GetFieldAsInteger64(psColDef->field_index));
1787 0 : break;
1788 :
1789 0 : case SWQ_FLOAT:
1790 0 : poDstFeat->SetField(
1791 : iRegularField,
1792 0 : poSrcFeat->GetFieldAsDouble(psColDef->field_index));
1793 0 : break;
1794 :
1795 0 : case SWQ_STRING:
1796 : case SWQ_TIMESTAMP:
1797 : case SWQ_DATE:
1798 : case SWQ_TIME:
1799 0 : poDstFeat->SetField(
1800 : iRegularField,
1801 0 : poSrcFeat->GetFieldAsString(psColDef->field_index));
1802 0 : break;
1803 :
1804 0 : case SWQ_GEOMETRY:
1805 0 : CPLAssert(false);
1806 : break;
1807 :
1808 11953 : default:
1809 23906 : poDstFeat->SetField(
1810 : iRegularField,
1811 11953 : poSrcFeat->GetRawFieldRef(psColDef->field_index));
1812 : }
1813 11953 : iRegularField++;
1814 : }
1815 : }
1816 :
1817 : /* -------------------------------------------------------------------- */
1818 : /* Copy values from any joined tables. */
1819 : /* -------------------------------------------------------------------- */
1820 3955 : for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
1821 : {
1822 93 : const swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1823 93 : const OGRFeature *poJoinFeature = apoFeatures[iJoin + 1].get();
1824 :
1825 93 : if (poJoinFeature == nullptr)
1826 30 : continue;
1827 :
1828 : // Copy over selected field values.
1829 63 : iRegularField = 0;
1830 460 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1831 : {
1832 397 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1833 :
1834 397 : if (psColDef->field_type == SWQ_GEOMETRY ||
1835 346 : psColDef->target_type == SWQ_GEOMETRY)
1836 51 : continue;
1837 :
1838 346 : if (psColDef->bHidden)
1839 : {
1840 0 : continue;
1841 : }
1842 :
1843 346 : if (psColDef->table_index == psJoinInfo->secondary_table)
1844 352 : poDstFeat->SetField(
1845 : iRegularField,
1846 176 : poJoinFeature->GetRawFieldRef(psColDef->field_index));
1847 :
1848 346 : iRegularField++;
1849 : }
1850 : }
1851 :
1852 3862 : return poDstFeat;
1853 : }
1854 :
1855 : /************************************************************************/
1856 : /* GetNextFeature() */
1857 : /************************************************************************/
1858 :
1859 4001 : OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
1860 :
1861 : {
1862 4001 : swq_select *psSelectInfo = m_pSelectInfo.get();
1863 :
1864 4001 : if (m_bEOF)
1865 2 : return nullptr;
1866 3999 : if (psSelectInfo->limit >= 0 &&
1867 48 : (m_nIteratedFeatures < 0 ? 0 : m_nIteratedFeatures) >=
1868 48 : psSelectInfo->limit)
1869 23 : return nullptr;
1870 :
1871 3976 : CreateOrderByIndex();
1872 6750 : if (m_anFIDIndex.empty() && m_nIteratedFeatures < 0 &&
1873 6750 : psSelectInfo->offset > 0 && psSelectInfo->query_mode == SWQM_RECORDSET)
1874 : {
1875 4 : m_poSrcLayer->SetNextByIndex(psSelectInfo->offset);
1876 : }
1877 3976 : if (m_nIteratedFeatures < 0)
1878 2243 : m_nIteratedFeatures = 0;
1879 :
1880 : /* -------------------------------------------------------------------- */
1881 : /* Handle summary sets. */
1882 : /* -------------------------------------------------------------------- */
1883 3976 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD ||
1884 3632 : psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
1885 : {
1886 446 : m_nIteratedFeatures++;
1887 446 : return GetFeature(m_nNextIndexFID++);
1888 : }
1889 :
1890 3530 : int bEvaluateSpatialFilter = MustEvaluateSpatialFilterOnGenSQL();
1891 :
1892 : /* -------------------------------------------------------------------- */
1893 : /* Handle ordered sets. */
1894 : /* -------------------------------------------------------------------- */
1895 : while (true)
1896 : {
1897 0 : std::unique_ptr<OGRFeature> poSrcFeat;
1898 3581 : if (!m_anFIDIndex.empty())
1899 : {
1900 : /* --------------------------------------------------------------------
1901 : */
1902 : /* Are we running in sorted mode? If so, run the fid through
1903 : */
1904 : /* the index. */
1905 : /* --------------------------------------------------------------------
1906 : */
1907 :
1908 1202 : if (m_nNextIndexFID >= static_cast<GIntBig>(m_anFIDIndex.size()))
1909 13 : return nullptr;
1910 :
1911 1189 : poSrcFeat.reset(m_poSrcLayer->GetFeature(
1912 1189 : m_anFIDIndex[static_cast<size_t>(m_nNextIndexFID)]));
1913 1189 : m_nNextIndexFID++;
1914 : }
1915 : else
1916 : {
1917 2379 : poSrcFeat.reset(m_poSrcLayer->GetNextFeature());
1918 : }
1919 :
1920 3568 : if (poSrcFeat == nullptr)
1921 711 : return nullptr;
1922 :
1923 2857 : auto poFeature = TranslateFeature(std::move(poSrcFeat));
1924 2857 : if (poFeature == nullptr)
1925 0 : return nullptr;
1926 :
1927 5830 : if ((m_poAttrQuery == nullptr ||
1928 2857 : m_poAttrQuery->Evaluate(poFeature.get())) &&
1929 0 : (!bEvaluateSpatialFilter ||
1930 0 : FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))))
1931 : {
1932 2806 : m_nIteratedFeatures++;
1933 2806 : return poFeature.release();
1934 : }
1935 51 : }
1936 :
1937 : return nullptr;
1938 : }
1939 :
1940 : /************************************************************************/
1941 : /* GetFeature() */
1942 : /************************************************************************/
1943 :
1944 1454 : OGRFeature *OGRGenSQLResultsLayer::GetFeature(GIntBig nFID)
1945 :
1946 : {
1947 1454 : swq_select *psSelectInfo = m_pSelectInfo.get();
1948 :
1949 1454 : CreateOrderByIndex();
1950 :
1951 : /* -------------------------------------------------------------------- */
1952 : /* Handle request for summary record. */
1953 : /* -------------------------------------------------------------------- */
1954 1454 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD)
1955 : {
1956 344 : if (!PrepareSummary() || nFID != 0 || !m_poSummaryFeature)
1957 5 : return nullptr;
1958 : else
1959 339 : return m_poSummaryFeature->Clone();
1960 : }
1961 :
1962 : /* -------------------------------------------------------------------- */
1963 : /* Handle request for distinct list record. */
1964 : /* -------------------------------------------------------------------- */
1965 1110 : if (psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
1966 : {
1967 102 : if (!PrepareSummary())
1968 2 : return nullptr;
1969 :
1970 100 : if (psSelectInfo->column_summary.empty())
1971 1 : return nullptr;
1972 :
1973 99 : swq_summary &oSummary = psSelectInfo->column_summary[0];
1974 99 : if (psSelectInfo->order_specs == 0)
1975 : {
1976 18 : if (nFID < 0 || nFID >= static_cast<GIntBig>(
1977 9 : oSummary.oVectorDistinctValues.size()))
1978 : {
1979 1 : return nullptr;
1980 : }
1981 8 : const size_t nIdx = static_cast<size_t>(nFID);
1982 8 : if (oSummary.oVectorDistinctValues[nIdx] != SZ_OGR_NULL)
1983 : {
1984 12 : m_poSummaryFeature->SetField(
1985 6 : 0, oSummary.oVectorDistinctValues[nIdx].c_str());
1986 : }
1987 : else
1988 2 : m_poSummaryFeature->SetFieldNull(0);
1989 : }
1990 : else
1991 : {
1992 90 : if (m_aosDistinctList.empty())
1993 : {
1994 : std::set<CPLString, swq_summary::Comparator>::const_iterator
1995 18 : oIter = oSummary.oSetDistinctValues.begin();
1996 : std::set<CPLString, swq_summary::Comparator>::const_iterator
1997 18 : oEnd = oSummary.oSetDistinctValues.end();
1998 : try
1999 : {
2000 18 : m_aosDistinctList.reserve(
2001 : oSummary.oSetDistinctValues.size());
2002 108 : for (; oIter != oEnd; ++oIter)
2003 : {
2004 90 : m_aosDistinctList.push_back(*oIter);
2005 : }
2006 : }
2007 0 : catch (std::bad_alloc &)
2008 : {
2009 0 : return nullptr;
2010 : }
2011 18 : oSummary.oSetDistinctValues.clear();
2012 : }
2013 :
2014 180 : if (nFID < 0 ||
2015 90 : nFID >= static_cast<GIntBig>(m_aosDistinctList.size()))
2016 8 : return nullptr;
2017 :
2018 82 : const size_t nIdx = static_cast<size_t>(nFID);
2019 82 : if (m_aosDistinctList[nIdx] != SZ_OGR_NULL)
2020 144 : m_poSummaryFeature->SetField(0,
2021 72 : m_aosDistinctList[nIdx].c_str());
2022 : else
2023 10 : m_poSummaryFeature->SetFieldNull(0);
2024 : }
2025 :
2026 90 : m_poSummaryFeature->SetFID(nFID);
2027 :
2028 90 : return m_poSummaryFeature->Clone();
2029 : }
2030 :
2031 : /* -------------------------------------------------------------------- */
2032 : /* Handle request for random record. */
2033 : /* -------------------------------------------------------------------- */
2034 : auto poSrcFeature =
2035 2016 : std::unique_ptr<OGRFeature>(m_poSrcLayer->GetFeature(nFID));
2036 1008 : if (poSrcFeature == nullptr)
2037 3 : return nullptr;
2038 :
2039 1005 : return TranslateFeature(std::move(poSrcFeature)).release();
2040 : }
2041 :
2042 : /************************************************************************/
2043 : /* GetSpatialFilter() */
2044 : /************************************************************************/
2045 :
2046 1 : OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
2047 :
2048 : {
2049 1 : return nullptr;
2050 : }
2051 :
2052 : /************************************************************************/
2053 : /* GetLayerDefn() */
2054 : /************************************************************************/
2055 :
2056 4597 : OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
2057 :
2058 : {
2059 4597 : swq_select *psSelectInfo = m_pSelectInfo.get();
2060 4597 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD && !m_poSummaryFeature)
2061 : {
2062 : // Run PrepareSummary() is we have a COUNT column so as to be
2063 : // able to downcast it from OFTInteger64 to OFTInteger
2064 19 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
2065 : {
2066 15 : swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
2067 15 : if (psColDef->col_func == SWQCF_COUNT)
2068 : {
2069 5 : PrepareSummary();
2070 5 : break;
2071 : }
2072 : }
2073 : }
2074 :
2075 4597 : return m_poDefn;
2076 : }
2077 :
2078 : /************************************************************************/
2079 : /* FreeIndexFields() */
2080 : /************************************************************************/
2081 :
2082 167 : void OGRGenSQLResultsLayer::FreeIndexFields(OGRField *pasIndexFields,
2083 : size_t l_nIndexSize)
2084 : {
2085 167 : swq_select *psSelectInfo = m_pSelectInfo.get();
2086 167 : const int nOrderItems = psSelectInfo->order_specs;
2087 :
2088 : /* -------------------------------------------------------------------- */
2089 : /* Free the key field values. */
2090 : /* -------------------------------------------------------------------- */
2091 437 : for (int iKey = 0; iKey < nOrderItems; iKey++)
2092 : {
2093 270 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2094 :
2095 270 : if (psKeyDef->field_index >= m_iFIDFieldIndex)
2096 : {
2097 5 : CPLAssert(psKeyDef->field_index <
2098 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2099 : /* warning: only special fields of type string should be deallocated
2100 : */
2101 5 : if (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex] ==
2102 : SWQ_STRING)
2103 : {
2104 11 : for (size_t i = 0; i < l_nIndexSize; i++)
2105 : {
2106 10 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
2107 10 : CPLFree(psField->String);
2108 : }
2109 : }
2110 5 : continue;
2111 : }
2112 :
2113 : OGRFieldDefn *poFDefn =
2114 265 : m_poSrcLayer->GetLayerDefn()->GetFieldDefn(psKeyDef->field_index);
2115 :
2116 265 : if (poFDefn->GetType() == OFTString)
2117 : {
2118 377 : for (size_t i = 0; i < l_nIndexSize; i++)
2119 : {
2120 261 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
2121 :
2122 522 : if (!OGR_RawField_IsUnset(psField) &&
2123 261 : !OGR_RawField_IsNull(psField))
2124 250 : CPLFree(psField->String);
2125 : }
2126 : }
2127 : }
2128 167 : }
2129 :
2130 : /************************************************************************/
2131 : /* ReadIndexFields() */
2132 : /************************************************************************/
2133 :
2134 1419 : void OGRGenSQLResultsLayer::ReadIndexFields(OGRFeature *poSrcFeat,
2135 : int nOrderItems,
2136 : OGRField *pasIndexFields)
2137 : {
2138 1419 : swq_select *psSelectInfo = m_pSelectInfo.get();
2139 3040 : for (int iKey = 0; iKey < nOrderItems; iKey++)
2140 : {
2141 1621 : const swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2142 1621 : OGRField *psDstField = pasIndexFields + iKey;
2143 :
2144 1621 : if (psKeyDef->field_index >= m_iFIDFieldIndex)
2145 : {
2146 34 : CPLAssert(psKeyDef->field_index <
2147 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2148 :
2149 34 : switch (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex])
2150 : {
2151 14 : case SWQ_INTEGER:
2152 : case SWQ_INTEGER64:
2153 : // Yes, store Integer as Integer64.
2154 : // This is consistent with the test in Compare()
2155 14 : psDstField->Integer64 =
2156 14 : poSrcFeat->GetFieldAsInteger64(psKeyDef->field_index);
2157 14 : break;
2158 :
2159 10 : case SWQ_FLOAT:
2160 10 : psDstField->Real =
2161 10 : poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
2162 10 : break;
2163 :
2164 10 : default:
2165 10 : psDstField->String = CPLStrdup(
2166 10 : poSrcFeat->GetFieldAsString(psKeyDef->field_index));
2167 10 : break;
2168 : }
2169 :
2170 34 : continue;
2171 : }
2172 :
2173 : OGRFieldDefn *poFDefn =
2174 1587 : m_poSrcLayer->GetLayerDefn()->GetFieldDefn(psKeyDef->field_index);
2175 :
2176 1587 : OGRField *psSrcField = poSrcFeat->GetRawFieldRef(psKeyDef->field_index);
2177 :
2178 1972 : if (poFDefn->GetType() == OFTInteger ||
2179 728 : poFDefn->GetType() == OFTInteger64 ||
2180 865 : poFDefn->GetType() == OFTReal || poFDefn->GetType() == OFTDate ||
2181 2233 : poFDefn->GetType() == OFTTime || poFDefn->GetType() == OFTDateTime)
2182 1328 : memcpy(psDstField, psSrcField, sizeof(OGRField));
2183 259 : else if (poFDefn->GetType() == OFTString)
2184 : {
2185 259 : if (poSrcFeat->IsFieldSetAndNotNull(psKeyDef->field_index))
2186 248 : psDstField->String = CPLStrdup(psSrcField->String);
2187 : else
2188 11 : memcpy(psDstField, psSrcField, sizeof(OGRField));
2189 : }
2190 : }
2191 1419 : }
2192 :
2193 : /************************************************************************/
2194 : /* CreateOrderByIndex() */
2195 : /* */
2196 : /* This method is responsible for creating an index providing */
2197 : /* ordered access to the features according to the supplied */
2198 : /* ORDER BY clauses. */
2199 : /* */
2200 : /* This is accomplished by making one pass through all the */
2201 : /* eligible source features, and capturing the order by fields */
2202 : /* of all records in memory. A quick sort is then applied to */
2203 : /* this in memory copy of the order-by fields to create the */
2204 : /* required index. */
2205 : /* */
2206 : /* Keeping all the key values in memory will *not* scale up to */
2207 : /* very large input datasets. */
2208 : /************************************************************************/
2209 :
2210 5619 : void OGRGenSQLResultsLayer::CreateOrderByIndex()
2211 :
2212 : {
2213 5619 : swq_select *psSelectInfo = m_pSelectInfo.get();
2214 5619 : const int nOrderItems = psSelectInfo->order_specs;
2215 :
2216 5619 : if (!(nOrderItems > 0 && psSelectInfo->query_mode == SWQM_RECORDSET))
2217 5577 : return;
2218 :
2219 2306 : if (m_bOrderByValid)
2220 2260 : return;
2221 :
2222 46 : m_bOrderByValid = true;
2223 46 : m_anFIDIndex.clear();
2224 :
2225 46 : ResetReading();
2226 :
2227 : /* -------------------------------------------------------------------- */
2228 : /* Optimize (memory-wise) ORDER BY ... LIMIT 1 [OFFSET 0] case. */
2229 : /* -------------------------------------------------------------------- */
2230 46 : if (psSelectInfo->offset == 0 && psSelectInfo->limit == 1)
2231 : {
2232 8 : std::vector<OGRField> asCurrentFields(nOrderItems);
2233 4 : std::vector<OGRField> asBestFields(nOrderItems);
2234 4 : memset(asCurrentFields.data(), 0, sizeof(OGRField) * nOrderItems);
2235 4 : memset(asBestFields.data(), 0, sizeof(OGRField) * nOrderItems);
2236 4 : bool bFoundSrcFeature = false;
2237 4 : GIntBig nBestFID = 0;
2238 125 : for (auto &&poSrcFeat : *m_poSrcLayer)
2239 : {
2240 121 : ReadIndexFields(poSrcFeat.get(), nOrderItems,
2241 : asCurrentFields.data());
2242 239 : if (!bFoundSrcFeature ||
2243 118 : Compare(asCurrentFields.data(), asBestFields.data()) < 0)
2244 : {
2245 107 : bFoundSrcFeature = true;
2246 107 : nBestFID = poSrcFeat->GetFID();
2247 107 : FreeIndexFields(asBestFields.data(), 1);
2248 107 : memcpy(asBestFields.data(), asCurrentFields.data(),
2249 107 : sizeof(OGRField) * nOrderItems);
2250 : }
2251 : else
2252 : {
2253 14 : FreeIndexFields(asCurrentFields.data(), 1);
2254 : }
2255 121 : memset(asCurrentFields.data(), 0, sizeof(OGRField) * nOrderItems);
2256 : }
2257 4 : FreeIndexFields(asBestFields.data(), 1);
2258 :
2259 4 : if (bFoundSrcFeature)
2260 : {
2261 3 : m_anFIDIndex.resize(1);
2262 3 : m_anFIDIndex[0] = nBestFID;
2263 : }
2264 4 : return;
2265 : }
2266 :
2267 : /* -------------------------------------------------------------------- */
2268 : /* Allocate set of key values, and the output index. */
2269 : /* -------------------------------------------------------------------- */
2270 42 : size_t nFeaturesAlloc = 100;
2271 42 : size_t nIndexSize = 0;
2272 42 : std::vector<OGRField> asIndexFields(nOrderItems * nFeaturesAlloc);
2273 84 : memset(asIndexFields.data(), 0,
2274 42 : sizeof(OGRField) * nOrderItems * nFeaturesAlloc);
2275 42 : std::vector<GIntBig> anFIDList;
2276 :
2277 : // Frees nIndexSize rows of asIndexFields
2278 : struct IndexFieldsFreer
2279 : {
2280 : OGRGenSQLResultsLayer &m_oLayer;
2281 : std::vector<OGRField> &m_asIndexFields;
2282 : size_t &m_nIndexSize;
2283 :
2284 42 : IndexFieldsFreer(OGRGenSQLResultsLayer &poLayerIn,
2285 : std::vector<OGRField> &asIndexFieldsIn,
2286 : size_t &nIndexSizeIn)
2287 42 : : m_oLayer(poLayerIn), m_asIndexFields(asIndexFieldsIn),
2288 42 : m_nIndexSize(nIndexSizeIn)
2289 : {
2290 42 : }
2291 :
2292 42 : ~IndexFieldsFreer()
2293 42 : {
2294 42 : m_oLayer.FreeIndexFields(m_asIndexFields.data(), m_nIndexSize);
2295 42 : }
2296 :
2297 : IndexFieldsFreer(const IndexFieldsFreer &) = delete;
2298 : IndexFieldsFreer &operator=(const IndexFieldsFreer &) = delete;
2299 : };
2300 :
2301 42 : IndexFieldsFreer oIndexFieldsFreer(*this, asIndexFields, nIndexSize);
2302 :
2303 : /* -------------------------------------------------------------------- */
2304 : /* Read in all the key values. */
2305 : /* -------------------------------------------------------------------- */
2306 :
2307 1340 : for (auto &&poSrcFeat : *m_poSrcLayer)
2308 : {
2309 1298 : if (nIndexSize == nFeaturesAlloc)
2310 : {
2311 10 : const uint64_t nNewFeaturesAlloc64 =
2312 10 : static_cast<uint64_t>(nFeaturesAlloc) + nFeaturesAlloc / 3;
2313 : #if SIZEOF_SIZE_T == 4
2314 : if (static_cast<size_t>(nNewFeaturesAlloc64) !=
2315 : nNewFeaturesAlloc64 ||
2316 : static_cast<size_t>(sizeof(OGRField) * nOrderItems *
2317 : nNewFeaturesAlloc64) !=
2318 : static_cast<uint64_t>(sizeof(OGRField)) * nOrderItems *
2319 : nNewFeaturesAlloc64)
2320 : {
2321 : CPLError(CE_Failure, CPLE_AppDefined,
2322 : "Cannot allocate pasIndexFields");
2323 : return;
2324 : }
2325 : #endif
2326 10 : const size_t nNewFeaturesAlloc =
2327 : static_cast<size_t>(nNewFeaturesAlloc64);
2328 :
2329 : try
2330 : {
2331 10 : asIndexFields.resize(nOrderItems * nNewFeaturesAlloc);
2332 10 : anFIDList.reserve(nNewFeaturesAlloc);
2333 : }
2334 0 : catch (const std::bad_alloc &)
2335 : {
2336 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
2337 : "CreateOrderByIndex(): out of memory");
2338 0 : return;
2339 : }
2340 :
2341 20 : memset(asIndexFields.data() + nFeaturesAlloc * nOrderItems, 0,
2342 10 : sizeof(OGRField) * nOrderItems *
2343 10 : (nNewFeaturesAlloc - nFeaturesAlloc));
2344 :
2345 10 : nFeaturesAlloc = nNewFeaturesAlloc;
2346 : }
2347 :
2348 1298 : ReadIndexFields(poSrcFeat.get(), nOrderItems,
2349 1298 : asIndexFields.data() + nIndexSize * nOrderItems);
2350 :
2351 1298 : anFIDList.push_back(poSrcFeat->GetFID());
2352 :
2353 1298 : nIndexSize++;
2354 : }
2355 :
2356 : // CPLDebug("GenSQL", "CreateOrderByIndex() = %zu features", nIndexSize);
2357 :
2358 : /* -------------------------------------------------------------------- */
2359 : /* Initialize m_anFIDIndex */
2360 : /* -------------------------------------------------------------------- */
2361 : try
2362 : {
2363 42 : m_anFIDIndex.reserve(nIndexSize);
2364 : }
2365 0 : catch (const std::bad_alloc &)
2366 : {
2367 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
2368 : "CreateOrderByIndex(): out of memory");
2369 0 : return;
2370 : }
2371 1340 : for (size_t i = 0; i < nIndexSize; i++)
2372 1298 : m_anFIDIndex.push_back(static_cast<GIntBig>(i));
2373 :
2374 : /* -------------------------------------------------------------------- */
2375 : /* Quick sort the records. */
2376 : /* -------------------------------------------------------------------- */
2377 :
2378 : GIntBig *panMerged = static_cast<GIntBig *>(
2379 42 : VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nIndexSize));
2380 42 : if (panMerged == nullptr)
2381 : {
2382 0 : m_anFIDIndex.clear();
2383 0 : return;
2384 : }
2385 :
2386 : // Note: this merge sort is slightly faster than std::sort()
2387 42 : SortIndexSection(asIndexFields.data(), panMerged, 0, nIndexSize);
2388 42 : VSIFree(panMerged);
2389 :
2390 : /* -------------------------------------------------------------------- */
2391 : /* Rework the FID map to map to real FIDs. */
2392 : /* -------------------------------------------------------------------- */
2393 42 : bool bAlreadySorted = true;
2394 1340 : for (size_t i = 0; i < nIndexSize; i++)
2395 : {
2396 1298 : if (m_anFIDIndex[i] != static_cast<GIntBig>(i))
2397 716 : bAlreadySorted = false;
2398 1298 : m_anFIDIndex[i] = anFIDList[static_cast<size_t>(m_anFIDIndex[i])];
2399 : }
2400 :
2401 : /* If it is already sorted, then free than m_anFIDIndex array */
2402 : /* so that GetNextFeature() can call a sequential GetNextFeature() */
2403 : /* on the source array. Very useful for layers where random access */
2404 : /* is slow. */
2405 : /* Use case: the GML result of a WFS GetFeature with a SORTBY */
2406 42 : if (bAlreadySorted)
2407 : {
2408 23 : m_anFIDIndex.clear();
2409 : }
2410 :
2411 42 : ResetReading();
2412 : }
2413 :
2414 : /************************************************************************/
2415 : /* SortIndexSection() */
2416 : /* */
2417 : /* Sort the records in a section of the index. */
2418 : /************************************************************************/
2419 :
2420 2556 : void OGRGenSQLResultsLayer::SortIndexSection(const OGRField *pasIndexFields,
2421 : GIntBig *panMerged, size_t nStart,
2422 : size_t nEntries)
2423 :
2424 : {
2425 2556 : if (nEntries < 2)
2426 1299 : return;
2427 :
2428 1257 : swq_select *psSelectInfo = m_pSelectInfo.get();
2429 1257 : const int nOrderItems = psSelectInfo->order_specs;
2430 :
2431 1257 : size_t nFirstGroup = nEntries / 2;
2432 1257 : size_t nFirstStart = nStart;
2433 1257 : size_t nSecondGroup = nEntries - nFirstGroup;
2434 1257 : size_t nSecondStart = nStart + nFirstGroup;
2435 :
2436 1257 : SortIndexSection(pasIndexFields, panMerged, nFirstStart, nFirstGroup);
2437 1257 : SortIndexSection(pasIndexFields, panMerged, nSecondStart, nSecondGroup);
2438 :
2439 12507 : for (size_t iMerge = 0; iMerge < nEntries; ++iMerge)
2440 : {
2441 11250 : int nResult = 0;
2442 :
2443 11250 : if (nFirstGroup == 0)
2444 1448 : nResult = 1;
2445 9802 : else if (nSecondGroup == 0)
2446 1616 : nResult = -1;
2447 : else
2448 8186 : nResult = Compare(
2449 8186 : pasIndexFields + m_anFIDIndex[nFirstStart] * nOrderItems,
2450 8186 : pasIndexFields + m_anFIDIndex[nSecondStart] * nOrderItems);
2451 :
2452 11250 : if (nResult > 0)
2453 : {
2454 5729 : panMerged[iMerge] = m_anFIDIndex[nSecondStart];
2455 5729 : nSecondStart++;
2456 5729 : nSecondGroup--;
2457 : }
2458 : else
2459 : {
2460 5521 : panMerged[iMerge] = m_anFIDIndex[nFirstStart];
2461 5521 : nFirstStart++;
2462 5521 : nFirstGroup--;
2463 : }
2464 : }
2465 :
2466 : /* Copy the merge list back into the main index */
2467 1257 : memcpy(m_anFIDIndex.data() + nStart, panMerged, sizeof(GIntBig) * nEntries);
2468 : }
2469 :
2470 : /************************************************************************/
2471 : /* ComparePrimitive() */
2472 : /************************************************************************/
2473 :
2474 8128 : template <class T> static inline int ComparePrimitive(const T &a, const T &b)
2475 : {
2476 8128 : if (a < b)
2477 3922 : return -1;
2478 4206 : if (a > b)
2479 4206 : return 1;
2480 0 : return 0;
2481 : }
2482 :
2483 : /************************************************************************/
2484 : /* Compare() */
2485 : /************************************************************************/
2486 :
2487 8304 : int OGRGenSQLResultsLayer::Compare(const OGRField *pasFirstTuple,
2488 : const OGRField *pasSecondTuple)
2489 :
2490 : {
2491 8304 : swq_select *psSelectInfo = m_pSelectInfo.get();
2492 8304 : int nResult = 0, iKey;
2493 :
2494 16608 : for (iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++)
2495 : {
2496 8304 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2497 8304 : OGRFieldDefn *poFDefn = nullptr;
2498 :
2499 8304 : if (psKeyDef->field_index >= m_iFIDFieldIndex)
2500 58 : poFDefn = nullptr;
2501 : else
2502 16492 : poFDefn = m_poSrcLayer->GetLayerDefn()->GetFieldDefn(
2503 8246 : psKeyDef->field_index);
2504 :
2505 16608 : if (OGR_RawField_IsUnset(&pasFirstTuple[iKey]) ||
2506 8304 : OGR_RawField_IsNull(&pasFirstTuple[iKey]))
2507 : {
2508 62 : if (OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2509 31 : OGR_RawField_IsNull(&pasSecondTuple[iKey]))
2510 22 : nResult = 0;
2511 : else
2512 9 : nResult = -1;
2513 : }
2514 16546 : else if (OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2515 8273 : OGR_RawField_IsNull(&pasSecondTuple[iKey]))
2516 : {
2517 18 : nResult = 1;
2518 : }
2519 8255 : else if (poFDefn == nullptr)
2520 : {
2521 58 : CPLAssert(psKeyDef->field_index <
2522 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2523 58 : switch (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex])
2524 : {
2525 21 : case SWQ_INTEGER:
2526 : // Yes, read Integer in Integer64.
2527 : // This is consistent with what is done ReadIndexFields()
2528 : case SWQ_INTEGER64:
2529 21 : nResult = ComparePrimitive(pasFirstTuple[iKey].Integer64,
2530 21 : pasSecondTuple[iKey].Integer64);
2531 21 : break;
2532 22 : case SWQ_FLOAT:
2533 22 : nResult = ComparePrimitive(pasFirstTuple[iKey].Real,
2534 22 : pasSecondTuple[iKey].Real);
2535 22 : break;
2536 15 : case SWQ_STRING:
2537 15 : nResult = strcmp(pasFirstTuple[iKey].String,
2538 15 : pasSecondTuple[iKey].String);
2539 15 : break;
2540 :
2541 0 : default:
2542 0 : CPLAssert(false);
2543 : nResult = 0;
2544 : }
2545 : }
2546 8197 : else if (poFDefn->GetType() == OFTInteger)
2547 : {
2548 7938 : nResult = ComparePrimitive(pasFirstTuple[iKey].Integer,
2549 7938 : pasSecondTuple[iKey].Integer);
2550 : }
2551 259 : else if (poFDefn->GetType() == OFTInteger64)
2552 : {
2553 68 : nResult = ComparePrimitive(pasFirstTuple[iKey].Integer64,
2554 68 : pasSecondTuple[iKey].Integer64);
2555 : }
2556 191 : else if (poFDefn->GetType() == OFTString)
2557 : {
2558 : nResult =
2559 111 : strcmp(pasFirstTuple[iKey].String, pasSecondTuple[iKey].String);
2560 : }
2561 80 : else if (poFDefn->GetType() == OFTReal)
2562 : {
2563 79 : nResult = ComparePrimitive(pasFirstTuple[iKey].Real,
2564 79 : pasSecondTuple[iKey].Real);
2565 : }
2566 2 : else if (poFDefn->GetType() == OFTDate ||
2567 2 : poFDefn->GetType() == OFTTime ||
2568 1 : poFDefn->GetType() == OFTDateTime)
2569 : {
2570 : nResult =
2571 1 : OGRCompareDate(&pasFirstTuple[iKey], &pasSecondTuple[iKey]);
2572 : }
2573 :
2574 8304 : if (!(psKeyDef->ascending_flag))
2575 64 : nResult *= -1;
2576 : }
2577 :
2578 8304 : return nResult;
2579 : }
2580 :
2581 : /************************************************************************/
2582 : /* AddFieldDefnToSet() */
2583 : /************************************************************************/
2584 :
2585 17198 : void OGRGenSQLResultsLayer::AddFieldDefnToSet(int iTable, int iColumn,
2586 : CPLHashSet *hSet)
2587 : {
2588 17198 : if (iTable != -1)
2589 : {
2590 15370 : OGRLayer *poLayer = m_apoTableLayers[iTable];
2591 15370 : const auto poLayerDefn = poLayer->GetLayerDefn();
2592 15370 : const int nFieldCount = poLayerDefn->GetFieldCount();
2593 15370 : if (iColumn == -1)
2594 : {
2595 3026 : for (int i = 0; i < nFieldCount; ++i)
2596 : {
2597 2716 : OGRFieldDefn *poFDefn = poLayerDefn->GetFieldDefn(i);
2598 2716 : CPLHashSetInsert(hSet, poFDefn);
2599 : }
2600 :
2601 310 : const int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
2602 557 : for (int i = 0; i < nGeomFieldCount; ++i)
2603 : {
2604 247 : OGRGeomFieldDefn *poFDefn = poLayerDefn->GetGeomFieldDefn(i);
2605 247 : CPLHashSetInsert(hSet, poFDefn);
2606 : }
2607 : }
2608 : else
2609 : {
2610 15060 : if (iColumn < nFieldCount)
2611 : {
2612 13338 : OGRFieldDefn *poFDefn = poLayerDefn->GetFieldDefn(iColumn);
2613 13338 : CPLHashSetInsert(hSet, poFDefn);
2614 : }
2615 1722 : else if (iColumn == nFieldCount + SPF_OGR_GEOMETRY ||
2616 1709 : iColumn == nFieldCount + SPF_OGR_GEOM_WKT ||
2617 1708 : iColumn == nFieldCount + SPF_OGR_GEOM_AREA)
2618 : {
2619 19 : auto poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(0);
2620 19 : CPLHashSetInsert(hSet, poSrcGFDefn);
2621 : }
2622 1703 : else if (IS_GEOM_FIELD_INDEX(poLayerDefn, iColumn))
2623 : {
2624 : const int iSrcGeomField =
2625 1519 : ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(poLayerDefn, iColumn);
2626 1519 : auto poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
2627 1519 : CPLHashSetInsert(hSet, poSrcGFDefn);
2628 : }
2629 : }
2630 : }
2631 17198 : }
2632 :
2633 : /************************************************************************/
2634 : /* ExploreExprForIgnoredFields() */
2635 : /************************************************************************/
2636 :
2637 5625 : void OGRGenSQLResultsLayer::ExploreExprForIgnoredFields(swq_expr_node *expr,
2638 : CPLHashSet *hSet)
2639 : {
2640 5625 : if (expr->eNodeType == SNT_COLUMN)
2641 : {
2642 1997 : AddFieldDefnToSet(expr->table_index, expr->field_index, hSet);
2643 : }
2644 3628 : else if (expr->eNodeType == SNT_OPERATION)
2645 : {
2646 4253 : for (int i = 0; i < expr->nSubExprCount; i++)
2647 2821 : ExploreExprForIgnoredFields(expr->papoSubExpr[i], hSet);
2648 : }
2649 5625 : }
2650 :
2651 : /************************************************************************/
2652 : /* FindAndSetIgnoredFields() */
2653 : /************************************************************************/
2654 :
2655 2155 : void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
2656 : {
2657 2155 : swq_select *psSelectInfo = m_pSelectInfo.get();
2658 : CPLHashSet *hSet =
2659 2155 : CPLHashSetNew(CPLHashSetHashPointer, CPLHashSetEqualPointer, nullptr);
2660 :
2661 : /* -------------------------------------------------------------------- */
2662 : /* 1st phase : explore the whole select infos to determine which */
2663 : /* source fields are used */
2664 : /* -------------------------------------------------------------------- */
2665 17275 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
2666 : {
2667 15120 : swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
2668 15120 : AddFieldDefnToSet(psColDef->table_index, psColDef->field_index, hSet);
2669 15120 : if (psColDef->expr)
2670 1828 : ExploreExprForIgnoredFields(psColDef->expr, hSet);
2671 : }
2672 :
2673 2155 : if (psSelectInfo->where_expr)
2674 946 : ExploreExprForIgnoredFields(psSelectInfo->where_expr, hSet);
2675 :
2676 2185 : for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
2677 : {
2678 30 : swq_join_def *psJoinDef = psSelectInfo->join_defs + iJoin;
2679 30 : ExploreExprForIgnoredFields(psJoinDef->poExpr, hSet);
2680 : }
2681 :
2682 2236 : for (int iOrder = 0; iOrder < psSelectInfo->order_specs; iOrder++)
2683 : {
2684 81 : swq_order_def *psOrderDef = psSelectInfo->order_defs + iOrder;
2685 81 : AddFieldDefnToSet(psOrderDef->table_index, psOrderDef->field_index,
2686 : hSet);
2687 : }
2688 :
2689 : /* -------------------------------------------------------------------- */
2690 : /* 2nd phase : now, we can exclude the unused fields */
2691 : /* -------------------------------------------------------------------- */
2692 4340 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
2693 : {
2694 2185 : OGRLayer *poLayer = m_apoTableLayers[iTable];
2695 2185 : OGRFeatureDefn *poSrcFDefn = poLayer->GetLayerDefn();
2696 2185 : char **papszIgnoredFields = nullptr;
2697 2185 : const int nSrcFieldCount = poSrcFDefn->GetFieldCount();
2698 18074 : for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
2699 : {
2700 15889 : OGRFieldDefn *poFDefn = poSrcFDefn->GetFieldDefn(iSrcField);
2701 15889 : if (CPLHashSetLookup(hSet, poFDefn) == nullptr)
2702 : {
2703 : papszIgnoredFields =
2704 1200 : CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
2705 : // CPLDebug("OGR", "Adding %s to the list of ignored fields of
2706 : // layer %s",
2707 : // poFDefn->GetNameRef(), poLayer->GetName());
2708 : }
2709 : }
2710 2185 : const int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
2711 4004 : for (int iSrcField = 0; iSrcField < nSrcGeomFieldCount; iSrcField++)
2712 : {
2713 1819 : OGRGeomFieldDefn *poFDefn = poSrcFDefn->GetGeomFieldDefn(iSrcField);
2714 1819 : if (CPLHashSetLookup(hSet, poFDefn) == nullptr)
2715 : {
2716 : papszIgnoredFields =
2717 74 : CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
2718 : // CPLDebug("OGR", "Adding %s to the list of ignored fields of
2719 : // layer %s",
2720 : // poFDefn->GetNameRef(), poLayer->GetName());
2721 : }
2722 : }
2723 2185 : poLayer->SetIgnoredFields(
2724 2185 : const_cast<const char **>(papszIgnoredFields));
2725 2185 : CSLDestroy(papszIgnoredFields);
2726 : }
2727 :
2728 2155 : CPLHashSetDestroy(hSet);
2729 2155 : }
2730 :
2731 : /************************************************************************/
2732 : /* InvalidateOrderByIndex() */
2733 : /************************************************************************/
2734 :
2735 389 : void OGRGenSQLResultsLayer::InvalidateOrderByIndex()
2736 : {
2737 389 : m_anFIDIndex.clear();
2738 389 : m_bOrderByValid = false;
2739 389 : }
2740 :
2741 : /************************************************************************/
2742 : /* SetAttributeFilter() */
2743 : /************************************************************************/
2744 :
2745 46 : OGRErr OGRGenSQLResultsLayer::SetAttributeFilter(const char *pszAttributeFilter)
2746 : {
2747 : const std::string osAdditionalWHERE =
2748 92 : pszAttributeFilter ? pszAttributeFilter : "";
2749 92 : std::string osWHERE;
2750 46 : if (!m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty())
2751 : {
2752 3 : if (!osAdditionalWHERE.empty())
2753 2 : osWHERE += '(';
2754 3 : osWHERE += m_osInitialWHERE;
2755 3 : if (!osAdditionalWHERE.empty())
2756 2 : osWHERE += ") AND (";
2757 : }
2758 46 : osWHERE += osAdditionalWHERE;
2759 49 : if (!m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty() &&
2760 3 : !osAdditionalWHERE.empty())
2761 : {
2762 2 : osWHERE += ')';
2763 : }
2764 46 : InvalidateOrderByIndex();
2765 61 : return OGRLayer::SetAttributeFilter(osWHERE.empty() ? nullptr
2766 107 : : osWHERE.c_str());
2767 : }
2768 :
2769 : /************************************************************************/
2770 : /* SetSpatialFilter() */
2771 : /************************************************************************/
2772 :
2773 343 : void OGRGenSQLResultsLayer::SetSpatialFilter(int iGeomField,
2774 : OGRGeometry *poGeom)
2775 : {
2776 343 : InvalidateOrderByIndex();
2777 343 : if (iGeomField == 0)
2778 337 : OGRLayer::SetSpatialFilter(poGeom);
2779 : else
2780 6 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
2781 343 : }
2782 :
2783 : /************************************************************************/
2784 : /* OGRGenSQLResultsLayerArrowStreamPrivateData */
2785 : /************************************************************************/
2786 :
2787 : // Structure whose instances are set on the ArrowArrayStream::private_data
2788 : // member of the ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2789 : struct OGRGenSQLResultsLayerArrowStreamPrivateData
2790 : {
2791 : // Member shared with OGRLayer::m_poSharedArrowArrayStreamPrivateData
2792 : // If the layer pointed by poShared->poLayer is destroyed, before its
2793 : // destruction, it nullifies poShared->poLayer, which we can detect.
2794 : std::shared_ptr<OGRLayer::ArrowArrayStreamPrivateData> poShared{};
2795 :
2796 : // ArrowArrayStream to be used with poShared->poLayer
2797 : struct ArrowArrayStream *psSrcLayerStream = nullptr;
2798 :
2799 : // Original release() callback of the ArrowArrayStream passed to
2800 : // OGRGenSQLResultsLayer::GetArrowStream()
2801 : void (*release_backup)(struct ArrowArrayStream *) = nullptr;
2802 :
2803 : // Original private_data member of the ArrowArrayStream passed to
2804 : // OGRGenSQLResultsLayer::GetArrowStream()
2805 : void *private_data_backup = nullptr;
2806 :
2807 : // Set as the ArrowArrayStream::release callback member of the
2808 : // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2809 5 : static void Release(struct ArrowArrayStream *self)
2810 : {
2811 5 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2812 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2813 : self->private_data);
2814 :
2815 : // Release source layer stream
2816 5 : if (psPrivateData->psSrcLayerStream->release)
2817 5 : psPrivateData->psSrcLayerStream->release(
2818 : psPrivateData->psSrcLayerStream);
2819 5 : CPLFree(psPrivateData->psSrcLayerStream);
2820 :
2821 : // Release ourselves using the base method
2822 5 : self->private_data = psPrivateData->private_data_backup;
2823 5 : self->release = psPrivateData->release_backup;
2824 5 : delete psPrivateData;
2825 5 : if (self->release)
2826 5 : self->release(self);
2827 5 : }
2828 :
2829 : // Set as the ArrowArrayStream::get_schema callback member of the
2830 : // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2831 5 : static int GetSchema(struct ArrowArrayStream *self, struct ArrowSchema *out)
2832 : {
2833 5 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2834 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2835 : self->private_data);
2836 0 : auto poLayer = dynamic_cast<OGRGenSQLResultsLayer *>(
2837 5 : psPrivateData->poShared->m_poLayer);
2838 5 : if (!poLayer)
2839 : {
2840 0 : CPLError(
2841 : CE_Failure, CPLE_NotSupported,
2842 : "Calling get_schema() on a freed OGRLayer is not supported");
2843 0 : return EINVAL;
2844 : }
2845 5 : return poLayer->GetArrowSchemaForwarded(self, out);
2846 : }
2847 :
2848 : // Set as the ArrowArrayStream::get_next callback member of the
2849 : // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2850 9 : static int GetNext(struct ArrowArrayStream *self, struct ArrowArray *out)
2851 : {
2852 9 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2853 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2854 : self->private_data);
2855 1 : auto poLayer = dynamic_cast<OGRGenSQLResultsLayer *>(
2856 9 : psPrivateData->poShared->m_poLayer);
2857 9 : if (!poLayer)
2858 : {
2859 1 : CPLError(CE_Failure, CPLE_NotSupported,
2860 : "Calling get_next() on a freed OGRLayer is not supported");
2861 1 : return EINVAL;
2862 : }
2863 8 : return poLayer->GetNextArrowArrayForwarded(self, out);
2864 : }
2865 : };
2866 :
2867 : /************************************************************************/
2868 : /* GetArrowStream() */
2869 : /************************************************************************/
2870 :
2871 12 : bool OGRGenSQLResultsLayer::GetArrowStream(struct ArrowArrayStream *out_stream,
2872 : CSLConstList papszOptions)
2873 : {
2874 17 : if (!TestCapability(OLCFastGetArrowStream) ||
2875 5 : CPLTestBool(CPLGetConfigOption("OGR_GENSQL_STREAM_BASE_IMPL", "NO")))
2876 : {
2877 14 : CPLStringList aosOptions(papszOptions);
2878 7 : aosOptions.SetNameValue("OGR_GENSQL_STREAM_BASE_IMPL", "YES");
2879 7 : return OGRLayer::GetArrowStream(out_stream, aosOptions.List());
2880 : }
2881 :
2882 5 : const swq_select *psSelectInfo = m_pSelectInfo.get();
2883 5 : if (m_nIteratedFeatures != -1)
2884 : {
2885 0 : CPLError(CE_Failure, CPLE_AppDefined,
2886 : "GetArrowStream() not supported on non-rewinded layer");
2887 0 : return false;
2888 : }
2889 5 : CPLStringList aosOptions(papszOptions);
2890 5 : if (psSelectInfo->limit > 0)
2891 : {
2892 : aosOptions.SetNameValue(
2893 : "MAX_FEATURES_IN_BATCH",
2894 : CPLSPrintf(CPL_FRMT_GIB,
2895 1 : std::min(psSelectInfo->limit,
2896 2 : CPLAtoGIntBig(aosOptions.FetchNameValueDef(
2897 1 : "MAX_FEATURES_IN_BATCH", "65536")))));
2898 : }
2899 5 : bool bRet = OGRLayer::GetArrowStream(out_stream, aosOptions.List());
2900 5 : if (bRet)
2901 : {
2902 : auto psSrcLayerStream = static_cast<struct ArrowArrayStream *>(
2903 5 : CPLMalloc(sizeof(ArrowArrayStream)));
2904 5 : if (m_poSrcLayer->GetArrowStream(psSrcLayerStream, aosOptions.List()))
2905 : {
2906 : auto psPrivateData =
2907 5 : new OGRGenSQLResultsLayerArrowStreamPrivateData;
2908 5 : CPLAssert(m_poSharedArrowArrayStreamPrivateData);
2909 5 : psPrivateData->poShared = m_poSharedArrowArrayStreamPrivateData;
2910 5 : psPrivateData->psSrcLayerStream = psSrcLayerStream;
2911 5 : psPrivateData->release_backup = out_stream->release;
2912 5 : psPrivateData->private_data_backup = out_stream->private_data;
2913 5 : out_stream->get_schema =
2914 : OGRGenSQLResultsLayerArrowStreamPrivateData::GetSchema;
2915 5 : out_stream->get_next =
2916 : OGRGenSQLResultsLayerArrowStreamPrivateData::GetNext;
2917 5 : out_stream->release =
2918 : OGRGenSQLResultsLayerArrowStreamPrivateData::Release;
2919 5 : out_stream->private_data = psPrivateData;
2920 : }
2921 : else
2922 : {
2923 0 : if (psSrcLayerStream->release)
2924 0 : psSrcLayerStream->release(psSrcLayerStream);
2925 0 : CPLFree(psSrcLayerStream);
2926 0 : if (out_stream->release)
2927 0 : out_stream->release(out_stream);
2928 0 : bRet = false;
2929 : }
2930 : }
2931 5 : return bRet;
2932 : }
2933 :
2934 : /************************************************************************/
2935 : /* GetArrowSchema() */
2936 : /************************************************************************/
2937 :
2938 7 : int OGRGenSQLResultsLayer::GetArrowSchema(struct ArrowArrayStream *stream,
2939 : struct ArrowSchema *out_schema)
2940 : {
2941 7 : if (m_aosArrowArrayStreamOptions.FetchNameValue(
2942 7 : "OGR_GENSQL_STREAM_BASE_IMPL") ||
2943 0 : !TestCapability(OLCFastGetArrowStream))
2944 : {
2945 7 : return OGRLayer::GetArrowSchema(stream, out_schema);
2946 : }
2947 :
2948 0 : return GetArrowSchemaForwarded(stream, out_schema);
2949 : }
2950 :
2951 : /************************************************************************/
2952 : /* GetArrowSchemaForwarded() */
2953 : /************************************************************************/
2954 :
2955 5 : int OGRGenSQLResultsLayer::GetArrowSchemaForwarded(
2956 : struct ArrowArrayStream *stream, struct ArrowSchema *out_schema) const
2957 : {
2958 5 : const swq_select *psSelectInfo = m_pSelectInfo.get();
2959 5 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2960 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2961 : stream->private_data);
2962 10 : int ret = m_poSrcLayer->GetArrowSchema(psPrivateData->psSrcLayerStream,
2963 5 : out_schema);
2964 5 : if (ret == 0)
2965 : {
2966 : struct ArrowSchema newSchema;
2967 5 : ret = OGRCloneArrowSchema(out_schema, &newSchema) ? 0 : EIO;
2968 5 : if (out_schema->release)
2969 5 : out_schema->release(out_schema);
2970 5 : if (ret == 0)
2971 : {
2972 5 : std::map<std::string, std::string> oMapSrcNameToRenamed;
2973 18 : for (std::size_t iField = 0;
2974 18 : iField < psSelectInfo->column_defs.size(); iField++)
2975 : {
2976 : const swq_col_def *psColDef =
2977 13 : &psSelectInfo->column_defs[iField];
2978 13 : CPLAssert(!psColDef->bHidden);
2979 13 : CPLAssert(psColDef->table_index >= 0);
2980 13 : CPLAssert(psColDef->col_func == SWQCF_NONE);
2981 :
2982 : const auto poLayerDefn =
2983 13 : m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
2984 13 : CPLAssert(poLayerDefn);
2985 :
2986 26 : if (psColDef->field_index >= 0 &&
2987 13 : psColDef->field_index < poLayerDefn->GetFieldCount())
2988 : {
2989 : const auto poSrcFDefn =
2990 9 : poLayerDefn->GetFieldDefn(psColDef->field_index);
2991 9 : if (psColDef->field_alias)
2992 14 : oMapSrcNameToRenamed[poSrcFDefn->GetNameRef()] =
2993 14 : psColDef->field_alias;
2994 : }
2995 4 : else if (IS_GEOM_FIELD_INDEX(poLayerDefn,
2996 : psColDef->field_index))
2997 : {
2998 : const int iSrcGeomField =
2999 4 : ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
3000 : poLayerDefn, psColDef->field_index);
3001 : const auto poSrcGFDefn =
3002 4 : poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
3003 4 : if (psColDef->field_alias)
3004 4 : oMapSrcNameToRenamed[poSrcGFDefn->GetNameRef()] =
3005 4 : psColDef->field_alias;
3006 : }
3007 : }
3008 :
3009 23 : for (int i = 0; i < newSchema.n_children; ++i)
3010 : {
3011 : const auto oIter =
3012 18 : oMapSrcNameToRenamed.find(newSchema.children[i]->name);
3013 18 : if (oIter != oMapSrcNameToRenamed.end())
3014 : {
3015 7 : CPLFree(const_cast<char *>(newSchema.children[i]->name));
3016 14 : newSchema.children[i]->name =
3017 7 : CPLStrdup(oIter->second.c_str());
3018 : }
3019 : }
3020 :
3021 5 : memcpy(out_schema, &newSchema, sizeof(newSchema));
3022 : }
3023 : }
3024 5 : return ret;
3025 : }
3026 :
3027 : /************************************************************************/
3028 : /* GetNextArrowArray() */
3029 : /************************************************************************/
3030 :
3031 14 : int OGRGenSQLResultsLayer::GetNextArrowArray(struct ArrowArrayStream *stream,
3032 : struct ArrowArray *out_array)
3033 : {
3034 14 : if (m_aosArrowArrayStreamOptions.FetchNameValue(
3035 14 : "OGR_GENSQL_STREAM_BASE_IMPL") ||
3036 0 : !TestCapability(OLCFastGetArrowStream))
3037 : {
3038 14 : return OGRLayer::GetNextArrowArray(stream, out_array);
3039 : }
3040 :
3041 0 : return GetNextArrowArrayForwarded(stream, out_array);
3042 : }
3043 :
3044 : /************************************************************************/
3045 : /* GetNextArrowArrayForwarded() */
3046 : /************************************************************************/
3047 :
3048 8 : int OGRGenSQLResultsLayer::GetNextArrowArrayForwarded(
3049 : struct ArrowArrayStream *stream, struct ArrowArray *out_array)
3050 : {
3051 8 : const swq_select *psSelectInfo = m_pSelectInfo.get();
3052 8 : if (psSelectInfo->limit >= 0 && m_nIteratedFeatures >= psSelectInfo->limit)
3053 : {
3054 1 : memset(out_array, 0, sizeof(*out_array));
3055 1 : return 0;
3056 : }
3057 :
3058 7 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
3059 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
3060 : stream->private_data);
3061 14 : const int ret = m_poSrcLayer->GetNextArrowArray(
3062 7 : psPrivateData->psSrcLayerStream, out_array);
3063 7 : if (ret == 0 && psSelectInfo->limit >= 0)
3064 : {
3065 1 : if (m_nIteratedFeatures < 0)
3066 1 : m_nIteratedFeatures = 0;
3067 1 : m_nIteratedFeatures += out_array->length;
3068 1 : if (m_nIteratedFeatures > psSelectInfo->limit)
3069 : {
3070 0 : out_array->length -= m_nIteratedFeatures - psSelectInfo->limit;
3071 0 : for (int i = 0; i < out_array->n_children; ++i)
3072 : {
3073 0 : out_array->children[i]->length -=
3074 0 : m_nIteratedFeatures - psSelectInfo->limit;
3075 : }
3076 : }
3077 : }
3078 7 : return ret;
3079 : }
3080 :
3081 : //! @endcond
|