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