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 1501 : explicit OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn *poGeomFieldDefn)
35 1501 : : OGRGeomFieldDefn(poGeomFieldDefn->GetNameRef(),
36 : poGeomFieldDefn->GetType()),
37 1501 : bForceGeomType(FALSE)
38 : {
39 1501 : SetSpatialRef(poGeomFieldDefn->GetSpatialRef());
40 1501 : }
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 2147 : OGRGenSQLResultsLayer::OGRGenSQLResultsLayer(
78 : GDALDataset *poSrcDSIn, std::unique_ptr<swq_select> &&pSelectInfo,
79 : const OGRGeometry *poSpatFilter, const char *pszWHEREIn,
80 2147 : const char *pszDialect)
81 2147 : : m_poSrcDS(poSrcDSIn), m_pSelectInfo(std::move(pSelectInfo))
82 : {
83 2147 : swq_select *psSelectInfo = m_pSelectInfo.get();
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Identify all the layers involved in the SELECT. */
87 : /* -------------------------------------------------------------------- */
88 2147 : m_apoTableLayers.reserve(psSelectInfo->table_count);
89 :
90 4324 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
91 : {
92 2177 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
93 2177 : GDALDataset *poTableDS = m_poSrcDS;
94 :
95 2177 : 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 4354 : m_apoTableLayers.push_back(
115 2177 : poTableDS->GetLayerByName(psTableDef->table_name));
116 2177 : if (!m_apoTableLayers.back())
117 0 : return;
118 : }
119 :
120 2147 : m_poSrcLayer = m_apoTableLayers[0];
121 2147 : 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 2147 : m_bForwardWhereToSourceLayer = true;
129 2147 : 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 2147 : OGRFeatureDefn *poSrcDefn = m_poSrcLayer->GetLayerDefn();
147 :
148 2147 : m_poDefn = new OGRFeatureDefn(psSelectInfo->table_defs[0].table_alias);
149 2147 : SetDescription(m_poDefn->GetName());
150 2147 : m_poDefn->SetGeomType(wkbNone);
151 2147 : m_poDefn->Reference();
152 :
153 2147 : m_iFIDFieldIndex = poSrcDefn->GetFieldCount();
154 :
155 16953 : for (std::size_t iField = 0; iField < psSelectInfo->column_defs.size();
156 : iField++)
157 : {
158 14806 : swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
159 14806 : OGRFieldDefn oFDefn("", OFTInteger);
160 14806 : OGRGeomFieldDefn oGFDefn("", wkbUnknown);
161 14806 : OGRFieldDefn *poSrcFDefn = nullptr;
162 14806 : OGRGeomFieldDefn *poSrcGFDefn = nullptr;
163 14806 : int bIsGeometry = FALSE;
164 14806 : OGRFeatureDefn *poLayerDefn = nullptr;
165 14806 : int iSrcGeomField = -1;
166 :
167 14806 : if (psColDef->bHidden)
168 7 : continue;
169 :
170 14799 : if (psColDef->table_index != -1)
171 : poLayerDefn =
172 14515 : m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
173 :
174 29004 : if (psColDef->field_index > -1 && poLayerDefn != nullptr &&
175 14205 : psColDef->field_index < poLayerDefn->GetFieldCount())
176 : {
177 12983 : poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
178 : }
179 :
180 29314 : if (poLayerDefn != nullptr &&
181 14515 : IS_GEOM_FIELD_INDEX(poLayerDefn, psColDef->field_index))
182 : {
183 1205 : bIsGeometry = TRUE;
184 1205 : iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
185 : poLayerDefn, psColDef->field_index);
186 1205 : poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
187 : }
188 :
189 14799 : if (psColDef->target_type == SWQ_GEOMETRY)
190 12 : bIsGeometry = TRUE;
191 :
192 14799 : if (psColDef->col_func == SWQCF_COUNT)
193 327 : bIsGeometry = FALSE;
194 :
195 14799 : if (strlen(psColDef->field_name) == 0 && !bIsGeometry)
196 : {
197 270 : CPLFree(psColDef->field_name);
198 270 : psColDef->field_name = static_cast<char *>(CPLMalloc(40));
199 270 : snprintf(psColDef->field_name, 40, "FIELD_%d",
200 270 : m_poDefn->GetFieldCount() + 1);
201 : }
202 :
203 14799 : if (psColDef->field_alias != nullptr)
204 : {
205 12983 : if (bIsGeometry)
206 1199 : oGFDefn.SetName(psColDef->field_alias);
207 : else
208 11784 : oFDefn.SetName(psColDef->field_alias);
209 : }
210 1816 : 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 2874 : CPLString osName;
221 1437 : if (psColDef->table_name[0])
222 : {
223 60 : osName = psColDef->table_name;
224 60 : osName += ".";
225 : }
226 1437 : osName += psColDef->field_name;
227 :
228 1437 : if (bIsGeometry)
229 17 : oGFDefn.SetName(osName);
230 : else
231 1420 : oFDefn.SetName(osName);
232 : }
233 :
234 14799 : if (psColDef->col_func == SWQCF_COUNT)
235 327 : oFDefn.SetType(OFTInteger64);
236 14472 : else if (poSrcFDefn != nullptr)
237 : {
238 12968 : if (psColDef->col_func == SWQCF_STDDEV_POP ||
239 12965 : psColDef->col_func == SWQCF_STDDEV_SAMP)
240 : {
241 5 : oFDefn.SetType(OFTReal);
242 : }
243 12963 : 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 12958 : oFDefn.SetType(poSrcFDefn->GetType());
249 12958 : if (psColDef->col_func == SWQCF_NONE ||
250 42 : psColDef->col_func == SWQCF_MIN ||
251 24 : psColDef->col_func == SWQCF_MAX)
252 : {
253 12948 : oFDefn.SetSubType(poSrcFDefn->GetSubType());
254 : }
255 : }
256 : else
257 : {
258 5 : oFDefn.SetType(OFTReal);
259 : }
260 :
261 12968 : if (psColDef->col_func != SWQCF_AVG &&
262 12962 : psColDef->col_func != SWQCF_STDDEV_POP &&
263 12959 : psColDef->col_func != SWQCF_STDDEV_SAMP &&
264 12957 : psColDef->col_func != SWQCF_SUM)
265 : {
266 12948 : oFDefn.SetWidth(poSrcFDefn->GetWidth());
267 12948 : oFDefn.SetPrecision(poSrcFDefn->GetPrecision());
268 : }
269 :
270 12968 : if (psColDef->col_func == SWQCF_NONE)
271 12916 : oFDefn.SetDomainName(poSrcFDefn->GetDomainName());
272 : }
273 1504 : else if (poSrcGFDefn != nullptr)
274 : {
275 1204 : oGFDefn.SetType(poSrcGFDefn->GetType());
276 1204 : oGFDefn.SetSpatialRef(poSrcGFDefn->GetSpatialRef());
277 : }
278 300 : 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 284 : switch (psColDef->field_type)
305 : {
306 22 : case SWQ_INTEGER:
307 22 : oFDefn.SetType(OFTInteger);
308 22 : 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 14799 : switch (psColDef->target_type)
331 : {
332 14775 : case SWQ_OTHER:
333 14775 : 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 14799 : if (psColDef->target_subtype != OFSTNone)
368 1 : oFDefn.SetSubType(psColDef->target_subtype);
369 :
370 14799 : if (psColDef->field_length > 0)
371 : {
372 3 : oFDefn.SetWidth(psColDef->field_length);
373 : }
374 :
375 14799 : if (psColDef->field_precision >= 0)
376 : {
377 2 : oFDefn.SetPrecision(psColDef->field_precision);
378 : }
379 :
380 14799 : if (bIsGeometry)
381 : {
382 1216 : 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 2318 : if (iSrcGeomField == 0 && poSrcDefn->GetGeomFieldCount() == 1 &&
387 1102 : oGFDefn.GetSpatialRef() == nullptr)
388 : {
389 246 : oGFDefn.SetSpatialRef(m_poSrcLayer->GetSpatialRef());
390 : }
391 1216 : int bForceGeomType = FALSE;
392 1216 : if (psColDef->eGeomType != wkbUnknown)
393 : {
394 6 : oGFDefn.SetType(psColDef->eGeomType);
395 6 : bForceGeomType = TRUE;
396 : }
397 1216 : 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 1216 : std::make_unique<OGRGenSQLGeomFieldDefn>(&oGFDefn);
410 1216 : poMyGeomFieldDefn->bForceGeomType = bForceGeomType;
411 1216 : m_poDefn->AddGeomFieldDefn(std::move(poMyGeomFieldDefn));
412 : }
413 : else
414 13583 : m_poDefn->AddFieldDefn(&oFDefn);
415 : }
416 :
417 : /* -------------------------------------------------------------------- */
418 : /* Add implicit geometry field. */
419 : /* -------------------------------------------------------------------- */
420 6071 : if (psSelectInfo->query_mode == SWQM_RECORDSET &&
421 1777 : m_poDefn->GetGeomFieldCount() == 0 &&
422 3924 : poSrcDefn->GetGeomFieldCount() == 1 && !psSelectInfo->bExcludedGeometry)
423 : {
424 285 : psSelectInfo->column_defs.emplace_back();
425 :
426 285 : swq_col_def *col_def = &psSelectInfo->column_defs.back();
427 :
428 285 : memset(col_def, 0, sizeof(swq_col_def));
429 285 : const char *pszName = poSrcDefn->GetGeomFieldDefn(0)->GetNameRef();
430 285 : if (*pszName != '\0')
431 11 : col_def->field_name = CPLStrdup(pszName);
432 : else
433 274 : col_def->field_name =
434 274 : CPLStrdup(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
435 285 : col_def->field_alias = nullptr;
436 285 : col_def->table_index = 0;
437 285 : col_def->field_index =
438 285 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poSrcDefn, 0);
439 285 : col_def->field_type = SWQ_GEOMETRY;
440 285 : col_def->target_type = SWQ_GEOMETRY;
441 :
442 285 : m_anGeomFieldToSrcGeomField.push_back(0);
443 :
444 285 : m_poDefn->AddGeomFieldDefn(std::make_unique<OGRGenSQLGeomFieldDefn>(
445 285 : poSrcDefn->GetGeomFieldDefn(0)));
446 :
447 : /* Hack while drivers haven't been updated so that */
448 : /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() ==
449 : * m_poSrcLayer->GetSpatialRef() */
450 285 : 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 2147 : if (poSpatFilter)
462 301 : OGRGenSQLResultsLayer::SetSpatialFilter(
463 : 0, const_cast<OGRGeometry *>(poSpatFilter));
464 :
465 2147 : OGRGenSQLResultsLayer::ResetReading();
466 :
467 2147 : FindAndSetIgnoredFields();
468 :
469 2147 : if (!m_bForwardWhereToSourceLayer)
470 4 : OGRLayer::SetAttributeFilter(m_osInitialWHERE.c_str());
471 : }
472 :
473 : /************************************************************************/
474 : /* ~OGRGenSQLResultsLayer() */
475 : /************************************************************************/
476 :
477 4290 : OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
478 :
479 : {
480 2145 : if (m_nFeaturesRead > 0 && m_poDefn != nullptr)
481 : {
482 968 : CPLDebug("GenSQL", CPL_FRMT_GIB " features read on layer '%s'.",
483 968 : m_nFeaturesRead, m_poDefn->GetName());
484 : }
485 :
486 2145 : OGRGenSQLResultsLayer::ClearFilters();
487 :
488 2145 : if (m_poDefn != nullptr)
489 : {
490 2145 : m_poDefn->Release();
491 : }
492 4290 : }
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 2203 : void OGRGenSQLResultsLayer::ClearFilters()
503 :
504 : {
505 : /* -------------------------------------------------------------------- */
506 : /* Clear any filters installed on the target layer. */
507 : /* -------------------------------------------------------------------- */
508 2203 : if (m_poSrcLayer != nullptr)
509 : {
510 2203 : m_poSrcLayer->ResetReading();
511 2203 : m_poSrcLayer->SetAttributeFilter("");
512 2203 : m_poSrcLayer->SetSpatialFilter(nullptr);
513 : }
514 :
515 : /* -------------------------------------------------------------------- */
516 : /* Clear any attribute filter installed on the joined layers. */
517 : /* -------------------------------------------------------------------- */
518 2203 : swq_select *psSelectInfo = m_pSelectInfo.get();
519 :
520 2203 : if (psSelectInfo != nullptr)
521 : {
522 2233 : 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 2203 : if (psSelectInfo != nullptr)
536 : {
537 4436 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
538 : {
539 2233 : OGRLayer *poLayer = m_apoTableLayers[iTable];
540 2233 : poLayer->SetIgnoredFields(nullptr);
541 : }
542 : }
543 2203 : }
544 :
545 : /************************************************************************/
546 : /* MustEvaluateSpatialFilterOnGenSQL() */
547 : /************************************************************************/
548 :
549 3687 : int OGRGenSQLResultsLayer::MustEvaluateSpatialFilterOnGenSQL()
550 : {
551 3687 : int bEvaluateSpatialFilter = FALSE;
552 3981 : 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 3687 : return bEvaluateSpatialFilter;
560 : }
561 :
562 : /************************************************************************/
563 : /* ApplyFiltersToSource() */
564 : /************************************************************************/
565 :
566 3178 : void OGRGenSQLResultsLayer::ApplyFiltersToSource()
567 : {
568 3178 : if (m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty())
569 : {
570 1200 : m_poSrcLayer->SetAttributeFilter(m_osInitialWHERE.c_str());
571 : }
572 : else
573 : {
574 1978 : m_poSrcLayer->SetAttributeFilter(nullptr);
575 : }
576 6356 : if (m_iGeomFieldFilter >= 0 &&
577 3178 : m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
578 : {
579 2295 : int iSrcGeomField = m_anGeomFieldToSrcGeomField[m_iGeomFieldFilter];
580 2295 : if (iSrcGeomField >= 0)
581 2285 : m_poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
582 : }
583 :
584 3178 : m_poSrcLayer->ResetReading();
585 3178 : }
586 :
587 : /************************************************************************/
588 : /* ResetReading() */
589 : /************************************************************************/
590 :
591 3185 : void OGRGenSQLResultsLayer::ResetReading()
592 :
593 : {
594 3185 : swq_select *psSelectInfo = m_pSelectInfo.get();
595 :
596 3185 : if (psSelectInfo->query_mode == SWQM_RECORDSET)
597 : {
598 2814 : ApplyFiltersToSource();
599 : }
600 :
601 3185 : m_nNextIndexFID = psSelectInfo->offset;
602 3185 : m_nIteratedFeatures = -1;
603 3185 : m_bEOF = false;
604 3185 : }
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 11 : OGRErr OGRGenSQLResultsLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
658 : int bForce)
659 :
660 : {
661 11 : swq_select *psSelectInfo = m_pSelectInfo.get();
662 :
663 19 : if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
664 8 : 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 8 : if (psSelectInfo->query_mode == SWQM_RECORDSET)
675 : {
676 8 : int iSrcGeomField = m_anGeomFieldToSrcGeomField[iGeomField];
677 8 : if (iSrcGeomField >= 0)
678 8 : 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 87 : switch (ePrimaryFieldType)
1391 : {
1392 13 : case OFTInteger:
1393 26 : return CPLString().Printf("%d", psSrcField->Integer);
1394 : break;
1395 :
1396 55 : case OFTInteger64:
1397 110 : return CPLString().Printf(CPL_FRMT_GIB,
1398 55 : psSrcField->Integer64);
1399 : break;
1400 :
1401 0 : case OFTReal:
1402 0 : return CPLString().Printf("%.17g", psSrcField->Real);
1403 : 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 38 : CPLString osRes = "'";
1412 19 : osRes += pszEscaped;
1413 19 : osRes += "'";
1414 19 : CPLFree(pszEscaped);
1415 19 : return osRes;
1416 : }
1417 : break;
1418 :
1419 0 : default:
1420 0 : CPLAssert(false);
1421 : return "";
1422 : }
1423 : }
1424 : }
1425 :
1426 89 : if (poExpr->table_index == secondary_table)
1427 : {
1428 89 : const auto poJoinFDefn = poJoinLayer->GetLayerDefn();
1429 89 : if (poExpr->field_index >= poJoinFDefn->GetFieldCount())
1430 : {
1431 2 : CPLAssert(poExpr->field_index <
1432 : poJoinFDefn->GetFieldCount() + SPECIAL_FIELD_COUNT);
1433 4 : return SpecialFieldNames[poExpr->field_index -
1434 2 : poJoinFDefn->GetFieldCount()];
1435 : }
1436 : else
1437 : {
1438 : const OGRFieldDefn *poSecondaryFieldDefn =
1439 87 : poJoinFDefn->GetFieldDefn(poExpr->field_index);
1440 87 : return CPLSPrintf("\"%s\"", poSecondaryFieldDefn->GetNameRef());
1441 : }
1442 : }
1443 :
1444 0 : CPLAssert(false);
1445 : return "";
1446 : }
1447 :
1448 122 : if (poExpr->eNodeType == SNT_OPERATION)
1449 : {
1450 : /* ----------------------------------------------------------------- */
1451 : /* Operation - start by unparsing all the subexpressions. */
1452 : /* ----------------------------------------------------------------- */
1453 244 : std::vector<char *> apszSubExpr;
1454 360 : for (int i = 0; i < poExpr->nSubExprCount; i++)
1455 : {
1456 : CPLString osSubExpr =
1457 241 : GetFilterForJoin(poExpr->papoSubExpr[i], poSrcFeat, poJoinLayer,
1458 241 : secondary_table);
1459 241 : if (osSubExpr.empty())
1460 : {
1461 3 : for (--i; i >= 0; i--)
1462 0 : CPLFree(apszSubExpr[i]);
1463 3 : return "";
1464 : }
1465 238 : apszSubExpr.push_back(CPLStrdup(osSubExpr));
1466 : }
1467 :
1468 : CPLString osExpr =
1469 238 : poExpr->UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
1470 :
1471 : /* ----------------------------------------------------------------- */
1472 : /* cleanup subexpressions. */
1473 : /* ----------------------------------------------------------------- */
1474 357 : for (int i = 0; i < poExpr->nSubExprCount; i++)
1475 238 : CPLFree(apszSubExpr[i]);
1476 :
1477 119 : return osExpr;
1478 : }
1479 :
1480 0 : return "";
1481 : }
1482 :
1483 : /************************************************************************/
1484 : /* TranslateFeature() */
1485 : /************************************************************************/
1486 :
1487 3858 : std::unique_ptr<OGRFeature> OGRGenSQLResultsLayer::TranslateFeature(
1488 : std::unique_ptr<OGRFeature> poSrcFeatUniquePtr)
1489 :
1490 : {
1491 3858 : swq_select *psSelectInfo = m_pSelectInfo.get();
1492 7716 : VectorOfUniquePtrFeature apoFeatures;
1493 :
1494 3858 : if (poSrcFeatUniquePtr == nullptr)
1495 0 : return nullptr;
1496 :
1497 3858 : m_nFeaturesRead++;
1498 :
1499 3858 : apoFeatures.push_back(std::move(poSrcFeatUniquePtr));
1500 3858 : auto poSrcFeat = apoFeatures.front().get();
1501 :
1502 : /* -------------------------------------------------------------------- */
1503 : /* Fetch the corresponding features from any jointed tables. */
1504 : /* -------------------------------------------------------------------- */
1505 3951 : for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
1506 : {
1507 93 : const swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1508 :
1509 : /* OGRMultiFeatureFetcher assumes that the features are pushed in */
1510 : /* apoFeatures with increasing secondary_table, so make sure */
1511 : /* we have taken care of this */
1512 93 : CPLAssert(psJoinInfo->secondary_table == iJoin + 1);
1513 :
1514 93 : OGRLayer *poJoinLayer = m_apoTableLayers[psJoinInfo->secondary_table];
1515 :
1516 : const std::string osFilter =
1517 186 : GetFilterForJoin(psJoinInfo->poExpr, poSrcFeat, poJoinLayer,
1518 93 : psJoinInfo->secondary_table);
1519 : // CPLDebug("OGR", "Filter = %s\n", osFilter.c_str());
1520 :
1521 : // if source key is null, we can't do join.
1522 93 : if (osFilter.empty())
1523 : {
1524 3 : apoFeatures.push_back(nullptr);
1525 3 : continue;
1526 : }
1527 :
1528 90 : std::unique_ptr<OGRFeature> poJoinFeature;
1529 :
1530 90 : poJoinLayer->ResetReading();
1531 90 : if (poJoinLayer->SetAttributeFilter(osFilter.c_str()) == OGRERR_NONE)
1532 90 : poJoinFeature.reset(poJoinLayer->GetNextFeature());
1533 :
1534 90 : apoFeatures.push_back(std::move(poJoinFeature));
1535 : }
1536 :
1537 : /* -------------------------------------------------------------------- */
1538 : /* Create destination feature. */
1539 : /* -------------------------------------------------------------------- */
1540 7716 : auto poDstFeat = std::make_unique<OGRFeature>(m_poDefn);
1541 :
1542 3858 : poDstFeat->SetFID(poSrcFeat->GetFID());
1543 :
1544 3858 : poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
1545 3858 : poDstFeat->SetNativeData(poSrcFeat->GetNativeData());
1546 3858 : poDstFeat->SetNativeMediaType(poSrcFeat->GetNativeMediaType());
1547 :
1548 : /* -------------------------------------------------------------------- */
1549 : /* Evaluate fields that are complex expressions. */
1550 : /* -------------------------------------------------------------------- */
1551 3858 : int iRegularField = 0;
1552 3858 : int iGeomField = 0;
1553 3858 : swq_evaluation_context sContext;
1554 18081 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1555 : {
1556 14223 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1557 :
1558 14223 : if (psColDef->bHidden)
1559 : {
1560 10 : const char *pszDstFieldName = psColDef->field_alias
1561 : ? psColDef->field_alias
1562 : : psColDef->field_name;
1563 10 : if (EQUAL(pszDstFieldName, "OGR_STYLE"))
1564 : {
1565 10 : if (psColDef->field_type == SWQ_STRING)
1566 : {
1567 : // Does this column definition directly references a
1568 : // source field ?
1569 7 : if (psColDef->field_index >= 0)
1570 : {
1571 4 : if (!IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(),
1572 : psColDef->field_index))
1573 : {
1574 4 : if (poSrcFeat->IsFieldSetAndNotNull(
1575 4 : psColDef->field_index))
1576 : {
1577 : const char *pszVal =
1578 4 : poSrcFeat->GetFieldAsString(
1579 2 : psColDef->field_index);
1580 2 : poDstFeat->SetStyleString(pszVal);
1581 : }
1582 : else
1583 : {
1584 2 : poDstFeat->SetStyleString(nullptr);
1585 : }
1586 : }
1587 : else
1588 : {
1589 0 : CPLError(CE_Warning, CPLE_AppDefined,
1590 : "OGR_STYLE HIDDEN field should reference "
1591 : "a column of type String");
1592 : }
1593 : }
1594 : else
1595 : {
1596 : auto poResult = std::unique_ptr<swq_expr_node>(
1597 3 : psColDef->expr->Evaluate(OGRMultiFeatureFetcher,
1598 3 : &apoFeatures, sContext));
1599 :
1600 3 : if (!poResult)
1601 : {
1602 0 : return nullptr;
1603 : }
1604 :
1605 8 : poDstFeat->SetStyleString(poResult->is_null
1606 : ? nullptr
1607 5 : : poResult->string_value);
1608 : }
1609 : }
1610 : else
1611 : {
1612 3 : CPLError(CE_Warning, CPLE_AppDefined,
1613 : "OGR_STYLE HIDDEN field should be of type String");
1614 : }
1615 : }
1616 13912 : continue;
1617 : }
1618 :
1619 : // Does this column definition directly references a
1620 : // source field ?
1621 : // If so, skip it for now, as it will be taken into account in the
1622 : // next loop.
1623 14213 : if (psColDef->field_index >= 0)
1624 : {
1625 13869 : if (psColDef->field_type == SWQ_GEOMETRY ||
1626 12253 : psColDef->target_type == SWQ_GEOMETRY)
1627 1616 : iGeomField++;
1628 : else
1629 12253 : iRegularField++;
1630 13869 : continue;
1631 : }
1632 :
1633 344 : auto poResult = std::unique_ptr<swq_expr_node>(psColDef->expr->Evaluate(
1634 344 : OGRMultiFeatureFetcher, &apoFeatures, sContext));
1635 :
1636 344 : if (!poResult)
1637 : {
1638 0 : return nullptr;
1639 : }
1640 :
1641 344 : if (poResult->is_null)
1642 : {
1643 33 : if (poResult->field_type == SWQ_GEOMETRY)
1644 2 : iGeomField++;
1645 : else
1646 31 : iRegularField++;
1647 33 : continue;
1648 : }
1649 :
1650 311 : switch (poResult->field_type)
1651 : {
1652 193 : case SWQ_BOOLEAN:
1653 : case SWQ_INTEGER:
1654 : case SWQ_INTEGER64:
1655 193 : poDstFeat->SetField(iRegularField++, poResult->int_value);
1656 193 : break;
1657 :
1658 51 : case SWQ_FLOAT:
1659 51 : poDstFeat->SetField(iRegularField++, poResult->float_value);
1660 51 : break;
1661 :
1662 10 : case SWQ_GEOMETRY:
1663 : {
1664 : OGRGenSQLGeomFieldDefn *poGeomFieldDefn =
1665 10 : cpl::down_cast<OGRGenSQLGeomFieldDefn *>(
1666 : poDstFeat->GetGeomFieldDefnRef(iGeomField));
1667 16 : if (poGeomFieldDefn->bForceGeomType &&
1668 6 : poResult->geometry_value != nullptr)
1669 : {
1670 : OGRwkbGeometryType eCurType =
1671 6 : wkbFlatten(poResult->geometry_value->getGeometryType());
1672 : OGRwkbGeometryType eReqType =
1673 6 : wkbFlatten(poGeomFieldDefn->GetType());
1674 6 : if (eCurType == wkbPolygon && eReqType == wkbMultiPolygon)
1675 : {
1676 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1677 : OGR_G_ForceToMultiPolygon(OGRGeometry::ToHandle(
1678 1 : poResult->geometry_value)));
1679 : }
1680 5 : else if ((eCurType == wkbMultiPolygon ||
1681 1 : eCurType == wkbGeometryCollection) &&
1682 : eReqType == wkbPolygon)
1683 : {
1684 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1685 : OGR_G_ForceToPolygon(OGRGeometry::ToHandle(
1686 1 : poResult->geometry_value)));
1687 : }
1688 4 : else if (eCurType == wkbLineString &&
1689 : eReqType == wkbMultiLineString)
1690 : {
1691 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1692 : OGR_G_ForceToMultiLineString(OGRGeometry::ToHandle(
1693 1 : poResult->geometry_value)));
1694 : }
1695 3 : else if ((eCurType == wkbMultiLineString ||
1696 1 : eCurType == wkbGeometryCollection) &&
1697 : eReqType == wkbLineString)
1698 : {
1699 1 : poResult->geometry_value = OGRGeometry::FromHandle(
1700 : OGR_G_ForceToLineString(OGRGeometry::ToHandle(
1701 1 : poResult->geometry_value)));
1702 : }
1703 : }
1704 10 : poDstFeat->SetGeomField(iGeomField++, poResult->geometry_value);
1705 10 : break;
1706 : }
1707 :
1708 57 : default:
1709 57 : poDstFeat->SetField(iRegularField++, poResult->string_value);
1710 57 : break;
1711 : }
1712 : }
1713 :
1714 : /* -------------------------------------------------------------------- */
1715 : /* Copy fields from primary record to the destination feature. */
1716 : /* -------------------------------------------------------------------- */
1717 3858 : iRegularField = 0;
1718 3858 : iGeomField = 0;
1719 18081 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1720 : {
1721 14223 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1722 :
1723 14223 : if (psColDef->bHidden)
1724 : {
1725 10 : continue;
1726 : }
1727 :
1728 : // Skip this column definition if it doesn't reference a field from
1729 : // the main feature
1730 14213 : if (psColDef->table_index != 0)
1731 : {
1732 626 : if (psColDef->field_type == SWQ_GEOMETRY ||
1733 614 : psColDef->target_type == SWQ_GEOMETRY)
1734 12 : iGeomField++;
1735 : else
1736 614 : iRegularField++;
1737 626 : continue;
1738 : }
1739 :
1740 13587 : if (IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(), psColDef->field_index))
1741 : {
1742 1616 : int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
1743 : poSrcFeat->GetDefnRef(), psColDef->field_index);
1744 1616 : poDstFeat->SetGeomField(iGeomField++,
1745 1616 : poSrcFeat->GetGeomFieldRef(iSrcGeomField));
1746 : }
1747 11971 : else if (psColDef->field_index >= m_iFIDFieldIndex)
1748 : {
1749 26 : CPLAssert(psColDef->field_index <
1750 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
1751 26 : switch (SpecialFieldTypes[psColDef->field_index - m_iFIDFieldIndex])
1752 : {
1753 7 : case SWQ_INTEGER:
1754 : case SWQ_INTEGER64:
1755 14 : poDstFeat->SetField(
1756 : iRegularField,
1757 7 : poSrcFeat->GetFieldAsInteger64(psColDef->field_index));
1758 7 : break;
1759 1 : case SWQ_FLOAT:
1760 2 : poDstFeat->SetField(
1761 : iRegularField,
1762 1 : poSrcFeat->GetFieldAsDouble(psColDef->field_index));
1763 1 : break;
1764 18 : default:
1765 36 : poDstFeat->SetField(
1766 : iRegularField,
1767 18 : poSrcFeat->GetFieldAsString(psColDef->field_index));
1768 : }
1769 26 : iRegularField++;
1770 : }
1771 : else
1772 : {
1773 11945 : switch (psColDef->target_type)
1774 : {
1775 0 : case SWQ_INTEGER:
1776 0 : poDstFeat->SetField(
1777 : iRegularField,
1778 0 : poSrcFeat->GetFieldAsInteger(psColDef->field_index));
1779 0 : break;
1780 :
1781 0 : case SWQ_INTEGER64:
1782 0 : poDstFeat->SetField(
1783 : iRegularField,
1784 0 : poSrcFeat->GetFieldAsInteger64(psColDef->field_index));
1785 0 : break;
1786 :
1787 0 : case SWQ_FLOAT:
1788 0 : poDstFeat->SetField(
1789 : iRegularField,
1790 0 : poSrcFeat->GetFieldAsDouble(psColDef->field_index));
1791 0 : break;
1792 :
1793 0 : case SWQ_STRING:
1794 : case SWQ_TIMESTAMP:
1795 : case SWQ_DATE:
1796 : case SWQ_TIME:
1797 0 : poDstFeat->SetField(
1798 : iRegularField,
1799 0 : poSrcFeat->GetFieldAsString(psColDef->field_index));
1800 0 : break;
1801 :
1802 0 : case SWQ_GEOMETRY:
1803 0 : CPLAssert(false);
1804 : break;
1805 :
1806 11945 : default:
1807 23890 : poDstFeat->SetField(
1808 : iRegularField,
1809 11945 : poSrcFeat->GetRawFieldRef(psColDef->field_index));
1810 : }
1811 11945 : iRegularField++;
1812 : }
1813 : }
1814 :
1815 : /* -------------------------------------------------------------------- */
1816 : /* Copy values from any joined tables. */
1817 : /* -------------------------------------------------------------------- */
1818 3951 : for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
1819 : {
1820 93 : const swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1821 93 : const OGRFeature *poJoinFeature = apoFeatures[iJoin + 1].get();
1822 :
1823 93 : if (poJoinFeature == nullptr)
1824 30 : continue;
1825 :
1826 : // Copy over selected field values.
1827 63 : iRegularField = 0;
1828 460 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1829 : {
1830 397 : const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1831 :
1832 397 : if (psColDef->field_type == SWQ_GEOMETRY ||
1833 346 : psColDef->target_type == SWQ_GEOMETRY)
1834 51 : continue;
1835 :
1836 346 : if (psColDef->bHidden)
1837 : {
1838 0 : continue;
1839 : }
1840 :
1841 346 : if (psColDef->table_index == psJoinInfo->secondary_table)
1842 352 : poDstFeat->SetField(
1843 : iRegularField,
1844 176 : poJoinFeature->GetRawFieldRef(psColDef->field_index));
1845 :
1846 346 : iRegularField++;
1847 : }
1848 : }
1849 :
1850 3858 : return poDstFeat;
1851 : }
1852 :
1853 : /************************************************************************/
1854 : /* GetNextFeature() */
1855 : /************************************************************************/
1856 :
1857 3990 : OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
1858 :
1859 : {
1860 3990 : swq_select *psSelectInfo = m_pSelectInfo.get();
1861 :
1862 3990 : if (m_bEOF)
1863 2 : return nullptr;
1864 3988 : if (psSelectInfo->limit >= 0 &&
1865 48 : (m_nIteratedFeatures < 0 ? 0 : m_nIteratedFeatures) >=
1866 48 : psSelectInfo->limit)
1867 23 : return nullptr;
1868 :
1869 3965 : CreateOrderByIndex();
1870 6728 : if (m_anFIDIndex.empty() && m_nIteratedFeatures < 0 &&
1871 6728 : psSelectInfo->offset > 0 && psSelectInfo->query_mode == SWQM_RECORDSET)
1872 : {
1873 4 : m_poSrcLayer->SetNextByIndex(psSelectInfo->offset);
1874 : }
1875 3965 : if (m_nIteratedFeatures < 0)
1876 2236 : m_nIteratedFeatures = 0;
1877 :
1878 : /* -------------------------------------------------------------------- */
1879 : /* Handle summary sets. */
1880 : /* -------------------------------------------------------------------- */
1881 3965 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD ||
1882 3621 : psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
1883 : {
1884 446 : m_nIteratedFeatures++;
1885 446 : return GetFeature(m_nNextIndexFID++);
1886 : }
1887 :
1888 3519 : int bEvaluateSpatialFilter = MustEvaluateSpatialFilterOnGenSQL();
1889 :
1890 : /* -------------------------------------------------------------------- */
1891 : /* Handle ordered sets. */
1892 : /* -------------------------------------------------------------------- */
1893 : while (true)
1894 : {
1895 0 : std::unique_ptr<OGRFeature> poSrcFeat;
1896 3570 : if (!m_anFIDIndex.empty())
1897 : {
1898 : /* --------------------------------------------------------------------
1899 : */
1900 : /* Are we running in sorted mode? If so, run the fid through
1901 : */
1902 : /* the index. */
1903 : /* --------------------------------------------------------------------
1904 : */
1905 :
1906 1202 : if (m_nNextIndexFID >= static_cast<GIntBig>(m_anFIDIndex.size()))
1907 13 : return nullptr;
1908 :
1909 1189 : poSrcFeat.reset(m_poSrcLayer->GetFeature(
1910 1189 : m_anFIDIndex[static_cast<size_t>(m_nNextIndexFID)]));
1911 1189 : m_nNextIndexFID++;
1912 : }
1913 : else
1914 : {
1915 2368 : poSrcFeat.reset(m_poSrcLayer->GetNextFeature());
1916 : }
1917 :
1918 3557 : if (poSrcFeat == nullptr)
1919 704 : return nullptr;
1920 :
1921 2853 : auto poFeature = TranslateFeature(std::move(poSrcFeat));
1922 2853 : if (poFeature == nullptr)
1923 0 : return nullptr;
1924 :
1925 5822 : if ((m_poAttrQuery == nullptr ||
1926 2853 : m_poAttrQuery->Evaluate(poFeature.get())) &&
1927 0 : (!bEvaluateSpatialFilter ||
1928 0 : FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))))
1929 : {
1930 2802 : m_nIteratedFeatures++;
1931 2802 : return poFeature.release();
1932 : }
1933 51 : }
1934 :
1935 : return nullptr;
1936 : }
1937 :
1938 : /************************************************************************/
1939 : /* GetFeature() */
1940 : /************************************************************************/
1941 :
1942 1454 : OGRFeature *OGRGenSQLResultsLayer::GetFeature(GIntBig nFID)
1943 :
1944 : {
1945 1454 : swq_select *psSelectInfo = m_pSelectInfo.get();
1946 :
1947 1454 : CreateOrderByIndex();
1948 :
1949 : /* -------------------------------------------------------------------- */
1950 : /* Handle request for summary record. */
1951 : /* -------------------------------------------------------------------- */
1952 1454 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD)
1953 : {
1954 344 : if (!PrepareSummary() || nFID != 0 || !m_poSummaryFeature)
1955 5 : return nullptr;
1956 : else
1957 339 : return m_poSummaryFeature->Clone();
1958 : }
1959 :
1960 : /* -------------------------------------------------------------------- */
1961 : /* Handle request for distinct list record. */
1962 : /* -------------------------------------------------------------------- */
1963 1110 : if (psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
1964 : {
1965 102 : if (!PrepareSummary())
1966 2 : return nullptr;
1967 :
1968 100 : if (psSelectInfo->column_summary.empty())
1969 1 : return nullptr;
1970 :
1971 99 : swq_summary &oSummary = psSelectInfo->column_summary[0];
1972 99 : if (psSelectInfo->order_specs == 0)
1973 : {
1974 18 : if (nFID < 0 || nFID >= static_cast<GIntBig>(
1975 9 : oSummary.oVectorDistinctValues.size()))
1976 : {
1977 1 : return nullptr;
1978 : }
1979 8 : const size_t nIdx = static_cast<size_t>(nFID);
1980 8 : if (oSummary.oVectorDistinctValues[nIdx] != SZ_OGR_NULL)
1981 : {
1982 12 : m_poSummaryFeature->SetField(
1983 6 : 0, oSummary.oVectorDistinctValues[nIdx].c_str());
1984 : }
1985 : else
1986 2 : m_poSummaryFeature->SetFieldNull(0);
1987 : }
1988 : else
1989 : {
1990 90 : if (m_aosDistinctList.empty())
1991 : {
1992 : std::set<CPLString, swq_summary::Comparator>::const_iterator
1993 18 : oIter = oSummary.oSetDistinctValues.begin();
1994 : std::set<CPLString, swq_summary::Comparator>::const_iterator
1995 18 : oEnd = oSummary.oSetDistinctValues.end();
1996 : try
1997 : {
1998 18 : m_aosDistinctList.reserve(
1999 : oSummary.oSetDistinctValues.size());
2000 108 : for (; oIter != oEnd; ++oIter)
2001 : {
2002 90 : m_aosDistinctList.push_back(*oIter);
2003 : }
2004 : }
2005 0 : catch (std::bad_alloc &)
2006 : {
2007 0 : return nullptr;
2008 : }
2009 18 : oSummary.oSetDistinctValues.clear();
2010 : }
2011 :
2012 180 : if (nFID < 0 ||
2013 90 : nFID >= static_cast<GIntBig>(m_aosDistinctList.size()))
2014 8 : return nullptr;
2015 :
2016 82 : const size_t nIdx = static_cast<size_t>(nFID);
2017 82 : if (m_aosDistinctList[nIdx] != SZ_OGR_NULL)
2018 144 : m_poSummaryFeature->SetField(0,
2019 72 : m_aosDistinctList[nIdx].c_str());
2020 : else
2021 10 : m_poSummaryFeature->SetFieldNull(0);
2022 : }
2023 :
2024 90 : m_poSummaryFeature->SetFID(nFID);
2025 :
2026 90 : return m_poSummaryFeature->Clone();
2027 : }
2028 :
2029 : /* -------------------------------------------------------------------- */
2030 : /* Handle request for random record. */
2031 : /* -------------------------------------------------------------------- */
2032 : auto poSrcFeature =
2033 2016 : std::unique_ptr<OGRFeature>(m_poSrcLayer->GetFeature(nFID));
2034 1008 : if (poSrcFeature == nullptr)
2035 3 : return nullptr;
2036 :
2037 1005 : return TranslateFeature(std::move(poSrcFeature)).release();
2038 : }
2039 :
2040 : /************************************************************************/
2041 : /* GetSpatialFilter() */
2042 : /************************************************************************/
2043 :
2044 1 : OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
2045 :
2046 : {
2047 1 : return nullptr;
2048 : }
2049 :
2050 : /************************************************************************/
2051 : /* GetLayerDefn() */
2052 : /************************************************************************/
2053 :
2054 4563 : OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
2055 :
2056 : {
2057 4563 : swq_select *psSelectInfo = m_pSelectInfo.get();
2058 4563 : if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD && !m_poSummaryFeature)
2059 : {
2060 : // Run PrepareSummary() is we have a COUNT column so as to be
2061 : // able to downcast it from OFTInteger64 to OFTInteger
2062 19 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
2063 : {
2064 15 : swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
2065 15 : if (psColDef->col_func == SWQCF_COUNT)
2066 : {
2067 5 : PrepareSummary();
2068 5 : break;
2069 : }
2070 : }
2071 : }
2072 :
2073 4563 : return m_poDefn;
2074 : }
2075 :
2076 : /************************************************************************/
2077 : /* FreeIndexFields() */
2078 : /************************************************************************/
2079 :
2080 160 : void OGRGenSQLResultsLayer::FreeIndexFields(OGRField *pasIndexFields,
2081 : size_t l_nIndexSize)
2082 : {
2083 160 : swq_select *psSelectInfo = m_pSelectInfo.get();
2084 160 : const int nOrderItems = psSelectInfo->order_specs;
2085 :
2086 : /* -------------------------------------------------------------------- */
2087 : /* Free the key field values. */
2088 : /* -------------------------------------------------------------------- */
2089 423 : for (int iKey = 0; iKey < nOrderItems; iKey++)
2090 : {
2091 263 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2092 :
2093 263 : if (psKeyDef->field_index >= m_iFIDFieldIndex)
2094 : {
2095 5 : CPLAssert(psKeyDef->field_index <
2096 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2097 : /* warning: only special fields of type string should be deallocated
2098 : */
2099 5 : if (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex] ==
2100 : SWQ_STRING)
2101 : {
2102 11 : for (size_t i = 0; i < l_nIndexSize; i++)
2103 : {
2104 10 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
2105 10 : CPLFree(psField->String);
2106 : }
2107 : }
2108 5 : continue;
2109 : }
2110 :
2111 : OGRFieldDefn *poFDefn =
2112 258 : m_poSrcLayer->GetLayerDefn()->GetFieldDefn(psKeyDef->field_index);
2113 :
2114 258 : if (poFDefn->GetType() == OFTString)
2115 : {
2116 377 : for (size_t i = 0; i < l_nIndexSize; i++)
2117 : {
2118 261 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
2119 :
2120 522 : if (!OGR_RawField_IsUnset(psField) &&
2121 261 : !OGR_RawField_IsNull(psField))
2122 250 : CPLFree(psField->String);
2123 : }
2124 : }
2125 : }
2126 160 : }
2127 :
2128 : /************************************************************************/
2129 : /* ReadIndexFields() */
2130 : /************************************************************************/
2131 :
2132 1415 : void OGRGenSQLResultsLayer::ReadIndexFields(OGRFeature *poSrcFeat,
2133 : int nOrderItems,
2134 : OGRField *pasIndexFields)
2135 : {
2136 1415 : swq_select *psSelectInfo = m_pSelectInfo.get();
2137 3032 : for (int iKey = 0; iKey < nOrderItems; iKey++)
2138 : {
2139 1617 : const swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2140 1617 : OGRField *psDstField = pasIndexFields + iKey;
2141 :
2142 1617 : if (psKeyDef->field_index >= m_iFIDFieldIndex)
2143 : {
2144 34 : CPLAssert(psKeyDef->field_index <
2145 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2146 :
2147 34 : switch (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex])
2148 : {
2149 14 : case SWQ_INTEGER:
2150 : case SWQ_INTEGER64:
2151 : // Yes, store Integer as Integer64.
2152 : // This is consistent with the test in Compare()
2153 14 : psDstField->Integer64 =
2154 14 : poSrcFeat->GetFieldAsInteger64(psKeyDef->field_index);
2155 14 : break;
2156 :
2157 10 : case SWQ_FLOAT:
2158 10 : psDstField->Real =
2159 10 : poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
2160 10 : break;
2161 :
2162 10 : default:
2163 10 : psDstField->String = CPLStrdup(
2164 10 : poSrcFeat->GetFieldAsString(psKeyDef->field_index));
2165 10 : break;
2166 : }
2167 :
2168 34 : continue;
2169 : }
2170 :
2171 : OGRFieldDefn *poFDefn =
2172 1583 : m_poSrcLayer->GetLayerDefn()->GetFieldDefn(psKeyDef->field_index);
2173 :
2174 1583 : OGRField *psSrcField = poSrcFeat->GetRawFieldRef(psKeyDef->field_index);
2175 :
2176 1964 : if (poFDefn->GetType() == OFTInteger ||
2177 720 : poFDefn->GetType() == OFTInteger64 ||
2178 861 : poFDefn->GetType() == OFTReal || poFDefn->GetType() == OFTDate ||
2179 2225 : poFDefn->GetType() == OFTTime || poFDefn->GetType() == OFTDateTime)
2180 1324 : memcpy(psDstField, psSrcField, sizeof(OGRField));
2181 259 : else if (poFDefn->GetType() == OFTString)
2182 : {
2183 259 : if (poSrcFeat->IsFieldSetAndNotNull(psKeyDef->field_index))
2184 248 : psDstField->String = CPLStrdup(psSrcField->String);
2185 : else
2186 11 : memcpy(psDstField, psSrcField, sizeof(OGRField));
2187 : }
2188 : }
2189 1415 : }
2190 :
2191 : /************************************************************************/
2192 : /* CreateOrderByIndex() */
2193 : /* */
2194 : /* This method is responsible for creating an index providing */
2195 : /* ordered access to the features according to the supplied */
2196 : /* ORDER BY clauses. */
2197 : /* */
2198 : /* This is accomplished by making one pass through all the */
2199 : /* eligible source features, and capturing the order by fields */
2200 : /* of all records in memory. A quick sort is then applied to */
2201 : /* this in memory copy of the order-by fields to create the */
2202 : /* required index. */
2203 : /* */
2204 : /* Keeping all the key values in memory will *not* scale up to */
2205 : /* very large input datasets. */
2206 : /************************************************************************/
2207 :
2208 5608 : void OGRGenSQLResultsLayer::CreateOrderByIndex()
2209 :
2210 : {
2211 5608 : swq_select *psSelectInfo = m_pSelectInfo.get();
2212 5608 : const int nOrderItems = psSelectInfo->order_specs;
2213 :
2214 5608 : if (!(nOrderItems > 0 && psSelectInfo->query_mode == SWQM_RECORDSET))
2215 5573 : return;
2216 :
2217 2296 : if (m_bOrderByValid)
2218 2257 : return;
2219 :
2220 39 : m_bOrderByValid = true;
2221 39 : m_anFIDIndex.clear();
2222 :
2223 39 : ResetReading();
2224 :
2225 : /* -------------------------------------------------------------------- */
2226 : /* Optimize (memory-wise) ORDER BY ... LIMIT 1 [OFFSET 0] case. */
2227 : /* -------------------------------------------------------------------- */
2228 39 : if (psSelectInfo->offset == 0 && psSelectInfo->limit == 1)
2229 : {
2230 8 : std::vector<OGRField> asCurrentFields(nOrderItems);
2231 4 : std::vector<OGRField> asBestFields(nOrderItems);
2232 4 : memset(asCurrentFields.data(), 0, sizeof(OGRField) * nOrderItems);
2233 4 : memset(asBestFields.data(), 0, sizeof(OGRField) * nOrderItems);
2234 4 : bool bFoundSrcFeature = false;
2235 4 : GIntBig nBestFID = 0;
2236 125 : for (auto &&poSrcFeat : *m_poSrcLayer)
2237 : {
2238 121 : ReadIndexFields(poSrcFeat.get(), nOrderItems,
2239 : asCurrentFields.data());
2240 239 : if (!bFoundSrcFeature ||
2241 118 : Compare(asCurrentFields.data(), asBestFields.data()) < 0)
2242 : {
2243 107 : bFoundSrcFeature = true;
2244 107 : nBestFID = poSrcFeat->GetFID();
2245 107 : FreeIndexFields(asBestFields.data(), 1);
2246 107 : memcpy(asBestFields.data(), asCurrentFields.data(),
2247 107 : sizeof(OGRField) * nOrderItems);
2248 : }
2249 : else
2250 : {
2251 14 : FreeIndexFields(asCurrentFields.data(), 1);
2252 : }
2253 121 : memset(asCurrentFields.data(), 0, sizeof(OGRField) * nOrderItems);
2254 : }
2255 4 : FreeIndexFields(asBestFields.data(), 1);
2256 :
2257 4 : if (bFoundSrcFeature)
2258 : {
2259 3 : m_anFIDIndex.resize(1);
2260 3 : m_anFIDIndex[0] = nBestFID;
2261 : }
2262 4 : return;
2263 : }
2264 :
2265 : /* -------------------------------------------------------------------- */
2266 : /* Allocate set of key values, and the output index. */
2267 : /* -------------------------------------------------------------------- */
2268 35 : size_t nFeaturesAlloc = 100;
2269 35 : size_t nIndexSize = 0;
2270 35 : std::vector<OGRField> asIndexFields(nOrderItems * nFeaturesAlloc);
2271 70 : memset(asIndexFields.data(), 0,
2272 35 : sizeof(OGRField) * nOrderItems * nFeaturesAlloc);
2273 35 : std::vector<GIntBig> anFIDList;
2274 :
2275 : // Frees nIndexSize rows of asIndexFields
2276 : struct IndexFieldsFreer
2277 : {
2278 : OGRGenSQLResultsLayer &m_oLayer;
2279 : std::vector<OGRField> &m_asIndexFields;
2280 : size_t &m_nIndexSize;
2281 :
2282 35 : IndexFieldsFreer(OGRGenSQLResultsLayer &poLayerIn,
2283 : std::vector<OGRField> &asIndexFieldsIn,
2284 : size_t &nIndexSizeIn)
2285 35 : : m_oLayer(poLayerIn), m_asIndexFields(asIndexFieldsIn),
2286 35 : m_nIndexSize(nIndexSizeIn)
2287 : {
2288 35 : }
2289 :
2290 35 : ~IndexFieldsFreer()
2291 35 : {
2292 35 : m_oLayer.FreeIndexFields(m_asIndexFields.data(), m_nIndexSize);
2293 35 : }
2294 :
2295 : IndexFieldsFreer(const IndexFieldsFreer &) = delete;
2296 : IndexFieldsFreer &operator=(const IndexFieldsFreer &) = delete;
2297 : };
2298 :
2299 35 : IndexFieldsFreer oIndexFieldsFreer(*this, asIndexFields, nIndexSize);
2300 :
2301 : /* -------------------------------------------------------------------- */
2302 : /* Read in all the key values. */
2303 : /* -------------------------------------------------------------------- */
2304 :
2305 1329 : for (auto &&poSrcFeat : *m_poSrcLayer)
2306 : {
2307 1294 : if (nIndexSize == nFeaturesAlloc)
2308 : {
2309 10 : const uint64_t nNewFeaturesAlloc64 =
2310 10 : static_cast<uint64_t>(nFeaturesAlloc) + nFeaturesAlloc / 3;
2311 : #if SIZEOF_SIZE_T == 4
2312 : if (static_cast<size_t>(nNewFeaturesAlloc64) !=
2313 : nNewFeaturesAlloc64 ||
2314 : static_cast<size_t>(sizeof(OGRField) * nOrderItems *
2315 : nNewFeaturesAlloc64) !=
2316 : static_cast<uint64_t>(sizeof(OGRField)) * nOrderItems *
2317 : nNewFeaturesAlloc64)
2318 : {
2319 : CPLError(CE_Failure, CPLE_AppDefined,
2320 : "Cannot allocate pasIndexFields");
2321 : return;
2322 : }
2323 : #endif
2324 10 : const size_t nNewFeaturesAlloc =
2325 : static_cast<size_t>(nNewFeaturesAlloc64);
2326 :
2327 : try
2328 : {
2329 10 : asIndexFields.resize(nOrderItems * nNewFeaturesAlloc);
2330 10 : anFIDList.reserve(nNewFeaturesAlloc);
2331 : }
2332 0 : catch (const std::bad_alloc &)
2333 : {
2334 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
2335 : "CreateOrderByIndex(): out of memory");
2336 0 : return;
2337 : }
2338 :
2339 20 : memset(asIndexFields.data() + nFeaturesAlloc * nOrderItems, 0,
2340 10 : sizeof(OGRField) * nOrderItems *
2341 10 : (nNewFeaturesAlloc - nFeaturesAlloc));
2342 :
2343 10 : nFeaturesAlloc = nNewFeaturesAlloc;
2344 : }
2345 :
2346 1294 : ReadIndexFields(poSrcFeat.get(), nOrderItems,
2347 1294 : asIndexFields.data() + nIndexSize * nOrderItems);
2348 :
2349 1294 : anFIDList.push_back(poSrcFeat->GetFID());
2350 :
2351 1294 : nIndexSize++;
2352 : }
2353 :
2354 : // CPLDebug("GenSQL", "CreateOrderByIndex() = %zu features", nIndexSize);
2355 :
2356 : /* -------------------------------------------------------------------- */
2357 : /* Initialize m_anFIDIndex */
2358 : /* -------------------------------------------------------------------- */
2359 : try
2360 : {
2361 35 : m_anFIDIndex.reserve(nIndexSize);
2362 : }
2363 0 : catch (const std::bad_alloc &)
2364 : {
2365 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
2366 : "CreateOrderByIndex(): out of memory");
2367 0 : return;
2368 : }
2369 1329 : for (size_t i = 0; i < nIndexSize; i++)
2370 1294 : m_anFIDIndex.push_back(static_cast<GIntBig>(i));
2371 :
2372 : /* -------------------------------------------------------------------- */
2373 : /* Quick sort the records. */
2374 : /* -------------------------------------------------------------------- */
2375 :
2376 : GIntBig *panMerged = static_cast<GIntBig *>(
2377 35 : VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nIndexSize));
2378 35 : if (panMerged == nullptr)
2379 : {
2380 0 : m_anFIDIndex.clear();
2381 0 : return;
2382 : }
2383 :
2384 : // Note: this merge sort is slightly faster than std::sort()
2385 35 : SortIndexSection(asIndexFields.data(), panMerged, 0, nIndexSize);
2386 35 : VSIFree(panMerged);
2387 :
2388 : /* -------------------------------------------------------------------- */
2389 : /* Rework the FID map to map to real FIDs. */
2390 : /* -------------------------------------------------------------------- */
2391 35 : bool bAlreadySorted = true;
2392 1329 : for (size_t i = 0; i < nIndexSize; i++)
2393 : {
2394 1294 : if (m_anFIDIndex[i] != static_cast<GIntBig>(i))
2395 716 : bAlreadySorted = false;
2396 1294 : m_anFIDIndex[i] = anFIDList[static_cast<size_t>(m_anFIDIndex[i])];
2397 : }
2398 :
2399 : /* If it is already sorted, then free than m_anFIDIndex array */
2400 : /* so that GetNextFeature() can call a sequential GetNextFeature() */
2401 : /* on the source array. Very useful for layers where random access */
2402 : /* is slow. */
2403 : /* Use case: the GML result of a WFS GetFeature with a SORTBY */
2404 35 : if (bAlreadySorted)
2405 : {
2406 16 : m_anFIDIndex.clear();
2407 : }
2408 :
2409 35 : ResetReading();
2410 : }
2411 :
2412 : /************************************************************************/
2413 : /* SortIndexSection() */
2414 : /* */
2415 : /* Sort the records in a section of the index. */
2416 : /************************************************************************/
2417 :
2418 2553 : void OGRGenSQLResultsLayer::SortIndexSection(const OGRField *pasIndexFields,
2419 : GIntBig *panMerged, size_t nStart,
2420 : size_t nEntries)
2421 :
2422 : {
2423 2553 : if (nEntries < 2)
2424 1294 : return;
2425 :
2426 1259 : swq_select *psSelectInfo = m_pSelectInfo.get();
2427 1259 : const int nOrderItems = psSelectInfo->order_specs;
2428 :
2429 1259 : size_t nFirstGroup = nEntries / 2;
2430 1259 : size_t nFirstStart = nStart;
2431 1259 : size_t nSecondGroup = nEntries - nFirstGroup;
2432 1259 : size_t nSecondStart = nStart + nFirstGroup;
2433 :
2434 1259 : SortIndexSection(pasIndexFields, panMerged, nFirstStart, nFirstGroup);
2435 1259 : SortIndexSection(pasIndexFields, panMerged, nSecondStart, nSecondGroup);
2436 :
2437 12515 : for (size_t iMerge = 0; iMerge < nEntries; ++iMerge)
2438 : {
2439 11256 : int nResult = 0;
2440 :
2441 11256 : if (nFirstGroup == 0)
2442 1451 : nResult = 1;
2443 9805 : else if (nSecondGroup == 0)
2444 1616 : nResult = -1;
2445 : else
2446 8189 : nResult = Compare(
2447 8189 : pasIndexFields + m_anFIDIndex[nFirstStart] * nOrderItems,
2448 8189 : pasIndexFields + m_anFIDIndex[nSecondStart] * nOrderItems);
2449 :
2450 11256 : if (nResult > 0)
2451 : {
2452 5732 : panMerged[iMerge] = m_anFIDIndex[nSecondStart];
2453 5732 : nSecondStart++;
2454 5732 : nSecondGroup--;
2455 : }
2456 : else
2457 : {
2458 5524 : panMerged[iMerge] = m_anFIDIndex[nFirstStart];
2459 5524 : nFirstStart++;
2460 5524 : nFirstGroup--;
2461 : }
2462 : }
2463 :
2464 : /* Copy the merge list back into the main index */
2465 1259 : memcpy(m_anFIDIndex.data() + nStart, panMerged, sizeof(GIntBig) * nEntries);
2466 : }
2467 :
2468 : /************************************************************************/
2469 : /* ComparePrimitive() */
2470 : /************************************************************************/
2471 :
2472 8131 : template <class T> static inline int ComparePrimitive(const T &a, const T &b)
2473 : {
2474 8131 : if (a < b)
2475 3925 : return -1;
2476 4206 : if (a > b)
2477 4206 : return 1;
2478 0 : return 0;
2479 : }
2480 :
2481 : /************************************************************************/
2482 : /* Compare() */
2483 : /************************************************************************/
2484 :
2485 8307 : int OGRGenSQLResultsLayer::Compare(const OGRField *pasFirstTuple,
2486 : const OGRField *pasSecondTuple)
2487 :
2488 : {
2489 8307 : swq_select *psSelectInfo = m_pSelectInfo.get();
2490 8307 : int nResult = 0, iKey;
2491 :
2492 16614 : for (iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++)
2493 : {
2494 8307 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2495 8307 : OGRFieldDefn *poFDefn = nullptr;
2496 :
2497 8307 : if (psKeyDef->field_index >= m_iFIDFieldIndex)
2498 58 : poFDefn = nullptr;
2499 : else
2500 16498 : poFDefn = m_poSrcLayer->GetLayerDefn()->GetFieldDefn(
2501 8249 : psKeyDef->field_index);
2502 :
2503 16614 : if (OGR_RawField_IsUnset(&pasFirstTuple[iKey]) ||
2504 8307 : OGR_RawField_IsNull(&pasFirstTuple[iKey]))
2505 : {
2506 62 : if (OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2507 31 : OGR_RawField_IsNull(&pasSecondTuple[iKey]))
2508 22 : nResult = 0;
2509 : else
2510 9 : nResult = -1;
2511 : }
2512 16552 : else if (OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2513 8276 : OGR_RawField_IsNull(&pasSecondTuple[iKey]))
2514 : {
2515 18 : nResult = 1;
2516 : }
2517 8258 : else if (poFDefn == nullptr)
2518 : {
2519 58 : CPLAssert(psKeyDef->field_index <
2520 : m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2521 58 : switch (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex])
2522 : {
2523 21 : case SWQ_INTEGER:
2524 : // Yes, read Integer in Integer64.
2525 : // This is consistent with what is done ReadIndexFields()
2526 : case SWQ_INTEGER64:
2527 21 : nResult = ComparePrimitive(pasFirstTuple[iKey].Integer64,
2528 21 : pasSecondTuple[iKey].Integer64);
2529 21 : break;
2530 22 : case SWQ_FLOAT:
2531 22 : nResult = ComparePrimitive(pasFirstTuple[iKey].Real,
2532 22 : pasSecondTuple[iKey].Real);
2533 22 : break;
2534 15 : case SWQ_STRING:
2535 15 : nResult = strcmp(pasFirstTuple[iKey].String,
2536 15 : pasSecondTuple[iKey].String);
2537 15 : break;
2538 :
2539 0 : default:
2540 0 : CPLAssert(false);
2541 : nResult = 0;
2542 : }
2543 : }
2544 8200 : else if (poFDefn->GetType() == OFTInteger)
2545 : {
2546 7938 : nResult = ComparePrimitive(pasFirstTuple[iKey].Integer,
2547 7938 : pasSecondTuple[iKey].Integer);
2548 : }
2549 262 : else if (poFDefn->GetType() == OFTInteger64)
2550 : {
2551 68 : nResult = ComparePrimitive(pasFirstTuple[iKey].Integer64,
2552 68 : pasSecondTuple[iKey].Integer64);
2553 : }
2554 194 : else if (poFDefn->GetType() == OFTString)
2555 : {
2556 : nResult =
2557 111 : strcmp(pasFirstTuple[iKey].String, pasSecondTuple[iKey].String);
2558 : }
2559 83 : else if (poFDefn->GetType() == OFTReal)
2560 : {
2561 82 : nResult = ComparePrimitive(pasFirstTuple[iKey].Real,
2562 82 : pasSecondTuple[iKey].Real);
2563 : }
2564 2 : else if (poFDefn->GetType() == OFTDate ||
2565 2 : poFDefn->GetType() == OFTTime ||
2566 1 : poFDefn->GetType() == OFTDateTime)
2567 : {
2568 : nResult =
2569 1 : OGRCompareDate(&pasFirstTuple[iKey], &pasSecondTuple[iKey]);
2570 : }
2571 :
2572 8307 : if (!(psKeyDef->ascending_flag))
2573 64 : nResult *= -1;
2574 : }
2575 :
2576 8307 : return nResult;
2577 : }
2578 :
2579 : /************************************************************************/
2580 : /* AddFieldDefnToSet() */
2581 : /************************************************************************/
2582 :
2583 17160 : void OGRGenSQLResultsLayer::AddFieldDefnToSet(int iTable, int iColumn,
2584 : CPLHashSet *hSet)
2585 : {
2586 17160 : if (iTable != -1)
2587 : {
2588 15335 : OGRLayer *poLayer = m_apoTableLayers[iTable];
2589 15335 : const auto poLayerDefn = poLayer->GetLayerDefn();
2590 15335 : const int nFieldCount = poLayerDefn->GetFieldCount();
2591 15335 : if (iColumn == -1)
2592 : {
2593 3026 : for (int i = 0; i < nFieldCount; ++i)
2594 : {
2595 2716 : OGRFieldDefn *poFDefn = poLayerDefn->GetFieldDefn(i);
2596 2716 : CPLHashSetInsert(hSet, poFDefn);
2597 : }
2598 :
2599 310 : const int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
2600 557 : for (int i = 0; i < nGeomFieldCount; ++i)
2601 : {
2602 247 : OGRGeomFieldDefn *poFDefn = poLayerDefn->GetGeomFieldDefn(i);
2603 247 : CPLHashSetInsert(hSet, poFDefn);
2604 : }
2605 : }
2606 : else
2607 : {
2608 15025 : if (iColumn < nFieldCount)
2609 : {
2610 13311 : OGRFieldDefn *poFDefn = poLayerDefn->GetFieldDefn(iColumn);
2611 13311 : CPLHashSetInsert(hSet, poFDefn);
2612 : }
2613 1714 : else if (iColumn == nFieldCount + SPF_OGR_GEOMETRY ||
2614 1701 : iColumn == nFieldCount + SPF_OGR_GEOM_WKT ||
2615 1700 : iColumn == nFieldCount + SPF_OGR_GEOM_AREA)
2616 : {
2617 19 : auto poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(0);
2618 19 : CPLHashSetInsert(hSet, poSrcGFDefn);
2619 : }
2620 1695 : else if (IS_GEOM_FIELD_INDEX(poLayerDefn, iColumn))
2621 : {
2622 : const int iSrcGeomField =
2623 1511 : ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(poLayerDefn, iColumn);
2624 1511 : auto poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
2625 1511 : CPLHashSetInsert(hSet, poSrcGFDefn);
2626 : }
2627 : }
2628 : }
2629 17160 : }
2630 :
2631 : /************************************************************************/
2632 : /* ExploreExprForIgnoredFields() */
2633 : /************************************************************************/
2634 :
2635 5622 : void OGRGenSQLResultsLayer::ExploreExprForIgnoredFields(swq_expr_node *expr,
2636 : CPLHashSet *hSet)
2637 : {
2638 5622 : if (expr->eNodeType == SNT_COLUMN)
2639 : {
2640 1995 : AddFieldDefnToSet(expr->table_index, expr->field_index, hSet);
2641 : }
2642 3627 : else if (expr->eNodeType == SNT_OPERATION)
2643 : {
2644 4253 : for (int i = 0; i < expr->nSubExprCount; i++)
2645 2821 : ExploreExprForIgnoredFields(expr->papoSubExpr[i], hSet);
2646 : }
2647 5622 : }
2648 :
2649 : /************************************************************************/
2650 : /* FindAndSetIgnoredFields() */
2651 : /************************************************************************/
2652 :
2653 2147 : void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
2654 : {
2655 2147 : swq_select *psSelectInfo = m_pSelectInfo.get();
2656 : CPLHashSet *hSet =
2657 2147 : CPLHashSetNew(CPLHashSetHashPointer, CPLHashSetEqualPointer, nullptr);
2658 :
2659 : /* -------------------------------------------------------------------- */
2660 : /* 1st phase : explore the whole select infos to determine which */
2661 : /* source fields are used */
2662 : /* -------------------------------------------------------------------- */
2663 17238 : for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
2664 : {
2665 15091 : swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
2666 15091 : AddFieldDefnToSet(psColDef->table_index, psColDef->field_index, hSet);
2667 15091 : if (psColDef->expr)
2668 1825 : ExploreExprForIgnoredFields(psColDef->expr, hSet);
2669 : }
2670 :
2671 2147 : if (psSelectInfo->where_expr)
2672 946 : ExploreExprForIgnoredFields(psSelectInfo->where_expr, hSet);
2673 :
2674 2177 : for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
2675 : {
2676 30 : swq_join_def *psJoinDef = psSelectInfo->join_defs + iJoin;
2677 30 : ExploreExprForIgnoredFields(psJoinDef->poExpr, hSet);
2678 : }
2679 :
2680 2221 : for (int iOrder = 0; iOrder < psSelectInfo->order_specs; iOrder++)
2681 : {
2682 74 : swq_order_def *psOrderDef = psSelectInfo->order_defs + iOrder;
2683 74 : AddFieldDefnToSet(psOrderDef->table_index, psOrderDef->field_index,
2684 : hSet);
2685 : }
2686 :
2687 : /* -------------------------------------------------------------------- */
2688 : /* 2nd phase : now, we can exclude the unused fields */
2689 : /* -------------------------------------------------------------------- */
2690 4324 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
2691 : {
2692 2177 : OGRLayer *poLayer = m_apoTableLayers[iTable];
2693 2177 : OGRFeatureDefn *poSrcFDefn = poLayer->GetLayerDefn();
2694 2177 : char **papszIgnoredFields = nullptr;
2695 2177 : const int nSrcFieldCount = poSrcFDefn->GetFieldCount();
2696 18043 : for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
2697 : {
2698 15866 : OGRFieldDefn *poFDefn = poSrcFDefn->GetFieldDefn(iSrcField);
2699 15866 : if (CPLHashSetLookup(hSet, poFDefn) == nullptr)
2700 : {
2701 : papszIgnoredFields =
2702 1197 : CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
2703 : // CPLDebug("OGR", "Adding %s to the list of ignored fields of
2704 : // layer %s",
2705 : // poFDefn->GetNameRef(), poLayer->GetName());
2706 : }
2707 : }
2708 2177 : const int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
2709 3988 : for (int iSrcField = 0; iSrcField < nSrcGeomFieldCount; iSrcField++)
2710 : {
2711 1811 : OGRGeomFieldDefn *poFDefn = poSrcFDefn->GetGeomFieldDefn(iSrcField);
2712 1811 : if (CPLHashSetLookup(hSet, poFDefn) == nullptr)
2713 : {
2714 : papszIgnoredFields =
2715 74 : CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
2716 : // CPLDebug("OGR", "Adding %s to the list of ignored fields of
2717 : // layer %s",
2718 : // poFDefn->GetNameRef(), poLayer->GetName());
2719 : }
2720 : }
2721 2177 : poLayer->SetIgnoredFields(
2722 2177 : const_cast<const char **>(papszIgnoredFields));
2723 2177 : CSLDestroy(papszIgnoredFields);
2724 : }
2725 :
2726 2147 : CPLHashSetDestroy(hSet);
2727 2147 : }
2728 :
2729 : /************************************************************************/
2730 : /* InvalidateOrderByIndex() */
2731 : /************************************************************************/
2732 :
2733 389 : void OGRGenSQLResultsLayer::InvalidateOrderByIndex()
2734 : {
2735 389 : m_anFIDIndex.clear();
2736 389 : m_bOrderByValid = false;
2737 389 : }
2738 :
2739 : /************************************************************************/
2740 : /* SetAttributeFilter() */
2741 : /************************************************************************/
2742 :
2743 46 : OGRErr OGRGenSQLResultsLayer::SetAttributeFilter(const char *pszAttributeFilter)
2744 : {
2745 : const std::string osAdditionalWHERE =
2746 92 : pszAttributeFilter ? pszAttributeFilter : "";
2747 92 : std::string osWHERE;
2748 46 : if (!m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty())
2749 : {
2750 3 : if (!osAdditionalWHERE.empty())
2751 2 : osWHERE += '(';
2752 3 : osWHERE += m_osInitialWHERE;
2753 3 : if (!osAdditionalWHERE.empty())
2754 2 : osWHERE += ") AND (";
2755 : }
2756 46 : osWHERE += osAdditionalWHERE;
2757 49 : if (!m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty() &&
2758 3 : !osAdditionalWHERE.empty())
2759 : {
2760 2 : osWHERE += ')';
2761 : }
2762 46 : InvalidateOrderByIndex();
2763 61 : return OGRLayer::SetAttributeFilter(osWHERE.empty() ? nullptr
2764 107 : : osWHERE.c_str());
2765 : }
2766 :
2767 : /************************************************************************/
2768 : /* SetSpatialFilter() */
2769 : /************************************************************************/
2770 :
2771 343 : void OGRGenSQLResultsLayer::SetSpatialFilter(int iGeomField,
2772 : OGRGeometry *poGeom)
2773 : {
2774 343 : InvalidateOrderByIndex();
2775 343 : if (iGeomField == 0)
2776 337 : OGRLayer::SetSpatialFilter(poGeom);
2777 : else
2778 6 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
2779 343 : }
2780 :
2781 : /************************************************************************/
2782 : /* OGRGenSQLResultsLayerArrowStreamPrivateData */
2783 : /************************************************************************/
2784 :
2785 : // Structure whose instances are set on the ArrowArrayStream::private_data
2786 : // member of the ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2787 : struct OGRGenSQLResultsLayerArrowStreamPrivateData
2788 : {
2789 : // Member shared with OGRLayer::m_poSharedArrowArrayStreamPrivateData
2790 : // If the layer pointed by poShared->poLayer is destroyed, before its
2791 : // destruction, it nullifies poShared->poLayer, which we can detect.
2792 : std::shared_ptr<OGRLayer::ArrowArrayStreamPrivateData> poShared{};
2793 :
2794 : // ArrowArrayStream to be used with poShared->poLayer
2795 : struct ArrowArrayStream *psSrcLayerStream = nullptr;
2796 :
2797 : // Original release() callback of the ArrowArrayStream passed to
2798 : // OGRGenSQLResultsLayer::GetArrowStream()
2799 : void (*release_backup)(struct ArrowArrayStream *) = nullptr;
2800 :
2801 : // Original private_data member of the ArrowArrayStream passed to
2802 : // OGRGenSQLResultsLayer::GetArrowStream()
2803 : void *private_data_backup = nullptr;
2804 :
2805 : // Set as the ArrowArrayStream::release callback member of the
2806 : // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2807 5 : static void Release(struct ArrowArrayStream *self)
2808 : {
2809 5 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2810 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2811 : self->private_data);
2812 :
2813 : // Release source layer stream
2814 5 : if (psPrivateData->psSrcLayerStream->release)
2815 5 : psPrivateData->psSrcLayerStream->release(
2816 : psPrivateData->psSrcLayerStream);
2817 5 : CPLFree(psPrivateData->psSrcLayerStream);
2818 :
2819 : // Release ourselves using the base method
2820 5 : self->private_data = psPrivateData->private_data_backup;
2821 5 : self->release = psPrivateData->release_backup;
2822 5 : delete psPrivateData;
2823 5 : if (self->release)
2824 5 : self->release(self);
2825 5 : }
2826 :
2827 : // Set as the ArrowArrayStream::get_schema callback member of the
2828 : // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2829 5 : static int GetSchema(struct ArrowArrayStream *self, struct ArrowSchema *out)
2830 : {
2831 5 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2832 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2833 : self->private_data);
2834 0 : auto poLayer = dynamic_cast<OGRGenSQLResultsLayer *>(
2835 5 : psPrivateData->poShared->m_poLayer);
2836 5 : if (!poLayer)
2837 : {
2838 0 : CPLError(
2839 : CE_Failure, CPLE_NotSupported,
2840 : "Calling get_schema() on a freed OGRLayer is not supported");
2841 0 : return EINVAL;
2842 : }
2843 5 : return poLayer->GetArrowSchemaForwarded(self, out);
2844 : }
2845 :
2846 : // Set as the ArrowArrayStream::get_next callback member of the
2847 : // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2848 9 : static int GetNext(struct ArrowArrayStream *self, struct ArrowArray *out)
2849 : {
2850 9 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2851 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2852 : self->private_data);
2853 1 : auto poLayer = dynamic_cast<OGRGenSQLResultsLayer *>(
2854 9 : psPrivateData->poShared->m_poLayer);
2855 9 : if (!poLayer)
2856 : {
2857 1 : CPLError(CE_Failure, CPLE_NotSupported,
2858 : "Calling get_next() on a freed OGRLayer is not supported");
2859 1 : return EINVAL;
2860 : }
2861 8 : return poLayer->GetNextArrowArrayForwarded(self, out);
2862 : }
2863 : };
2864 :
2865 : /************************************************************************/
2866 : /* GetArrowStream() */
2867 : /************************************************************************/
2868 :
2869 12 : bool OGRGenSQLResultsLayer::GetArrowStream(struct ArrowArrayStream *out_stream,
2870 : CSLConstList papszOptions)
2871 : {
2872 17 : if (!TestCapability(OLCFastGetArrowStream) ||
2873 5 : CPLTestBool(CPLGetConfigOption("OGR_GENSQL_STREAM_BASE_IMPL", "NO")))
2874 : {
2875 14 : CPLStringList aosOptions(papszOptions);
2876 7 : aosOptions.SetNameValue("OGR_GENSQL_STREAM_BASE_IMPL", "YES");
2877 7 : return OGRLayer::GetArrowStream(out_stream, aosOptions.List());
2878 : }
2879 :
2880 5 : const swq_select *psSelectInfo = m_pSelectInfo.get();
2881 5 : if (m_nIteratedFeatures != -1)
2882 : {
2883 0 : CPLError(CE_Failure, CPLE_AppDefined,
2884 : "GetArrowStream() not supported on non-rewinded layer");
2885 0 : return false;
2886 : }
2887 5 : CPLStringList aosOptions(papszOptions);
2888 5 : if (psSelectInfo->limit > 0)
2889 : {
2890 : aosOptions.SetNameValue(
2891 : "MAX_FEATURES_IN_BATCH",
2892 : CPLSPrintf(CPL_FRMT_GIB,
2893 1 : std::min(psSelectInfo->limit,
2894 2 : CPLAtoGIntBig(aosOptions.FetchNameValueDef(
2895 1 : "MAX_FEATURES_IN_BATCH", "65536")))));
2896 : }
2897 5 : bool bRet = OGRLayer::GetArrowStream(out_stream, aosOptions.List());
2898 5 : if (bRet)
2899 : {
2900 : auto psSrcLayerStream = static_cast<struct ArrowArrayStream *>(
2901 5 : CPLMalloc(sizeof(ArrowArrayStream)));
2902 5 : if (m_poSrcLayer->GetArrowStream(psSrcLayerStream, aosOptions.List()))
2903 : {
2904 : auto psPrivateData =
2905 5 : new OGRGenSQLResultsLayerArrowStreamPrivateData;
2906 5 : CPLAssert(m_poSharedArrowArrayStreamPrivateData);
2907 5 : psPrivateData->poShared = m_poSharedArrowArrayStreamPrivateData;
2908 5 : psPrivateData->psSrcLayerStream = psSrcLayerStream;
2909 5 : psPrivateData->release_backup = out_stream->release;
2910 5 : psPrivateData->private_data_backup = out_stream->private_data;
2911 5 : out_stream->get_schema =
2912 : OGRGenSQLResultsLayerArrowStreamPrivateData::GetSchema;
2913 5 : out_stream->get_next =
2914 : OGRGenSQLResultsLayerArrowStreamPrivateData::GetNext;
2915 5 : out_stream->release =
2916 : OGRGenSQLResultsLayerArrowStreamPrivateData::Release;
2917 5 : out_stream->private_data = psPrivateData;
2918 : }
2919 : else
2920 : {
2921 0 : if (psSrcLayerStream->release)
2922 0 : psSrcLayerStream->release(psSrcLayerStream);
2923 0 : CPLFree(psSrcLayerStream);
2924 0 : if (out_stream->release)
2925 0 : out_stream->release(out_stream);
2926 0 : bRet = false;
2927 : }
2928 : }
2929 5 : return bRet;
2930 : }
2931 :
2932 : /************************************************************************/
2933 : /* GetArrowSchema() */
2934 : /************************************************************************/
2935 :
2936 7 : int OGRGenSQLResultsLayer::GetArrowSchema(struct ArrowArrayStream *stream,
2937 : struct ArrowSchema *out_schema)
2938 : {
2939 7 : if (m_aosArrowArrayStreamOptions.FetchNameValue(
2940 7 : "OGR_GENSQL_STREAM_BASE_IMPL") ||
2941 0 : !TestCapability(OLCFastGetArrowStream))
2942 : {
2943 7 : return OGRLayer::GetArrowSchema(stream, out_schema);
2944 : }
2945 :
2946 0 : return GetArrowSchemaForwarded(stream, out_schema);
2947 : }
2948 :
2949 : /************************************************************************/
2950 : /* GetArrowSchemaForwarded() */
2951 : /************************************************************************/
2952 :
2953 5 : int OGRGenSQLResultsLayer::GetArrowSchemaForwarded(
2954 : struct ArrowArrayStream *stream, struct ArrowSchema *out_schema) const
2955 : {
2956 5 : const swq_select *psSelectInfo = m_pSelectInfo.get();
2957 5 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2958 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2959 : stream->private_data);
2960 10 : int ret = m_poSrcLayer->GetArrowSchema(psPrivateData->psSrcLayerStream,
2961 5 : out_schema);
2962 5 : if (ret == 0)
2963 : {
2964 : struct ArrowSchema newSchema;
2965 5 : ret = OGRCloneArrowSchema(out_schema, &newSchema) ? 0 : EIO;
2966 5 : if (out_schema->release)
2967 5 : out_schema->release(out_schema);
2968 5 : if (ret == 0)
2969 : {
2970 5 : std::map<std::string, std::string> oMapSrcNameToRenamed;
2971 18 : for (std::size_t iField = 0;
2972 18 : iField < psSelectInfo->column_defs.size(); iField++)
2973 : {
2974 : const swq_col_def *psColDef =
2975 13 : &psSelectInfo->column_defs[iField];
2976 13 : CPLAssert(!psColDef->bHidden);
2977 13 : CPLAssert(psColDef->table_index >= 0);
2978 13 : CPLAssert(psColDef->col_func == SWQCF_NONE);
2979 :
2980 : const auto poLayerDefn =
2981 13 : m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
2982 13 : CPLAssert(poLayerDefn);
2983 :
2984 26 : if (psColDef->field_index >= 0 &&
2985 13 : psColDef->field_index < poLayerDefn->GetFieldCount())
2986 : {
2987 : const auto poSrcFDefn =
2988 9 : poLayerDefn->GetFieldDefn(psColDef->field_index);
2989 9 : if (psColDef->field_alias)
2990 14 : oMapSrcNameToRenamed[poSrcFDefn->GetNameRef()] =
2991 14 : psColDef->field_alias;
2992 : }
2993 4 : else if (IS_GEOM_FIELD_INDEX(poLayerDefn,
2994 : psColDef->field_index))
2995 : {
2996 : const int iSrcGeomField =
2997 4 : ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
2998 : poLayerDefn, psColDef->field_index);
2999 : const auto poSrcGFDefn =
3000 4 : poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
3001 4 : if (psColDef->field_alias)
3002 4 : oMapSrcNameToRenamed[poSrcGFDefn->GetNameRef()] =
3003 4 : psColDef->field_alias;
3004 : }
3005 : }
3006 :
3007 23 : for (int i = 0; i < newSchema.n_children; ++i)
3008 : {
3009 : const auto oIter =
3010 18 : oMapSrcNameToRenamed.find(newSchema.children[i]->name);
3011 18 : if (oIter != oMapSrcNameToRenamed.end())
3012 : {
3013 7 : CPLFree(const_cast<char *>(newSchema.children[i]->name));
3014 14 : newSchema.children[i]->name =
3015 7 : CPLStrdup(oIter->second.c_str());
3016 : }
3017 : }
3018 :
3019 5 : memcpy(out_schema, &newSchema, sizeof(newSchema));
3020 : }
3021 : }
3022 5 : return ret;
3023 : }
3024 :
3025 : /************************************************************************/
3026 : /* GetNextArrowArray() */
3027 : /************************************************************************/
3028 :
3029 14 : int OGRGenSQLResultsLayer::GetNextArrowArray(struct ArrowArrayStream *stream,
3030 : struct ArrowArray *out_array)
3031 : {
3032 14 : if (m_aosArrowArrayStreamOptions.FetchNameValue(
3033 14 : "OGR_GENSQL_STREAM_BASE_IMPL") ||
3034 0 : !TestCapability(OLCFastGetArrowStream))
3035 : {
3036 14 : return OGRLayer::GetNextArrowArray(stream, out_array);
3037 : }
3038 :
3039 0 : return GetNextArrowArrayForwarded(stream, out_array);
3040 : }
3041 :
3042 : /************************************************************************/
3043 : /* GetNextArrowArrayForwarded() */
3044 : /************************************************************************/
3045 :
3046 8 : int OGRGenSQLResultsLayer::GetNextArrowArrayForwarded(
3047 : struct ArrowArrayStream *stream, struct ArrowArray *out_array)
3048 : {
3049 8 : const swq_select *psSelectInfo = m_pSelectInfo.get();
3050 8 : if (psSelectInfo->limit >= 0 && m_nIteratedFeatures >= psSelectInfo->limit)
3051 : {
3052 1 : memset(out_array, 0, sizeof(*out_array));
3053 1 : return 0;
3054 : }
3055 :
3056 7 : OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
3057 : static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
3058 : stream->private_data);
3059 14 : const int ret = m_poSrcLayer->GetNextArrowArray(
3060 7 : psPrivateData->psSrcLayerStream, out_array);
3061 7 : if (ret == 0 && psSelectInfo->limit >= 0)
3062 : {
3063 1 : if (m_nIteratedFeatures < 0)
3064 1 : m_nIteratedFeatures = 0;
3065 1 : m_nIteratedFeatures += out_array->length;
3066 1 : if (m_nIteratedFeatures > psSelectInfo->limit)
3067 : {
3068 0 : out_array->length -= m_nIteratedFeatures - psSelectInfo->limit;
3069 0 : for (int i = 0; i < out_array->n_children; ++i)
3070 : {
3071 0 : out_array->children[i]->length -=
3072 0 : m_nIteratedFeatures - psSelectInfo->limit;
3073 : }
3074 : }
3075 : }
3076 7 : return ret;
3077 : }
3078 :
3079 : //! @endcond
|