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