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