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