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