Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRVRTLayer class.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2009-2014, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "ogr_vrt.h"
16 :
17 : #include <cassert>
18 : #include <cmath>
19 : #include <cstddef>
20 : #include <cstdio>
21 : #include <cstdlib>
22 : #include <cstring>
23 : #include <limits>
24 : #include <string>
25 : #include <vector>
26 :
27 : #include "cpl_conv.h"
28 : #include "cpl_error.h"
29 : #include "cpl_minixml.h"
30 : #include "cpl_string.h"
31 : #include "gdal.h"
32 : #include "gdal_priv.h"
33 : #include "ogr_api.h"
34 : #include "ogr_core.h"
35 : #include "ogr_feature.h"
36 : #include "ogr_geometry.h"
37 : #include "ogr_spatialref.h"
38 : #include "ogrpgeogeometry.h"
39 : #include "ogrsf_frmts.h"
40 : #include "ogrvrtgeometrytypes.h"
41 : #include "memdataset.h"
42 :
43 : #define UNSUPPORTED_OP_READ_ONLY \
44 : "%s : unsupported operation on a read-only datasource."
45 :
46 : /************************************************************************/
47 : /* GetFieldIndexCaseSensitiveFirst() */
48 : /************************************************************************/
49 :
50 1653 : static int GetFieldIndexCaseSensitiveFirst(const OGRFeatureDefn *poFDefn,
51 : const char *pszFieldName)
52 : {
53 1653 : int idx = poFDefn->GetFieldIndexCaseSensitive(pszFieldName);
54 1653 : if (idx < 0)
55 470 : idx = poFDefn->GetFieldIndex(pszFieldName);
56 1653 : return idx;
57 : }
58 :
59 : /************************************************************************/
60 : /* OGRVRTGeomFieldProps() */
61 : /************************************************************************/
62 :
63 : OGRVRTGeomFieldProps::OGRVRTGeomFieldProps() = default;
64 :
65 : /************************************************************************/
66 : /* ~OGRVRTGeomFieldProps() */
67 : /************************************************************************/
68 :
69 : OGRVRTGeomFieldProps::~OGRVRTGeomFieldProps() = default;
70 :
71 : /************************************************************************/
72 : /* OGRVRTLayer() */
73 : /************************************************************************/
74 :
75 911 : OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource *poDSIn) : poDS(poDSIn)
76 : {
77 911 : }
78 :
79 : /************************************************************************/
80 : /* ~OGRVRTLayer() */
81 : /************************************************************************/
82 :
83 1822 : OGRVRTLayer::~OGRVRTLayer()
84 :
85 : {
86 911 : if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
87 : {
88 242 : CPLDebug("VRT", "%d features read on layer '%s'.",
89 121 : static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
90 : }
91 :
92 911 : if (poSrcDS != nullptr)
93 : {
94 444 : if (poSrcLayer)
95 : {
96 441 : poSrcLayer->SetIgnoredFields(nullptr);
97 441 : poSrcLayer->SetAttributeFilter(nullptr);
98 441 : poSrcLayer->SetSpatialFilter(nullptr);
99 : }
100 :
101 444 : if (bSrcLayerFromSQL && poSrcLayer)
102 2 : poSrcDS->ReleaseResultSet(poSrcLayer);
103 : }
104 :
105 911 : CPLFree(pszAttrFilter);
106 1822 : }
107 :
108 : /************************************************************************/
109 : /* GetSrcLayerDefn() */
110 : /************************************************************************/
111 :
112 40535 : OGRFeatureDefn *OGRVRTLayer::GetSrcLayerDefn()
113 : {
114 40535 : if (poSrcFeatureDefn)
115 40095 : return poSrcFeatureDefn;
116 :
117 440 : if (poSrcLayer)
118 440 : poSrcFeatureDefn = poSrcLayer->GetLayerDefn();
119 :
120 440 : return poSrcFeatureDefn;
121 : }
122 :
123 : /************************************************************************/
124 : /* FastInitialize() */
125 : /************************************************************************/
126 :
127 911 : bool OGRVRTLayer::FastInitialize(CPLXMLNode *psLTreeIn,
128 : const char *pszVRTDirectory, int bUpdateIn)
129 :
130 : {
131 911 : psLTree = psLTreeIn;
132 911 : bUpdate = CPL_TO_BOOL(bUpdateIn);
133 911 : osVRTDirectory = pszVRTDirectory;
134 :
135 911 : if (!EQUAL(psLTree->pszValue, "OGRVRTLayer"))
136 0 : return FALSE;
137 :
138 : // Get layer name.
139 911 : const char *pszLayerName = CPLGetXMLValue(psLTree, "name", nullptr);
140 :
141 911 : if (pszLayerName == nullptr)
142 : {
143 1 : CPLError(CE_Failure, CPLE_AppDefined,
144 : "Missing name attribute on OGRVRTLayer");
145 1 : return FALSE;
146 : }
147 :
148 910 : osName = pszLayerName;
149 910 : SetDescription(pszLayerName);
150 :
151 : // Do we have a fixed geometry type? If so, use it.
152 910 : CPLXMLNode *psGeometryFieldNode = CPLGetXMLNode(psLTree, "GeometryField");
153 910 : const char *pszGType = CPLGetXMLValue(psLTree, "GeometryType", nullptr);
154 910 : if (pszGType == nullptr && psGeometryFieldNode != nullptr)
155 31 : pszGType = CPLGetXMLValue(psGeometryFieldNode, "GeometryType", nullptr);
156 910 : if (pszGType != nullptr)
157 : {
158 359 : int l_bError = FALSE;
159 : const OGRwkbGeometryType eGeomType =
160 359 : OGRVRTGetGeometryType(pszGType, &l_bError);
161 359 : if (l_bError)
162 : {
163 1 : CPLError(CE_Failure, CPLE_AppDefined,
164 : "GeometryType %s not recognised.", pszGType);
165 1 : return FALSE;
166 : }
167 358 : if (eGeomType != wkbNone)
168 : {
169 351 : apoGeomFieldProps.push_back(
170 702 : std::make_unique<OGRVRTGeomFieldProps>());
171 351 : apoGeomFieldProps[0]->eGeomType = eGeomType;
172 : }
173 : }
174 :
175 : // Apply a spatial reference system if provided.
176 909 : const char *pszLayerSRS = CPLGetXMLValue(psLTree, "LayerSRS", nullptr);
177 909 : if (pszLayerSRS == nullptr && psGeometryFieldNode != nullptr)
178 142 : pszLayerSRS = CPLGetXMLValue(psGeometryFieldNode, "SRS", nullptr);
179 909 : if (pszLayerSRS != nullptr)
180 : {
181 184 : if (apoGeomFieldProps.empty())
182 : {
183 3 : apoGeomFieldProps.push_back(
184 6 : std::make_unique<OGRVRTGeomFieldProps>());
185 : }
186 184 : if (!(EQUAL(pszLayerSRS, "NULL")))
187 : {
188 184 : OGRSpatialReference oSRS;
189 184 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
190 :
191 184 : if (oSRS.SetFromUserInput(
192 : pszLayerSRS,
193 : OGRSpatialReference::
194 184 : SET_FROM_USER_INPUT_LIMITATIONS_get()) != OGRERR_NONE)
195 : {
196 1 : CPLError(CE_Failure, CPLE_AppDefined,
197 : "Failed to import LayerSRS `%s'.", pszLayerSRS);
198 1 : return FALSE;
199 : }
200 183 : apoGeomFieldProps[0]->poSRS =
201 366 : OGRSpatialReferenceRefCountedPtr::makeClone(&oSRS);
202 : }
203 : }
204 :
205 : // Set FeatureCount if provided.
206 : const char *pszFeatureCount =
207 908 : CPLGetXMLValue(psLTree, "FeatureCount", nullptr);
208 908 : if (pszFeatureCount != nullptr)
209 : {
210 1 : nFeatureCount = CPLAtoGIntBig(pszFeatureCount);
211 : }
212 :
213 : // Set Extent if provided.
214 908 : const char *pszExtentXMin = CPLGetXMLValue(psLTree, "ExtentXMin", nullptr);
215 908 : const char *pszExtentYMin = CPLGetXMLValue(psLTree, "ExtentYMin", nullptr);
216 908 : const char *pszExtentXMax = CPLGetXMLValue(psLTree, "ExtentXMax", nullptr);
217 908 : const char *pszExtentYMax = CPLGetXMLValue(psLTree, "ExtentYMax", nullptr);
218 908 : if (pszExtentXMin == nullptr && psGeometryFieldNode != nullptr)
219 : {
220 : pszExtentXMin =
221 312 : CPLGetXMLValue(psGeometryFieldNode, "ExtentXMin", nullptr);
222 : pszExtentYMin =
223 312 : CPLGetXMLValue(psGeometryFieldNode, "ExtentYMin", nullptr);
224 : pszExtentXMax =
225 312 : CPLGetXMLValue(psGeometryFieldNode, "ExtentXMax", nullptr);
226 : pszExtentYMax =
227 312 : CPLGetXMLValue(psGeometryFieldNode, "ExtentYMax", nullptr);
228 : }
229 908 : if (pszExtentXMin != nullptr && pszExtentYMin != nullptr &&
230 8 : pszExtentXMax != nullptr && pszExtentYMax != nullptr)
231 : {
232 8 : if (apoGeomFieldProps.empty())
233 : {
234 0 : apoGeomFieldProps.push_back(
235 0 : std::make_unique<OGRVRTGeomFieldProps>());
236 0 : assert(!apoGeomFieldProps.empty());
237 : }
238 8 : apoGeomFieldProps[0]->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
239 8 : apoGeomFieldProps[0]->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
240 8 : apoGeomFieldProps[0]->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
241 8 : apoGeomFieldProps[0]->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
242 : }
243 :
244 908 : return TRUE;
245 : }
246 :
247 : /************************************************************************/
248 : /* ParseGeometryField() */
249 : /************************************************************************/
250 :
251 145 : bool OGRVRTLayer::ParseGeometryField(CPLXMLNode *psNode,
252 : CPLXMLNode *psNodeParent,
253 : OGRVRTGeomFieldProps *poProps)
254 : {
255 145 : const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
256 145 : poProps->osName = pszName ? pszName : "";
257 145 : if (pszName == nullptr && apoGeomFieldProps.size() > 1 &&
258 0 : poProps != apoGeomFieldProps[0].get())
259 : {
260 0 : CPLError(CE_Warning, CPLE_AppDefined,
261 : "A 'name' attribute should be defined when there are "
262 : "several geometry fields");
263 : }
264 :
265 : // Do we have a fixed geometry type?
266 145 : const char *pszGType = CPLGetXMLValue(psNode, "GeometryType", nullptr);
267 145 : if (pszGType == nullptr && poProps == apoGeomFieldProps[0].get())
268 132 : pszGType = CPLGetXMLValue(psNodeParent, "GeometryType", nullptr);
269 145 : if (pszGType != nullptr)
270 : {
271 116 : int l_bError = FALSE;
272 116 : poProps->eGeomType = OGRVRTGetGeometryType(pszGType, &l_bError);
273 116 : if (l_bError)
274 : {
275 0 : CPLError(CE_Failure, CPLE_AppDefined,
276 : "GeometryType %s not recognised.", pszGType);
277 0 : return false;
278 : }
279 : }
280 :
281 : // Determine which field(s) to get the geometry from.
282 145 : const char *pszEncoding = CPLGetXMLValue(psNode, "encoding", "direct");
283 :
284 145 : if (EQUAL(pszEncoding, "Direct"))
285 28 : poProps->eGeometryStyle = VGS_Direct;
286 117 : else if (EQUAL(pszEncoding, "None"))
287 0 : poProps->eGeometryStyle = VGS_None;
288 117 : else if (EQUAL(pszEncoding, "WKT"))
289 52 : poProps->eGeometryStyle = VGS_WKT;
290 65 : else if (EQUAL(pszEncoding, "WKB"))
291 1 : poProps->eGeometryStyle = VGS_WKB;
292 64 : else if (EQUAL(pszEncoding, "Shape"))
293 1 : poProps->eGeometryStyle = VGS_Shape;
294 63 : else if (EQUAL(pszEncoding, "PointFromColumns"))
295 : {
296 62 : poProps->eGeometryStyle = VGS_PointFromColumns;
297 62 : poProps->bUseSpatialSubquery = CPLTestBool(
298 : CPLGetXMLValue(psNode, "GeometryField.useSpatialSubquery", "TRUE"));
299 :
300 62 : poProps->iGeomXField = GetFieldIndexCaseSensitiveFirst(
301 62 : GetSrcLayerDefn(), CPLGetXMLValue(psNode, "x", "missing"));
302 62 : poProps->iGeomYField = GetFieldIndexCaseSensitiveFirst(
303 62 : GetSrcLayerDefn(), CPLGetXMLValue(psNode, "y", "missing"));
304 62 : poProps->iGeomZField = GetFieldIndexCaseSensitiveFirst(
305 62 : GetSrcLayerDefn(), CPLGetXMLValue(psNode, "z", "missing"));
306 62 : poProps->iGeomMField = GetFieldIndexCaseSensitiveFirst(
307 62 : GetSrcLayerDefn(), CPLGetXMLValue(psNode, "m", "missing"));
308 :
309 62 : if (poProps->iGeomXField == -1 || poProps->iGeomYField == -1)
310 : {
311 1 : CPLError(CE_Failure, CPLE_AppDefined,
312 : "Unable to identify source X or Y field for "
313 : "PointFromColumns encoding.");
314 1 : return false;
315 : }
316 :
317 61 : if (pszGType == nullptr)
318 : {
319 7 : poProps->eGeomType = wkbPoint;
320 7 : if (poProps->iGeomZField != -1)
321 1 : poProps->eGeomType = OGR_GT_SetZ(poProps->eGeomType);
322 7 : if (poProps->iGeomMField != -1)
323 1 : poProps->eGeomType = OGR_GT_SetM(poProps->eGeomType);
324 : }
325 : }
326 : else
327 : {
328 1 : CPLError(CE_Failure, CPLE_AppDefined, "encoding=\"%s\" not recognised.",
329 : pszEncoding);
330 1 : return false;
331 : }
332 :
333 143 : if (poProps->eGeometryStyle == VGS_WKT ||
334 91 : poProps->eGeometryStyle == VGS_WKB ||
335 90 : poProps->eGeometryStyle == VGS_Shape)
336 : {
337 54 : const char *pszFieldName = CPLGetXMLValue(psNode, "field", "missing");
338 :
339 54 : poProps->iGeomField =
340 54 : GetFieldIndexCaseSensitiveFirst(GetSrcLayerDefn(), pszFieldName);
341 :
342 54 : if (poProps->iGeomField == -1)
343 : {
344 1 : CPLError(CE_Failure, CPLE_AppDefined,
345 : "Unable to identify source field '%s' for geometry.",
346 : pszFieldName);
347 1 : return false;
348 53 : }
349 : }
350 89 : else if (poProps->eGeometryStyle == VGS_Direct)
351 : {
352 28 : const char *pszFieldName = CPLGetXMLValue(psNode, "field", nullptr);
353 :
354 49 : if (pszFieldName != nullptr ||
355 21 : GetSrcLayerDefn()->GetGeomFieldCount() > 1)
356 : {
357 13 : if (pszFieldName == nullptr)
358 6 : pszFieldName = poProps->osName;
359 13 : poProps->iGeomField =
360 13 : GetSrcLayerDefn()->GetGeomFieldIndex(pszFieldName);
361 :
362 13 : if (poProps->iGeomField == -1)
363 : {
364 1 : CPLError(CE_Failure, CPLE_AppDefined,
365 : "Unable to identify source geometry field '%s' "
366 : "for geometry.",
367 : pszFieldName);
368 1 : return false;
369 : }
370 : }
371 15 : else if (GetSrcLayerDefn()->GetGeomFieldCount() == 1)
372 : {
373 15 : poProps->iGeomField = 0;
374 : }
375 0 : else if (psNode != nullptr)
376 : {
377 0 : CPLError(CE_Failure, CPLE_AppDefined,
378 : "Unable to identify source geometry field.");
379 0 : return false;
380 : }
381 : }
382 :
383 141 : poProps->bReportSrcColumn =
384 141 : CPLTestBool(CPLGetXMLValue(psNode, "reportSrcColumn", "YES"));
385 :
386 : // Guess geometry type if not explicitly provided (or computed).
387 141 : if (pszGType == nullptr && poProps->eGeomType == wkbUnknown)
388 : {
389 18 : if (GetSrcLayerDefn()->GetGeomFieldCount() == 1)
390 7 : poProps->eGeomType = poSrcLayer->GetGeomType();
391 11 : else if (poProps->eGeometryStyle == VGS_Direct &&
392 6 : poProps->iGeomField >= 0)
393 : {
394 12 : poProps->eGeomType = GetSrcLayerDefn()
395 6 : ->GetGeomFieldDefn(poProps->iGeomField)
396 6 : ->GetType();
397 : }
398 : }
399 :
400 : // Copy spatial reference system from source if not provided.
401 141 : const char *pszSRS = CPLGetXMLValue(psNode, "SRS", nullptr);
402 141 : if (pszSRS == nullptr && poProps == apoGeomFieldProps[0].get())
403 129 : pszSRS = CPLGetXMLValue(psNodeParent, "LayerSRS", nullptr);
404 141 : if (pszSRS == nullptr)
405 : {
406 40 : const OGRSpatialReference *poSRS = nullptr;
407 40 : if (GetSrcLayerDefn()->GetGeomFieldCount() == 1)
408 : {
409 20 : poSRS = poSrcLayer->GetSpatialRef();
410 : }
411 20 : else if (poProps->eGeometryStyle == VGS_Direct &&
412 6 : poProps->iGeomField >= 0)
413 : {
414 6 : poSRS = GetSrcLayerDefn()
415 6 : ->GetGeomFieldDefn(poProps->iGeomField)
416 6 : ->GetSpatialRef();
417 : }
418 40 : if (poSRS != nullptr)
419 11 : poProps->poSRS = OGRSpatialReferenceRefCountedPtr::makeClone(poSRS);
420 : }
421 101 : else if (poProps->poSRS == nullptr)
422 : {
423 98 : if (!(EQUAL(pszSRS, "NULL")))
424 : {
425 98 : OGRSpatialReference oSRS;
426 98 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
427 :
428 98 : if (oSRS.SetFromUserInput(
429 : pszSRS,
430 : OGRSpatialReference::
431 98 : SET_FROM_USER_INPUT_LIMITATIONS_get()) != OGRERR_NONE)
432 : {
433 0 : CPLError(CE_Failure, CPLE_AppDefined,
434 : "Failed to import SRS `%s'.", pszSRS);
435 0 : return false;
436 : }
437 98 : poProps->poSRS = OGRSpatialReferenceRefCountedPtr::makeClone(&oSRS);
438 : }
439 : }
440 :
441 : // Do we have a SrcRegion?
442 141 : const CPLXMLNode *psSrcRegionNode = CPLGetXMLNode(psNode, "SrcRegion");
443 141 : if (psSrcRegionNode == nullptr && poProps == apoGeomFieldProps[0].get())
444 129 : psSrcRegionNode = CPLGetXMLNode(psNodeParent, "SrcRegion");
445 141 : const char *pszSrcRegion = CPLGetXMLValue(psSrcRegionNode, "", nullptr);
446 141 : if (pszSrcRegion != nullptr)
447 : {
448 : poProps->poSrcRegion =
449 12 : OGRGeometryFactory::createFromWkt(pszSrcRegion).first;
450 :
451 12 : if (poProps->poSrcRegion == nullptr)
452 : {
453 1 : CPLError(CE_Warning, CPLE_AppDefined,
454 : "Ignoring SrcRegion. It must be a valid WKT geometry");
455 : }
456 :
457 12 : poProps->bSrcClip =
458 12 : CPLTestBool(CPLGetXMLValue(psSrcRegionNode, "clip", "FALSE"));
459 : }
460 :
461 : // Set Extent if provided.
462 141 : const char *pszExtentXMin = CPLGetXMLValue(psNode, "ExtentXMin", nullptr);
463 141 : const char *pszExtentYMin = CPLGetXMLValue(psNode, "ExtentYMin", nullptr);
464 141 : const char *pszExtentXMax = CPLGetXMLValue(psNode, "ExtentXMax", nullptr);
465 141 : const char *pszExtentYMax = CPLGetXMLValue(psNode, "ExtentYMax", nullptr);
466 141 : if (pszExtentXMin != nullptr && pszExtentYMin != nullptr &&
467 6 : pszExtentXMax != nullptr && pszExtentYMax != nullptr)
468 : {
469 6 : poProps->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
470 6 : poProps->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
471 6 : poProps->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
472 6 : poProps->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
473 : }
474 :
475 141 : poProps->bNullable =
476 141 : CPLTestBool(CPLGetXMLValue(psNode, "nullable", "TRUE"));
477 :
478 141 : if (GetSrcLayerDefn()->GetGeomFieldCount() == 1)
479 : {
480 : poProps->sCoordinatePrecision =
481 41 : GetSrcLayerDefn()->GetGeomFieldDefn(0)->GetCoordinatePrecision();
482 : }
483 100 : else if (poProps->eGeometryStyle == VGS_Direct && poProps->iGeomField >= 0)
484 : {
485 : poProps->sCoordinatePrecision =
486 12 : GetSrcLayerDefn()
487 12 : ->GetGeomFieldDefn(poProps->iGeomField)
488 12 : ->GetCoordinatePrecision();
489 : }
490 141 : if (const char *pszXYResolution =
491 141 : CPLGetXMLValue(psNode, "XYResolution", nullptr))
492 : {
493 1 : poProps->sCoordinatePrecision.dfXYResolution = CPLAtof(pszXYResolution);
494 : }
495 141 : if (const char *pszZResolution =
496 141 : CPLGetXMLValue(psNode, "ZResolution", nullptr))
497 : {
498 1 : poProps->sCoordinatePrecision.dfZResolution = CPLAtof(pszZResolution);
499 : }
500 141 : if (const char *pszMResolution =
501 141 : CPLGetXMLValue(psNode, "MResolution", nullptr))
502 : {
503 1 : poProps->sCoordinatePrecision.dfMResolution = CPLAtof(pszMResolution);
504 : }
505 :
506 141 : return true;
507 : }
508 :
509 : /************************************************************************/
510 : /* FullInitialize() */
511 : /************************************************************************/
512 :
513 : // TODO(schwehr): Remove gotos.
514 508 : bool OGRVRTLayer::FullInitialize()
515 : {
516 508 : if (bHasFullInitialized)
517 0 : return true;
518 :
519 508 : const char *pszSharedSetting = nullptr;
520 508 : const char *pszSQL = nullptr;
521 508 : const char *pszStyleFieldName = nullptr;
522 508 : CPLXMLNode *psChild = nullptr;
523 508 : bool bFoundGeometryField = false;
524 :
525 508 : bHasFullInitialized = true;
526 :
527 508 : poFeatureDefn = OGRFeatureDefnRefCountedPtr::makeInstance(osName);
528 :
529 508 : if (poDS->GetRecursionDetected())
530 34 : return false;
531 :
532 : // Figure out the data source name. It may be treated relative
533 : // to vrt filename, but normally it is used directly.
534 948 : std::string osSrcDSName = CPLGetXMLValue(psLTree, "SrcDataSource", "");
535 :
536 474 : if (osSrcDSName.empty())
537 : {
538 20 : CPLError(CE_Failure, CPLE_AppDefined,
539 : "Missing SrcDataSource for layer %s.", osName.c_str());
540 20 : goto error;
541 : }
542 :
543 454 : if (CPLTestBool(
544 454 : CPLGetXMLValue(psLTree, "SrcDataSource.relativetoVRT", "0")))
545 : {
546 : static const char *const apszPrefixes[] = {"CSV:", "GPSBABEL:"};
547 261 : bool bDone = false;
548 783 : for (size_t i = 0; i < sizeof(apszPrefixes) / sizeof(apszPrefixes[0]);
549 : i++)
550 : {
551 522 : const char *pszPrefix = apszPrefixes[i];
552 522 : if (EQUALN(osSrcDSName.c_str(), pszPrefix, strlen(pszPrefix)))
553 : {
554 0 : auto nLastPart = osSrcDSName.find(':') + 1;
555 : // CSV:z:/foo.xyz
556 0 : if ((osSrcDSName[nLastPart] == '/' ||
557 0 : osSrcDSName[nLastPart] == '\\') &&
558 0 : nLastPart >= 3 && osSrcDSName[nLastPart - 3] == ':')
559 0 : nLastPart -= 2;
560 0 : CPLString osPrefix(osSrcDSName);
561 0 : osPrefix.resize(nLastPart);
562 0 : osSrcDSName = osPrefix + CPLProjectRelativeFilenameSafe(
563 : osVRTDirectory,
564 0 : osSrcDSName.c_str() + nLastPart);
565 0 : bDone = true;
566 0 : break;
567 : }
568 : }
569 261 : if (!bDone)
570 : {
571 522 : osSrcDSName = CPLProjectRelativeFilenameSafe(osVRTDirectory,
572 261 : osSrcDSName.c_str());
573 : }
574 : }
575 :
576 : // Are we accessing this datasource in shared mode? We default
577 : // to shared for SrcSQL requests, but we also allow the XML to
578 : // control our shared setting with an attribute on the
579 : // datasource element.
580 454 : pszSharedSetting = CPLGetXMLValue(psLTree, "SrcDataSource.shared", nullptr);
581 454 : if (pszSharedSetting == nullptr)
582 : {
583 377 : if (CPLGetXMLValue(psLTree, "SrcSQL", nullptr) == nullptr)
584 374 : pszSharedSetting = "OFF";
585 : else
586 3 : pszSharedSetting = "ON";
587 : }
588 :
589 454 : bSrcDSShared = CPLTestBool(pszSharedSetting);
590 :
591 : // Update mode doesn't make sense if we have a SrcSQL element.
592 454 : if (CPLGetXMLValue(psLTree, "SrcSQL", nullptr) != nullptr)
593 3 : bUpdate = false;
594 :
595 : // Try to access the datasource.
596 454 : try_again:
597 454 : CPLErrorReset();
598 454 : if (EQUAL(osSrcDSName.c_str(), "@dummy@"))
599 : {
600 0 : poSrcDS.reset(
601 0 : MEMDataset::Create("@dummy@", 0, 0, 0, GDT_Unknown, nullptr));
602 0 : poSrcDS->CreateLayer("@dummy@");
603 : }
604 454 : else if (bSrcDSShared)
605 : {
606 79 : if (poDS->IsInForbiddenNames(osSrcDSName.c_str()))
607 : {
608 4 : CPLError(CE_Failure, CPLE_AppDefined,
609 : "Cyclic VRT opening detected!");
610 4 : poDS->SetRecursionDetected();
611 : }
612 : else
613 : {
614 : CPLStringList aosOpenOptions(
615 150 : GDALDeserializeOpenOptionsFromXML(psLTree));
616 75 : int l_nFlags = GDAL_OF_VECTOR | GDAL_OF_SHARED;
617 75 : if (bUpdate)
618 0 : l_nFlags |= GDAL_OF_UPDATE;
619 75 : poSrcDS.reset(GDALDataset::Open(osSrcDSName.c_str(), l_nFlags,
620 75 : nullptr, aosOpenOptions.List(),
621 : nullptr));
622 : // Is it a VRT datasource?
623 75 : if (poSrcDS != nullptr && poSrcDS->GetDriver() == poDS->GetDriver())
624 : {
625 : OGRVRTDataSource *poVRTSrcDS =
626 3 : cpl::down_cast<OGRVRTDataSource *>(poSrcDS.get());
627 3 : poVRTSrcDS->AddForbiddenNames(poDS->GetDescription());
628 : }
629 : }
630 : }
631 : else
632 : {
633 375 : if (poDS->GetCallLevel() < 32)
634 : {
635 : CPLStringList aosOpenOptions(
636 746 : GDALDeserializeOpenOptionsFromXML(psLTree));
637 373 : int l_nFlags = GDAL_OF_VECTOR;
638 373 : if (bUpdate)
639 44 : l_nFlags |= GDAL_OF_UPDATE;
640 373 : poSrcDS.reset(GDALDataset::Open(osSrcDSName.c_str(), l_nFlags,
641 373 : nullptr, aosOpenOptions.List(),
642 : nullptr));
643 : // Is it a VRT datasource?
644 373 : if (poSrcDS != nullptr && poSrcDS->GetDriver() == poDS->GetDriver())
645 : {
646 : OGRVRTDataSource *poVRTSrcDS =
647 66 : dynamic_cast<OGRVRTDataSource *>(poSrcDS.get());
648 66 : if (poVRTSrcDS)
649 : {
650 66 : poVRTSrcDS->SetCallLevel(poDS->GetCallLevel() + 1);
651 66 : poVRTSrcDS->SetParentDS(poDS);
652 : }
653 : }
654 : }
655 : else
656 : {
657 2 : CPLError(CE_Failure, CPLE_AppDefined,
658 : "Trying to open a VRT from a VRT from a VRT from ... "
659 : "[32 times] a VRT!");
660 :
661 2 : poDS->SetRecursionDetected();
662 :
663 2 : OGRVRTDataSource *poParent = poDS->GetParentDS();
664 66 : while (poParent != nullptr)
665 : {
666 64 : poParent->SetRecursionDetected();
667 64 : poParent = poParent->GetParentDS();
668 : }
669 : }
670 : }
671 :
672 454 : if (poSrcDS == nullptr)
673 : {
674 10 : if (bUpdate)
675 : {
676 0 : CPLError(CE_Warning, CPLE_AppDefined,
677 : "Cannot open datasource `%s' in update mode. "
678 : "Trying again in read-only mode",
679 : osSrcDSName.c_str());
680 0 : bUpdate = false;
681 0 : goto try_again;
682 : }
683 10 : if (strlen(CPLGetLastErrorMsg()) == 0)
684 4 : CPLError(CE_Failure, CPLE_AppDefined,
685 : "Failed to open datasource `%s'.", osSrcDSName.c_str());
686 10 : goto error;
687 : }
688 :
689 : // Apply any metadata.
690 444 : oMDMD.XMLInit(psLTree, TRUE);
691 :
692 : // Is this layer derived from an SQL query result?
693 444 : pszSQL = CPLGetXMLValue(psLTree, "SrcSQL", nullptr);
694 :
695 444 : if (pszSQL != nullptr)
696 : {
697 : const char *pszDialect =
698 3 : CPLGetXMLValue(psLTree, "SrcSQL.dialect", nullptr);
699 3 : if (pszDialect != nullptr && pszDialect[0] == '\0')
700 0 : pszDialect = nullptr;
701 3 : poSrcLayer = poSrcDS->ExecuteSQL(pszSQL, nullptr, pszDialect);
702 3 : if (poSrcLayer == nullptr)
703 : {
704 1 : CPLError(CE_Failure, CPLE_AppDefined,
705 : "SQL statement failed, or returned no layer result:\n%s",
706 : pszSQL);
707 1 : goto error;
708 : }
709 2 : bSrcLayerFromSQL = true;
710 : }
711 :
712 : // Fetch the layer if it is a regular layer.
713 443 : if (poSrcLayer == nullptr)
714 : {
715 : const char *pszSrcLayerName =
716 441 : CPLGetXMLValue(psLTree, "SrcLayer", osName);
717 :
718 441 : poSrcLayer = poSrcDS->GetLayerByName(pszSrcLayerName);
719 441 : if (poSrcLayer == nullptr)
720 : {
721 2 : CPLError(CE_Failure, CPLE_AppDefined,
722 : "Failed to find layer '%s' on datasource '%s'.",
723 : pszSrcLayerName, osSrcDSName.c_str());
724 2 : goto error;
725 : }
726 : }
727 :
728 : // Search for GeometryField definitions.
729 :
730 : // Create as many OGRVRTGeomFieldProps as there are
731 : // GeometryField elements.
732 1973 : for (psChild = psLTree->psChild; psChild != nullptr;
733 1532 : psChild = psChild->psNext)
734 : {
735 1536 : if (psChild->eType == CXT_Element &&
736 1044 : EQUAL(psChild->pszValue, "GeometryField"))
737 : {
738 137 : if (!bFoundGeometryField)
739 : {
740 131 : bFoundGeometryField = true;
741 :
742 : // Recreate the first one if already taken into account in
743 : // FastInitialize().
744 131 : if (apoGeomFieldProps.size() == 1)
745 : {
746 111 : apoGeomFieldProps.clear();
747 : }
748 : }
749 :
750 137 : apoGeomFieldProps.push_back(
751 274 : std::make_unique<OGRVRTGeomFieldProps>());
752 137 : if (!ParseGeometryField(psChild, psLTree,
753 137 : apoGeomFieldProps.back().get()))
754 : {
755 4 : goto error;
756 : }
757 : }
758 : }
759 :
760 747 : if (!bFoundGeometryField &&
761 310 : CPLGetXMLValue(psLTree, "SrcRegion", nullptr) != nullptr)
762 : {
763 3 : apoGeomFieldProps.push_back(std::make_unique<OGRVRTGeomFieldProps>());
764 : }
765 :
766 437 : if (!bFoundGeometryField && apoGeomFieldProps.size() == 1)
767 : {
768 : // Otherwise use the top-level elements such as SrcRegion.
769 8 : if (!ParseGeometryField(nullptr, psLTree, apoGeomFieldProps[0].get()))
770 0 : goto error;
771 : }
772 :
773 739 : if (apoGeomFieldProps.empty() &&
774 302 : CPLGetXMLValue(psLTree, "GeometryType", nullptr) == nullptr)
775 : {
776 : // If no GeometryField is found but source geometry fields
777 : // exist, use them.
778 297 : for (int iGeomField = 0;
779 604 : iGeomField < GetSrcLayerDefn()->GetGeomFieldCount(); iGeomField++)
780 : {
781 307 : apoGeomFieldProps.push_back(
782 614 : std::make_unique<OGRVRTGeomFieldProps>());
783 307 : OGRVRTGeomFieldProps *poProps = apoGeomFieldProps.back().get();
784 : OGRGeomFieldDefn *poFDefn =
785 307 : GetSrcLayerDefn()->GetGeomFieldDefn(iGeomField);
786 307 : poProps->osName = poFDefn->GetNameRef();
787 307 : poProps->eGeomType = poFDefn->GetType();
788 614 : poProps->poSRS = OGRSpatialReferenceRefCountedPtr::makeClone(
789 614 : poFDefn->GetSpatialRef());
790 307 : poProps->iGeomField = iGeomField;
791 307 : poProps->bNullable = CPL_TO_BOOL(poFDefn->IsNullable());
792 : }
793 : }
794 :
795 : // Instantiate real geometry fields from VRT properties.
796 437 : poFeatureDefn->SetGeomType(wkbNone);
797 885 : for (const auto &poProp : apoGeomFieldProps)
798 : {
799 896 : OGRGeomFieldDefn oFieldDefn(poProp->osName, poProp->eGeomType);
800 448 : oFieldDefn.SetSpatialRef(poProp->poSRS);
801 448 : oFieldDefn.SetNullable(poProp->bNullable);
802 448 : oFieldDefn.SetCoordinatePrecision(poProp->sCoordinatePrecision);
803 448 : poFeatureDefn->AddGeomFieldDefn(&oFieldDefn);
804 : }
805 :
806 437 : bAttrFilterPassThrough = true;
807 :
808 : // Figure out what should be used as an FID.
809 : {
810 437 : CPLXMLNode *psFIDNode = CPLGetXMLNode(psLTree, "FID");
811 437 : if (psFIDNode != nullptr)
812 : {
813 : const char *pszSrcFIDFieldName =
814 31 : CPLGetXMLValue(psFIDNode, nullptr, "");
815 31 : if (!EQUAL(pszSrcFIDFieldName, ""))
816 : {
817 31 : iFIDField = GetFieldIndexCaseSensitiveFirst(GetSrcLayerDefn(),
818 : pszSrcFIDFieldName);
819 31 : if (iFIDField == -1)
820 : {
821 1 : CPLError(CE_Failure, CPLE_AppDefined,
822 : "Unable to identify FID field '%s'.",
823 : pszSrcFIDFieldName);
824 1 : goto error;
825 : }
826 : }
827 :
828 : // User facing FID column name.
829 : osFIDFieldName =
830 30 : CPLGetXMLValue(psFIDNode, "name", pszSrcFIDFieldName);
831 30 : if (!EQUAL(osFIDFieldName, poSrcLayer->GetFIDColumn()))
832 : {
833 30 : bAttrFilterPassThrough = false;
834 : }
835 : }
836 : else
837 : {
838 406 : osFIDFieldName = poSrcLayer->GetFIDColumn();
839 : }
840 : }
841 :
842 : // Figure out what should be used as a Style.
843 436 : pszStyleFieldName = CPLGetXMLValue(psLTree, "Style", nullptr);
844 :
845 436 : if (pszStyleFieldName != nullptr)
846 : {
847 4 : iStyleField = GetFieldIndexCaseSensitiveFirst(GetSrcLayerDefn(),
848 : pszStyleFieldName);
849 4 : if (iStyleField == -1)
850 : {
851 1 : CPLError(CE_Failure, CPLE_AppDefined,
852 : "Unable to identify Style field '%s'.", pszStyleFieldName);
853 1 : goto error;
854 : }
855 :
856 3 : if (!EQUAL(pszStyleFieldName, "OGR_STYLE"))
857 : {
858 3 : bAttrFilterPassThrough = false;
859 : }
860 : }
861 :
862 : // Search for schema definitions in the VRT.
863 1946 : for (psChild = psLTree->psChild; psChild != nullptr;
864 1511 : psChild = psChild->psNext)
865 : {
866 1518 : if (psChild->eType == CXT_Element && EQUAL(psChild->pszValue, "Field"))
867 : {
868 : // Field name.
869 84 : const char *pszName = CPLGetXMLValue(psChild, "name", nullptr);
870 84 : if (pszName == nullptr)
871 : {
872 1 : CPLError(CE_Failure, CPLE_AppDefined,
873 : "Unable to identify Field name.");
874 7 : goto error;
875 : }
876 :
877 83 : OGRFieldDefn oFieldDefn(pszName, OFTString);
878 :
879 : // Type.
880 83 : const char *pszArg = CPLGetXMLValue(psChild, "type", nullptr);
881 :
882 83 : if (pszArg != nullptr)
883 : {
884 69 : int iType = 0; // Used after for.
885 :
886 339 : for (; iType <= static_cast<int>(OFTMaxType); iType++)
887 : {
888 338 : if (EQUAL(pszArg, OGRFieldDefn::GetFieldTypeName(
889 : static_cast<OGRFieldType>(iType))))
890 : {
891 68 : oFieldDefn.SetType(static_cast<OGRFieldType>(iType));
892 68 : break;
893 : }
894 : }
895 :
896 69 : if (iType > static_cast<int>(OFTMaxType))
897 : {
898 1 : CPLError(CE_Failure, CPLE_AppDefined,
899 : "Unable to identify Field type '%s'.", pszArg);
900 1 : goto error;
901 : }
902 : }
903 :
904 : // Subtype.
905 82 : pszArg = CPLGetXMLValue(psChild, "subtype", nullptr);
906 82 : if (pszArg != nullptr)
907 : {
908 7 : OGRFieldSubType eSubType = OFSTNone;
909 :
910 7 : int iType = 0; // Used after for.
911 19 : for (; iType <= static_cast<int>(OFSTMaxSubType); iType++)
912 : {
913 18 : if (EQUAL(pszArg, OGRFieldDefn::GetFieldSubTypeName(
914 : static_cast<OGRFieldSubType>(iType))))
915 : {
916 6 : eSubType = static_cast<OGRFieldSubType>(iType);
917 6 : break;
918 : }
919 : }
920 :
921 7 : if (iType > static_cast<int>(OFSTMaxSubType))
922 : {
923 1 : CPLError(CE_Failure, CPLE_AppDefined,
924 : "Unable to identify Field subtype '%s'.", pszArg);
925 1 : goto error;
926 : }
927 :
928 6 : if (!OGR_AreTypeSubTypeCompatible(oFieldDefn.GetType(),
929 : eSubType))
930 : {
931 1 : CPLError(
932 : CE_Failure, CPLE_AppDefined,
933 : "Invalid subtype '%s' for type '%s'.", pszArg,
934 : OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()));
935 1 : goto error;
936 : }
937 :
938 5 : oFieldDefn.SetSubType(eSubType);
939 : }
940 :
941 : // Width and precision.
942 80 : int nWidth = atoi(CPLGetXMLValue(psChild, "width", "0"));
943 80 : if (nWidth < 0)
944 : {
945 1 : CPLError(CE_Failure, CPLE_IllegalArg,
946 : "Invalid width for field %s.", pszName);
947 1 : goto error;
948 : }
949 79 : oFieldDefn.SetWidth(nWidth);
950 :
951 79 : int nPrecision = atoi(CPLGetXMLValue(psChild, "precision", "0"));
952 79 : if (nPrecision < 0 || nPrecision > 1024)
953 : {
954 1 : CPLError(CE_Failure, CPLE_IllegalArg,
955 : "Invalid precision for field %s.", pszName);
956 1 : goto error;
957 : }
958 78 : oFieldDefn.SetPrecision(nPrecision);
959 :
960 : // Nullable attribute.
961 : const bool bNullable =
962 78 : CPLTestBool(CPLGetXMLValue(psChild, "nullable", "true"));
963 78 : oFieldDefn.SetNullable(bNullable);
964 :
965 : // Unique attribute.
966 : const bool bUnique =
967 78 : CPLTestBool(CPLGetXMLValue(psChild, "unique", "false"));
968 78 : oFieldDefn.SetUnique(bUnique);
969 :
970 : // Default attribute.
971 78 : oFieldDefn.SetDefault(CPLGetXMLValue(psChild, "default", nullptr));
972 :
973 : const char *pszAlternativeName =
974 78 : CPLGetXMLValue(psChild, "alternativeName", nullptr);
975 78 : if (pszAlternativeName)
976 1 : oFieldDefn.SetAlternativeName(pszAlternativeName);
977 :
978 : const char *pszComment =
979 78 : CPLGetXMLValue(psChild, "comment", nullptr);
980 78 : if (pszComment)
981 1 : oFieldDefn.SetComment(pszComment);
982 :
983 : // Create the field.
984 78 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
985 :
986 78 : abDirectCopy.push_back(FALSE);
987 :
988 : // Source field.
989 : int iSrcField =
990 78 : GetFieldIndexCaseSensitiveFirst(GetSrcLayerDefn(), pszName);
991 :
992 78 : pszArg = CPLGetXMLValue(psChild, "src", nullptr);
993 :
994 78 : if (pszArg != nullptr)
995 : {
996 55 : iSrcField =
997 55 : GetFieldIndexCaseSensitiveFirst(GetSrcLayerDefn(), pszArg);
998 55 : if (iSrcField == -1)
999 : {
1000 1 : CPLError(CE_Failure, CPLE_AppDefined,
1001 : "Unable to find source field '%s'.", pszArg);
1002 1 : goto error;
1003 : }
1004 : }
1005 :
1006 77 : if (iSrcField < 0 ||
1007 54 : (pszArg != nullptr && strcmp(pszArg, pszName) != 0))
1008 : {
1009 7 : bAttrFilterPassThrough = false;
1010 : }
1011 : else
1012 : {
1013 : OGRFieldDefn *poSrcFieldDefn =
1014 70 : GetSrcLayerDefn()->GetFieldDefn(iSrcField);
1015 70 : if (poSrcFieldDefn->GetType() != oFieldDefn.GetType())
1016 46 : bAttrFilterPassThrough = false;
1017 : }
1018 :
1019 77 : anSrcField.push_back(iSrcField);
1020 : }
1021 : }
1022 :
1023 428 : CPLAssert(poFeatureDefn->GetFieldCount() ==
1024 : static_cast<int>(anSrcField.size()));
1025 :
1026 : // Create the schema, if it was not explicitly in the VRT.
1027 428 : if (poFeatureDefn->GetFieldCount() == 0)
1028 : {
1029 400 : const int nSrcFieldCount = GetSrcLayerDefn()->GetFieldCount();
1030 :
1031 1368 : for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
1032 : {
1033 968 : bool bSkip = false;
1034 2199 : for (const auto &poProp : apoGeomFieldProps)
1035 : {
1036 1259 : if (!poProp->bReportSrcColumn &&
1037 20 : (iSrcField == poProp->iGeomXField ||
1038 16 : iSrcField == poProp->iGeomYField ||
1039 12 : iSrcField == poProp->iGeomZField ||
1040 12 : iSrcField == poProp->iGeomMField ||
1041 12 : (poProp->eGeometryStyle != VGS_Direct &&
1042 12 : iSrcField == poProp->iGeomField)))
1043 : {
1044 8 : bSkip = true;
1045 8 : break;
1046 : }
1047 : }
1048 968 : if (bSkip)
1049 8 : continue;
1050 :
1051 960 : poFeatureDefn->AddFieldDefn(
1052 960 : GetSrcLayerDefn()->GetFieldDefn(iSrcField));
1053 960 : anSrcField.push_back(iSrcField);
1054 960 : abDirectCopy.push_back(TRUE);
1055 : }
1056 :
1057 400 : bAttrFilterPassThrough = true;
1058 : }
1059 :
1060 : // Is VRT layer definition identical to the source layer defn?
1061 : // If so, use it directly, and save the translation of features.
1062 823 : if (GetSrcLayerDefn() != nullptr && iFIDField == -1 && iStyleField == -1 &&
1063 395 : GetSrcLayerDefn()->IsSame(poFeatureDefn.get()))
1064 : {
1065 242 : bool bSame = true;
1066 534 : for (size_t i = 0; i < apoGeomFieldProps.size(); i++)
1067 : {
1068 584 : if (apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct ||
1069 292 : apoGeomFieldProps[i]->iGeomField != static_cast<int>(i))
1070 : {
1071 0 : bSame = false;
1072 0 : break;
1073 : }
1074 : }
1075 242 : if (bSame)
1076 : {
1077 242 : CPLDebug("VRT", "Source feature definition is identical to VRT "
1078 : "feature definition. Use optimized path");
1079 242 : poFeatureDefn.reset(GetSrcLayerDefn(), /* add_ref = */ true);
1080 534 : for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1081 : {
1082 292 : apoGeomFieldProps[i]->poSRS.reset(
1083 : const_cast<OGRSpatialReference *>(
1084 292 : poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef()),
1085 : /* add_ref = */ true);
1086 : }
1087 : }
1088 : }
1089 :
1090 428 : CPLAssert(poFeatureDefn->GetGeomFieldCount() ==
1091 : static_cast<int>(apoGeomFieldProps.size()));
1092 :
1093 : // Allow vrt to override whether attribute filters should be
1094 : // passed through.
1095 428 : if (CPLGetXMLValue(psLTree, "attrFilterPassThrough", nullptr) != nullptr)
1096 0 : bAttrFilterPassThrough = CPLTestBool(
1097 0 : CPLGetXMLValue(psLTree, "attrFilterPassThrough", "TRUE"));
1098 :
1099 428 : SetIgnoredFields(nullptr);
1100 :
1101 428 : return true;
1102 :
1103 46 : error:
1104 46 : bError = true;
1105 46 : poFeatureDefn = OGRFeatureDefnRefCountedPtr::makeInstance(osName);
1106 46 : poFeatureDefn->SetGeomType(wkbNone);
1107 46 : apoGeomFieldProps.clear();
1108 46 : return false;
1109 : }
1110 :
1111 : /************************************************************************/
1112 : /* ResetReading() */
1113 : /************************************************************************/
1114 :
1115 3403 : void OGRVRTLayer::ResetReading()
1116 : {
1117 3403 : bNeedReset = true;
1118 3403 : }
1119 :
1120 : /************************************************************************/
1121 : /* ResetSourceReading() */
1122 : /************************************************************************/
1123 :
1124 1444 : bool OGRVRTLayer::ResetSourceReading()
1125 :
1126 : {
1127 1444 : bool bSuccess = true;
1128 :
1129 : // Do we want to let source layer do spatial restriction?
1130 1444 : char *pszFilter = nullptr;
1131 4317 : for (size_t i = 0; i < apoGeomFieldProps.size(); i++)
1132 : {
1133 2067 : if ((m_poFilterGeom || apoGeomFieldProps[i]->poSrcRegion) &&
1134 5004 : apoGeomFieldProps[i]->bUseSpatialSubquery &&
1135 32 : apoGeomFieldProps[i]->eGeometryStyle == VGS_PointFromColumns)
1136 : {
1137 64 : OGRFieldDefn *poXField = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1138 32 : apoGeomFieldProps[i]->iGeomXField);
1139 64 : OGRFieldDefn *poYField = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1140 32 : apoGeomFieldProps[i]->iGeomYField);
1141 :
1142 32 : const char *pszXField = poXField->GetNameRef();
1143 32 : const char *pszYField = poYField->GetNameRef();
1144 :
1145 32 : OGRFieldType xType = poXField->GetType();
1146 32 : OGRFieldType yType = poYField->GetType();
1147 32 : if (!((xType == OFTReal || xType == OFTInteger ||
1148 : xType == OFTInteger64) &&
1149 0 : (yType == OFTReal || yType == OFTInteger ||
1150 : yType == OFTInteger64)))
1151 : {
1152 2 : CPLError(CE_Warning, CPLE_AppDefined,
1153 : "The '%s' and/or '%s' fields of the source layer "
1154 : "are not declared as numeric fields, "
1155 : "so the spatial filter cannot be turned into an "
1156 : "attribute filter on them",
1157 : pszXField, pszYField);
1158 2 : apoGeomFieldProps[i]->bUseSpatialSubquery = false;
1159 : }
1160 :
1161 32 : if (apoGeomFieldProps[i]->bUseSpatialSubquery)
1162 : {
1163 30 : OGREnvelope sEnvelope;
1164 60 : CPLString osFilter;
1165 :
1166 30 : if (apoGeomFieldProps[i]->poSrcRegion != nullptr)
1167 : {
1168 5 : if (m_poFilterGeom == nullptr)
1169 : {
1170 3 : apoGeomFieldProps[i]->poSrcRegion->getEnvelope(
1171 3 : &sEnvelope);
1172 : }
1173 : else
1174 : {
1175 : auto poIntersection = std::unique_ptr<OGRGeometry>(
1176 2 : apoGeomFieldProps[i]->poSrcRegion->Intersection(
1177 4 : m_poFilterGeom));
1178 2 : if (poIntersection && !poIntersection->IsEmpty())
1179 : {
1180 2 : poIntersection->getEnvelope(&sEnvelope);
1181 : }
1182 : else
1183 : {
1184 0 : sEnvelope.MinX = 0;
1185 0 : sEnvelope.MaxX = 0;
1186 0 : sEnvelope.MinY = 0;
1187 0 : sEnvelope.MaxY = 0;
1188 : }
1189 : }
1190 : }
1191 : else
1192 : {
1193 25 : CPLAssert(m_poFilterGeom);
1194 25 : m_poFilterGeom->getEnvelope(&sEnvelope);
1195 : }
1196 :
1197 30 : if (!std::isinf(sEnvelope.MinX))
1198 : osFilter +=
1199 28 : CPLSPrintf("\"%s\" > %.15g", pszXField, sEnvelope.MinX);
1200 2 : else if (sEnvelope.MinX > 0)
1201 0 : osFilter += "0 = 1";
1202 :
1203 30 : if (!std::isinf(sEnvelope.MaxX))
1204 : {
1205 28 : if (!osFilter.empty())
1206 28 : osFilter += " AND ";
1207 : osFilter +=
1208 28 : CPLSPrintf("\"%s\" < %.15g", pszXField, sEnvelope.MaxX);
1209 : }
1210 2 : else if (sEnvelope.MaxX < 0)
1211 : {
1212 0 : if (!osFilter.empty())
1213 0 : osFilter += " AND ";
1214 0 : osFilter += "0 = 1";
1215 : }
1216 :
1217 30 : if (!std::isinf(sEnvelope.MinY))
1218 : {
1219 28 : if (!osFilter.empty())
1220 28 : osFilter += " AND ";
1221 : osFilter +=
1222 28 : CPLSPrintf("\"%s\" > %.15g", pszYField, sEnvelope.MinY);
1223 : }
1224 2 : else if (sEnvelope.MinY > 0)
1225 : {
1226 0 : if (!osFilter.empty())
1227 0 : osFilter += " AND ";
1228 0 : osFilter += "0 = 1";
1229 : }
1230 :
1231 30 : if (!std::isinf(sEnvelope.MaxY))
1232 : {
1233 28 : if (!osFilter.empty())
1234 28 : osFilter += " AND ";
1235 : osFilter +=
1236 28 : CPLSPrintf("\"%s\" < %.15g", pszYField, sEnvelope.MaxY);
1237 : }
1238 2 : else if (sEnvelope.MaxY < 0)
1239 : {
1240 0 : if (!osFilter.empty())
1241 0 : osFilter += " AND ";
1242 0 : osFilter += "0 = 1";
1243 : }
1244 :
1245 30 : if (!osFilter.empty())
1246 : {
1247 28 : pszFilter = CPLStrdup(osFilter);
1248 : }
1249 : }
1250 :
1251 : // Just do it on one geometry field. To complicated otherwise!
1252 32 : break;
1253 : }
1254 : }
1255 :
1256 : // Install spatial + attr filter query on source layer.
1257 1444 : if (pszFilter == nullptr && pszAttrFilter == nullptr)
1258 : {
1259 1144 : bSuccess = poSrcLayer->SetAttributeFilter(nullptr) == OGRERR_NONE;
1260 : }
1261 300 : else if (pszFilter != nullptr && pszAttrFilter == nullptr)
1262 : {
1263 21 : bSuccess = poSrcLayer->SetAttributeFilter(pszFilter) == OGRERR_NONE;
1264 : }
1265 279 : else if (pszFilter == nullptr && pszAttrFilter != nullptr)
1266 : {
1267 272 : bSuccess = poSrcLayer->SetAttributeFilter(pszAttrFilter) == OGRERR_NONE;
1268 : }
1269 : else
1270 : {
1271 7 : CPLString osMerged = pszFilter;
1272 :
1273 7 : osMerged += " AND (";
1274 7 : osMerged += pszAttrFilter;
1275 7 : osMerged += ")";
1276 :
1277 7 : bSuccess = poSrcLayer->SetAttributeFilter(osMerged) == OGRERR_NONE;
1278 : }
1279 :
1280 1444 : CPLFree(pszFilter);
1281 :
1282 1444 : m_bEmptyResultSet = false;
1283 :
1284 : // Clear spatial filter (to be safe) for non direct geometries
1285 : // and reset reading.
1286 1444 : if (m_iGeomFieldFilter < static_cast<int>(apoGeomFieldProps.size()) &&
1287 2713 : apoGeomFieldProps[m_iGeomFieldFilter]->eGeometryStyle == VGS_Direct &&
1288 1269 : apoGeomFieldProps[m_iGeomFieldFilter]->iGeomField >= 0)
1289 : {
1290 1269 : OGRGeometry *poNewSpatialGeom = nullptr;
1291 : OGRGeometry *poSrcRegion =
1292 1269 : apoGeomFieldProps[m_iGeomFieldFilter]->poSrcRegion.get();
1293 1269 : std::unique_ptr<OGRGeometry> poIntersection;
1294 :
1295 1269 : if (poSrcRegion == nullptr)
1296 : {
1297 1210 : poNewSpatialGeom = m_poFilterGeom;
1298 : }
1299 59 : else if (m_poFilterGeom == nullptr)
1300 : {
1301 42 : poNewSpatialGeom = poSrcRegion;
1302 : }
1303 : else
1304 : {
1305 17 : bool bDoIntersection = true;
1306 17 : if (m_bFilterIsEnvelope)
1307 : {
1308 13 : OGREnvelope sEnvelope;
1309 13 : m_poFilterGeom->getEnvelope(&sEnvelope);
1310 15 : if (std::isinf(sEnvelope.MinX) && std::isinf(sEnvelope.MinY) &&
1311 2 : std::isinf(sEnvelope.MaxX) && std::isinf(sEnvelope.MaxY) &&
1312 1 : sEnvelope.MinX < 0 && sEnvelope.MinY < 0 &&
1313 14 : sEnvelope.MaxX > 0 && sEnvelope.MaxY > 0)
1314 : {
1315 1 : poNewSpatialGeom = poSrcRegion;
1316 1 : bDoIntersection = false;
1317 : }
1318 : }
1319 17 : if (bDoIntersection)
1320 : {
1321 16 : poIntersection.reset(m_poFilterGeom->Intersection(poSrcRegion));
1322 16 : poNewSpatialGeom = poIntersection.get();
1323 16 : if (!poIntersection)
1324 0 : m_bEmptyResultSet = true;
1325 : }
1326 : }
1327 1269 : poSrcLayer->SetSpatialFilter(
1328 1269 : apoGeomFieldProps[m_iGeomFieldFilter]->iGeomField,
1329 : poNewSpatialGeom);
1330 : }
1331 : else
1332 : {
1333 175 : poSrcLayer->SetSpatialFilter(nullptr);
1334 : }
1335 1444 : poSrcLayer->ResetReading();
1336 1444 : bNeedReset = false;
1337 :
1338 1444 : return bSuccess;
1339 : }
1340 :
1341 : /************************************************************************/
1342 : /* GetNextFeature() */
1343 : /************************************************************************/
1344 :
1345 25585 : OGRFeature *OGRVRTLayer::GetNextFeature()
1346 :
1347 : {
1348 25585 : if (m_bEmptyResultSet)
1349 0 : return nullptr;
1350 25585 : if (!bHasFullInitialized)
1351 40 : FullInitialize();
1352 25585 : if (!poSrcLayer || poDS->GetRecursionDetected())
1353 7 : return nullptr;
1354 25578 : if (bError)
1355 13 : return nullptr;
1356 :
1357 25565 : if (bNeedReset)
1358 : {
1359 1331 : if (!ResetSourceReading())
1360 2 : return nullptr;
1361 : }
1362 :
1363 : for (; true;)
1364 : {
1365 : auto poSrcFeature =
1366 25571 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
1367 25571 : if (poSrcFeature == nullptr)
1368 1077 : return nullptr;
1369 :
1370 0 : std::unique_ptr<OGRFeature> poFeature;
1371 24494 : if (poFeatureDefn.get() == GetSrcLayerDefn())
1372 : {
1373 3593 : poFeature = std::move(poSrcFeature);
1374 3593 : ClipAndAssignSRS(poFeature.get());
1375 : }
1376 : else
1377 : {
1378 20901 : poFeature = TranslateFeature(poSrcFeature, TRUE);
1379 : }
1380 :
1381 24494 : if (poFeature == nullptr)
1382 4 : return nullptr;
1383 :
1384 24490 : if (((m_iGeomFieldFilter < static_cast<int>(apoGeomFieldProps.size()) &&
1385 24413 : apoGeomFieldProps[m_iGeomFieldFilter]->eGeometryStyle ==
1386 20556 : VGS_Direct) ||
1387 20556 : m_poFilterGeom == nullptr ||
1388 49393 : FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
1389 24486 : (m_poAttrQuery == nullptr ||
1390 6 : m_poAttrQuery->Evaluate(poFeature.get())))
1391 : {
1392 24482 : return poFeature.release();
1393 : }
1394 8 : }
1395 : }
1396 :
1397 : /************************************************************************/
1398 : /* ClipAndAssignSRS() */
1399 : /************************************************************************/
1400 :
1401 24562 : void OGRVRTLayer::ClipAndAssignSRS(OGRFeature *poFeature)
1402 : {
1403 50173 : for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1404 : {
1405 : // Clip the geometry to the SrcRegion if asked.
1406 25611 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
1407 25611 : if (apoGeomFieldProps[i]->poSrcRegion != nullptr &&
1408 25611 : apoGeomFieldProps[i]->bSrcClip && poGeom != nullptr)
1409 : {
1410 : poGeom =
1411 39 : poGeom->Intersection(apoGeomFieldProps[i]->poSrcRegion.get());
1412 39 : if (poGeom != nullptr)
1413 39 : poGeom->assignSpatialReference(
1414 39 : GetLayerDefn()->GetGeomFieldDefn(i)->GetSpatialRef());
1415 :
1416 39 : poFeature->SetGeomFieldDirectly(i, poGeom);
1417 : }
1418 25572 : else if (poGeom != nullptr)
1419 24778 : poGeom->assignSpatialReference(
1420 24778 : GetLayerDefn()->GetGeomFieldDefn(i)->GetSpatialRef());
1421 : }
1422 24562 : }
1423 :
1424 : /************************************************************************/
1425 : /* TranslateFeature() */
1426 : /* */
1427 : /* Translate a source feature into a feature for this layer. */
1428 : /************************************************************************/
1429 :
1430 : std::unique_ptr<OGRFeature>
1431 20930 : OGRVRTLayer::TranslateFeature(std::unique_ptr<OGRFeature> &poSrcFeat,
1432 : int bUseSrcRegion)
1433 :
1434 : {
1435 20930 : retry:
1436 20930 : auto poDstFeat = std::make_unique<OGRFeature>(poFeatureDefn.get());
1437 :
1438 20930 : m_nFeaturesRead++;
1439 :
1440 : // Handle FID.
1441 20930 : if (iFIDField == -1)
1442 20902 : poDstFeat->SetFID(poSrcFeat->GetFID());
1443 : else
1444 28 : poDstFeat->SetFID(poSrcFeat->GetFieldAsInteger64(iFIDField));
1445 :
1446 : // Handle style string.
1447 20930 : if (iStyleField != -1)
1448 : {
1449 9 : if (poSrcFeat->IsFieldSetAndNotNull(iStyleField))
1450 9 : poDstFeat->SetStyleString(poSrcFeat->GetFieldAsString(iStyleField));
1451 : }
1452 : else
1453 : {
1454 20921 : if (poSrcFeat->GetStyleString() != nullptr)
1455 0 : poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
1456 : }
1457 :
1458 41910 : for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1459 : {
1460 : OGRVRTGeometryStyle eGeometryStyle =
1461 20994 : apoGeomFieldProps[i]->eGeometryStyle;
1462 20994 : int iGeomField = apoGeomFieldProps[i]->iGeomField;
1463 :
1464 : // Handle the geometry. Eventually there will be several more
1465 : // supported options.
1466 41988 : if (eGeometryStyle == VGS_None ||
1467 20994 : GetLayerDefn()->GetGeomFieldDefn(i)->IsIgnored())
1468 : {
1469 : // Do nothing.
1470 : }
1471 20966 : else if (eGeometryStyle == VGS_WKT && iGeomField != -1)
1472 : {
1473 63 : const char *pszWKT = poSrcFeat->GetFieldAsString(iGeomField);
1474 :
1475 63 : if (pszWKT != nullptr)
1476 : {
1477 63 : auto [poGeom, _] = OGRGeometryFactory::createFromWkt(pszWKT);
1478 63 : if (poGeom == nullptr)
1479 0 : CPLDebug("OGR_VRT", "Did not get geometry from %s", pszWKT);
1480 :
1481 63 : poDstFeat->SetGeomField(i, std::move(poGeom));
1482 63 : }
1483 : }
1484 20903 : else if (eGeometryStyle == VGS_WKB && iGeomField != -1)
1485 : {
1486 1 : int nBytes = 0;
1487 1 : GByte *pabyWKB = nullptr;
1488 1 : bool bNeedFree = false;
1489 :
1490 1 : if (poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary)
1491 : {
1492 0 : pabyWKB = poSrcFeat->GetFieldAsBinary(iGeomField, &nBytes);
1493 : }
1494 : else
1495 : {
1496 1 : const char *pszWKT = poSrcFeat->GetFieldAsString(iGeomField);
1497 :
1498 1 : pabyWKB = CPLHexToBinary(pszWKT, &nBytes);
1499 1 : bNeedFree = true;
1500 : }
1501 :
1502 1 : if (pabyWKB != nullptr)
1503 : {
1504 1 : OGRGeometry *poGeom = nullptr;
1505 :
1506 1 : if (OGRGeometryFactory::createFromWkb(pabyWKB, nullptr, &poGeom,
1507 1 : nBytes) == OGRERR_NONE)
1508 1 : poDstFeat->SetGeomFieldDirectly(i, poGeom);
1509 : }
1510 :
1511 1 : if (bNeedFree)
1512 1 : CPLFree(pabyWKB);
1513 : }
1514 20902 : else if (eGeometryStyle == VGS_Shape && iGeomField != -1)
1515 : {
1516 3 : int nBytes = 0;
1517 3 : GByte *pabyWKB = nullptr;
1518 3 : bool bNeedFree = false;
1519 :
1520 3 : if (poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary)
1521 : {
1522 0 : pabyWKB = poSrcFeat->GetFieldAsBinary(iGeomField, &nBytes);
1523 : }
1524 : else
1525 : {
1526 3 : const char *pszWKT = poSrcFeat->GetFieldAsString(iGeomField);
1527 :
1528 3 : pabyWKB = CPLHexToBinary(pszWKT, &nBytes);
1529 3 : bNeedFree = true;
1530 : }
1531 :
1532 3 : if (pabyWKB != nullptr)
1533 : {
1534 3 : OGRGeometry *poGeom = nullptr;
1535 :
1536 3 : if (OGRCreateFromShapeBin(pabyWKB, &poGeom, nBytes) ==
1537 : OGRERR_NONE)
1538 3 : poDstFeat->SetGeomFieldDirectly(i, poGeom);
1539 : }
1540 :
1541 3 : if (bNeedFree)
1542 3 : CPLFree(pabyWKB);
1543 : }
1544 20899 : else if (eGeometryStyle == VGS_Direct && iGeomField != -1)
1545 : {
1546 424 : poDstFeat->SetGeomField(i, poSrcFeat->GetGeomFieldRef(iGeomField));
1547 : }
1548 20475 : else if (eGeometryStyle == VGS_PointFromColumns)
1549 : {
1550 20475 : OGRPoint *poPoint = nullptr;
1551 20475 : if (apoGeomFieldProps[i]->iGeomZField != -1)
1552 : {
1553 61233 : poPoint = new OGRPoint(poSrcFeat->GetFieldAsDouble(
1554 20411 : apoGeomFieldProps[i]->iGeomXField),
1555 40822 : poSrcFeat->GetFieldAsDouble(
1556 20411 : apoGeomFieldProps[i]->iGeomYField),
1557 40822 : poSrcFeat->GetFieldAsDouble(
1558 40822 : apoGeomFieldProps[i]->iGeomZField));
1559 : }
1560 : else
1561 : {
1562 192 : poPoint = new OGRPoint(poSrcFeat->GetFieldAsDouble(
1563 64 : apoGeomFieldProps[i]->iGeomXField),
1564 128 : poSrcFeat->GetFieldAsDouble(
1565 128 : apoGeomFieldProps[i]->iGeomYField));
1566 : }
1567 20475 : if (apoGeomFieldProps[i]->iGeomMField >= 0)
1568 : {
1569 2 : poPoint->setM(poSrcFeat->GetFieldAsDouble(
1570 1 : apoGeomFieldProps[i]->iGeomMField));
1571 : }
1572 20475 : poDstFeat->SetGeomFieldDirectly(i, poPoint);
1573 : }
1574 : else
1575 : {
1576 : // Add other options here.
1577 : }
1578 :
1579 : // In the non-direct case, we need to check that the geometry
1580 : // intersects the source region before an optional clipping.
1581 41964 : if (bUseSrcRegion &&
1582 41529 : apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct &&
1583 20535 : apoGeomFieldProps[i]->poSrcRegion != nullptr)
1584 : {
1585 24 : OGRGeometry *poGeom = poDstFeat->GetGeomFieldRef(i);
1586 48 : if (poGeom != nullptr &&
1587 24 : !poGeom->Intersects(apoGeomFieldProps[i]->poSrcRegion.get()))
1588 : {
1589 14 : poDstFeat.reset();
1590 :
1591 : // Fetch next source feature and retry translating it.
1592 14 : poSrcFeat.reset(poSrcLayer->GetNextFeature());
1593 14 : if (poSrcFeat == nullptr)
1594 4 : return nullptr;
1595 :
1596 10 : goto retry;
1597 : }
1598 : }
1599 : }
1600 :
1601 20916 : ClipAndAssignSRS(poDstFeat.get());
1602 :
1603 : // Copy fields.
1604 83957 : for (int iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount();
1605 : iVRTField++)
1606 : {
1607 63041 : if (anSrcField[iVRTField] == -1)
1608 8 : continue;
1609 :
1610 63033 : OGRFieldDefn *poDstDefn = poFeatureDefn->GetFieldDefn(iVRTField);
1611 : OGRFieldDefn *poSrcDefn =
1612 63033 : poSrcLayer->GetLayerDefn()->GetFieldDefn(anSrcField[iVRTField]);
1613 :
1614 126030 : if (!poSrcFeat->IsFieldSetAndNotNull(anSrcField[iVRTField]) ||
1615 62997 : poDstDefn->IsIgnored())
1616 38 : continue;
1617 :
1618 125990 : if (abDirectCopy[iVRTField] &&
1619 62995 : poDstDefn->GetType() == poSrcDefn->GetType())
1620 : {
1621 125822 : poDstFeat->SetField(
1622 62911 : iVRTField, poSrcFeat->GetRawFieldRef(anSrcField[iVRTField]));
1623 : }
1624 : else
1625 : {
1626 : // Eventually we need to offer some more sophisticated translation
1627 : // options here for more esoteric types.
1628 84 : if (poDstDefn->GetType() == OFTReal)
1629 32 : poDstFeat->SetField(iVRTField, poSrcFeat->GetFieldAsDouble(
1630 16 : anSrcField[iVRTField]));
1631 : else
1632 136 : poDstFeat->SetField(iVRTField, poSrcFeat->GetFieldAsString(
1633 68 : anSrcField[iVRTField]));
1634 : }
1635 : }
1636 :
1637 20916 : return poDstFeat;
1638 : }
1639 :
1640 : /************************************************************************/
1641 : /* GetFeature() */
1642 : /************************************************************************/
1643 :
1644 97 : OGRFeature *OGRVRTLayer::GetFeature(GIntBig nFeatureId)
1645 :
1646 : {
1647 97 : if (!bHasFullInitialized)
1648 3 : FullInitialize();
1649 97 : if (!poSrcLayer || poDS->GetRecursionDetected())
1650 1 : return nullptr;
1651 :
1652 96 : bNeedReset = true;
1653 :
1654 : // If the FID is directly mapped, we can do a simple
1655 : // GetFeature() to get our target feature. Otherwise we need
1656 : // to setup an appropriate query to get it.
1657 96 : std::unique_ptr<OGRFeature> poSrcFeature;
1658 96 : std::unique_ptr<OGRFeature> poFeature;
1659 :
1660 96 : if (iFIDField == -1)
1661 : {
1662 94 : poSrcFeature.reset(poSrcLayer->GetFeature(nFeatureId));
1663 : }
1664 : else
1665 : {
1666 : const char *pszFID =
1667 2 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iFIDField)->GetNameRef();
1668 2 : char *pszFIDQuery = static_cast<char *>(CPLMalloc(strlen(pszFID) + 64));
1669 :
1670 2 : poSrcLayer->ResetReading();
1671 2 : snprintf(pszFIDQuery, strlen(pszFID) + 64, "%s = " CPL_FRMT_GIB, pszFID,
1672 : nFeatureId);
1673 2 : poSrcLayer->SetSpatialFilter(nullptr);
1674 2 : poSrcLayer->SetAttributeFilter(pszFIDQuery);
1675 2 : CPLFree(pszFIDQuery);
1676 :
1677 2 : poSrcFeature.reset(poSrcLayer->GetNextFeature());
1678 : }
1679 :
1680 96 : if (poSrcFeature == nullptr)
1681 24 : return nullptr;
1682 :
1683 : // Translate feature and return it.
1684 72 : if (poFeatureDefn.get() == GetSrcLayerDefn())
1685 : {
1686 53 : poFeature = std::move(poSrcFeature);
1687 53 : ClipAndAssignSRS(poFeature.get());
1688 : }
1689 : else
1690 : {
1691 19 : poFeature = TranslateFeature(poSrcFeature, FALSE);
1692 : }
1693 :
1694 72 : return poFeature.release();
1695 : }
1696 :
1697 : /************************************************************************/
1698 : /* SetNextByIndex() */
1699 : /************************************************************************/
1700 :
1701 24 : OGRErr OGRVRTLayer::SetNextByIndex(GIntBig nIndex)
1702 : {
1703 24 : if (!bHasFullInitialized)
1704 2 : FullInitialize();
1705 24 : if (!poSrcLayer || poDS->GetRecursionDetected())
1706 1 : return OGRERR_FAILURE;
1707 :
1708 23 : if (bNeedReset)
1709 : {
1710 1 : if (!ResetSourceReading())
1711 0 : return OGRERR_FAILURE;
1712 : }
1713 :
1714 23 : if (TestCapability(OLCFastSetNextByIndex))
1715 13 : return poSrcLayer->SetNextByIndex(nIndex);
1716 :
1717 10 : return OGRLayer::SetNextByIndex(nIndex);
1718 : }
1719 :
1720 : /************************************************************************/
1721 : /* TranslateVRTFeatureToSrcFeature() */
1722 : /* */
1723 : /* Translate a VRT feature into a feature for the source layer */
1724 : /************************************************************************/
1725 :
1726 : std::unique_ptr<OGRFeature>
1727 5 : OGRVRTLayer::TranslateVRTFeatureToSrcFeature(const OGRFeature *poVRTFeature)
1728 : {
1729 5 : auto poSrcFeat = std::make_unique<OGRFeature>(poSrcLayer->GetLayerDefn());
1730 :
1731 5 : poSrcFeat->SetFID(poVRTFeature->GetFID());
1732 :
1733 : // Handle style string.
1734 5 : if (iStyleField != -1)
1735 : {
1736 1 : if (poVRTFeature->GetStyleString() != nullptr)
1737 0 : poSrcFeat->SetField(iStyleField, poVRTFeature->GetStyleString());
1738 : }
1739 : else
1740 : {
1741 4 : if (poVRTFeature->GetStyleString() != nullptr)
1742 0 : poSrcFeat->SetStyleString(poVRTFeature->GetStyleString());
1743 : }
1744 :
1745 : // Handle the geometry. Eventually there will be several more
1746 : // supported options.
1747 10 : for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1748 : {
1749 : OGRVRTGeometryStyle eGeometryStyle =
1750 5 : apoGeomFieldProps[i]->eGeometryStyle;
1751 5 : int iGeomField = apoGeomFieldProps[i]->iGeomField;
1752 :
1753 5 : if (eGeometryStyle == VGS_None)
1754 : {
1755 : // Do nothing.
1756 : }
1757 5 : else if (eGeometryStyle == VGS_WKT && iGeomField >= 0)
1758 : {
1759 1 : const OGRGeometry *poGeom = poVRTFeature->GetGeomFieldRef(i);
1760 1 : if (poGeom != nullptr)
1761 : {
1762 1 : char *pszWKT = nullptr;
1763 1 : if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
1764 : {
1765 1 : poSrcFeat->SetField(iGeomField, pszWKT);
1766 : }
1767 1 : CPLFree(pszWKT);
1768 1 : }
1769 : }
1770 4 : else if (eGeometryStyle == VGS_WKB && iGeomField >= 0)
1771 : {
1772 1 : const OGRGeometry *poGeom = poVRTFeature->GetGeomFieldRef(i);
1773 1 : if (poGeom != nullptr)
1774 : {
1775 1 : const size_t nSize = poGeom->WkbSize();
1776 1 : if (nSize >
1777 1 : static_cast<size_t>(std::numeric_limits<int>::max()))
1778 : {
1779 : }
1780 : else
1781 : {
1782 : GByte *pabyData =
1783 1 : static_cast<GByte *>(VSI_MALLOC_VERBOSE(nSize));
1784 2 : if (pabyData &&
1785 1 : poGeom->exportToWkb(wkbNDR, pabyData) == OGRERR_NONE)
1786 : {
1787 1 : if (poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() ==
1788 : OFTBinary)
1789 : {
1790 0 : poSrcFeat->SetField(
1791 : iGeomField, static_cast<int>(nSize), pabyData);
1792 : }
1793 : else
1794 : {
1795 1 : char *pszHexWKB = CPLBinaryToHex(
1796 : static_cast<int>(nSize), pabyData);
1797 1 : poSrcFeat->SetField(iGeomField, pszHexWKB);
1798 1 : CPLFree(pszHexWKB);
1799 : }
1800 : }
1801 1 : CPLFree(pabyData);
1802 : }
1803 1 : }
1804 : }
1805 3 : else if (eGeometryStyle == VGS_Shape)
1806 : {
1807 0 : CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
1808 : }
1809 3 : else if (eGeometryStyle == VGS_Direct && iGeomField >= 0)
1810 : {
1811 2 : poSrcFeat->SetGeomField(iGeomField,
1812 : poVRTFeature->GetGeomFieldRef(i));
1813 : }
1814 1 : else if (eGeometryStyle == VGS_PointFromColumns)
1815 : {
1816 1 : const OGRGeometry *poGeom = poVRTFeature->GetGeomFieldRef(i);
1817 1 : if (poGeom != nullptr)
1818 : {
1819 1 : if (wkbFlatten(poGeom->getGeometryType()) != wkbPoint)
1820 : {
1821 0 : CPLError(CE_Warning, CPLE_NotSupported,
1822 : "Cannot set a non ponctual geometry for "
1823 : "PointFromColumns geometry");
1824 : }
1825 : else
1826 : {
1827 1 : auto poPoint = poGeom->toPoint();
1828 1 : poSrcFeat->SetField(apoGeomFieldProps[i]->iGeomXField,
1829 : poPoint->getX());
1830 1 : poSrcFeat->SetField(apoGeomFieldProps[i]->iGeomYField,
1831 : poPoint->getY());
1832 1 : if (apoGeomFieldProps[i]->iGeomZField != -1)
1833 : {
1834 0 : poSrcFeat->SetField(apoGeomFieldProps[i]->iGeomZField,
1835 : poPoint->getZ());
1836 : }
1837 1 : if (apoGeomFieldProps[i]->iGeomMField != -1)
1838 : {
1839 0 : poSrcFeat->SetField(apoGeomFieldProps[i]->iGeomMField,
1840 : poPoint->getM());
1841 : }
1842 : }
1843 : }
1844 : }
1845 : else
1846 : {
1847 : // Add other options here.
1848 : }
1849 :
1850 5 : OGRGeometry *poGeom = poSrcFeat->GetGeomFieldRef(i);
1851 5 : if (poGeom != nullptr)
1852 2 : poGeom->assignSpatialReference(
1853 2 : GetLayerDefn()->GetGeomFieldDefn(i)->GetSpatialRef());
1854 : }
1855 :
1856 : // Copy fields.
1857 16 : for (int iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount();
1858 : iVRTField++)
1859 : {
1860 11 : bool bSkip = false;
1861 20 : for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1862 : {
1863 : // Do not set source geometry columns. Have been set just above.
1864 11 : if ((apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct &&
1865 9 : anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomField) ||
1866 9 : anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomXField ||
1867 9 : anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomYField ||
1868 31 : anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomZField ||
1869 9 : anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomMField)
1870 : {
1871 2 : bSkip = true;
1872 2 : break;
1873 : }
1874 : }
1875 11 : if (bSkip)
1876 2 : continue;
1877 :
1878 9 : OGRFieldDefn *poVRTDefn = poFeatureDefn->GetFieldDefn(iVRTField);
1879 : OGRFieldDefn *poSrcDefn =
1880 9 : poSrcLayer->GetLayerDefn()->GetFieldDefn(anSrcField[iVRTField]);
1881 :
1882 18 : if (abDirectCopy[iVRTField] &&
1883 9 : poVRTDefn->GetType() == poSrcDefn->GetType())
1884 : {
1885 9 : poSrcFeat->SetField(anSrcField[iVRTField],
1886 : poVRTFeature->GetRawFieldRef(iVRTField));
1887 : }
1888 : else
1889 : {
1890 : // Eventually we need to offer some more sophisticated translation
1891 : // options here for more esoteric types.
1892 0 : poSrcFeat->SetField(anSrcField[iVRTField],
1893 : poVRTFeature->GetFieldAsString(iVRTField));
1894 : }
1895 : }
1896 :
1897 5 : return poSrcFeat;
1898 : }
1899 :
1900 : /************************************************************************/
1901 : /* ICreateFeature() */
1902 : /************************************************************************/
1903 :
1904 11 : OGRErr OGRVRTLayer::ICreateFeature(OGRFeature *poVRTFeature)
1905 : {
1906 11 : if (!bHasFullInitialized)
1907 0 : FullInitialize();
1908 11 : if (!poSrcLayer || poDS->GetRecursionDetected())
1909 1 : return OGRERR_FAILURE;
1910 :
1911 10 : if (!bUpdate)
1912 : {
1913 2 : CPLError(CE_Failure, CPLE_NotSupported, UNSUPPORTED_OP_READ_ONLY,
1914 : "CreateFeature");
1915 2 : return OGRERR_FAILURE;
1916 : }
1917 :
1918 8 : if (iFIDField != -1)
1919 : {
1920 0 : CPLError(CE_Failure, CPLE_AppDefined,
1921 : "The CreateFeature() operation is not supported "
1922 : "if the FID option is specified.");
1923 0 : return OGRERR_FAILURE;
1924 : }
1925 :
1926 8 : if (GetSrcLayerDefn() == poFeatureDefn.get())
1927 5 : return poSrcLayer->CreateFeature(poVRTFeature);
1928 :
1929 3 : auto poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1930 3 : poSrcFeature->SetFID(OGRNullFID);
1931 3 : OGRErr eErr = poSrcLayer->CreateFeature(poSrcFeature.get());
1932 3 : if (eErr == OGRERR_NONE)
1933 : {
1934 3 : poVRTFeature->SetFID(poSrcFeature->GetFID());
1935 : }
1936 3 : return eErr;
1937 : }
1938 :
1939 : /************************************************************************/
1940 : /* ISetFeature() */
1941 : /************************************************************************/
1942 :
1943 16 : OGRErr OGRVRTLayer::ISetFeature(OGRFeature *poVRTFeature)
1944 : {
1945 16 : if (!bHasFullInitialized)
1946 0 : FullInitialize();
1947 16 : if (!poSrcLayer || poDS->GetRecursionDetected())
1948 1 : return OGRERR_FAILURE;
1949 :
1950 15 : if (!bUpdate)
1951 : {
1952 10 : CPLError(CE_Failure, CPLE_NotSupported, UNSUPPORTED_OP_READ_ONLY,
1953 : "SetFeature");
1954 10 : return OGRERR_FAILURE;
1955 : }
1956 :
1957 5 : if (iFIDField != -1)
1958 : {
1959 0 : CPLError(CE_Failure, CPLE_AppDefined,
1960 : "The SetFeature() operation is not supported "
1961 : "if the FID option is specified.");
1962 0 : return OGRERR_FAILURE;
1963 : }
1964 :
1965 5 : if (GetSrcLayerDefn() == poFeatureDefn.get())
1966 3 : return poSrcLayer->SetFeature(poVRTFeature);
1967 :
1968 4 : auto poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1969 2 : return poSrcLayer->SetFeature(poSrcFeature.get());
1970 : }
1971 :
1972 : /************************************************************************/
1973 : /* DeleteFeature() */
1974 : /************************************************************************/
1975 :
1976 20 : OGRErr OGRVRTLayer::DeleteFeature(GIntBig nFID)
1977 :
1978 : {
1979 20 : if (!bHasFullInitialized)
1980 2 : FullInitialize();
1981 20 : if (!poSrcLayer || poDS->GetRecursionDetected())
1982 1 : return OGRERR_FAILURE;
1983 :
1984 19 : if (!bUpdate)
1985 : {
1986 18 : CPLError(CE_Failure, CPLE_NotSupported, UNSUPPORTED_OP_READ_ONLY,
1987 : "DeleteFeature");
1988 18 : return OGRERR_FAILURE;
1989 : }
1990 :
1991 1 : if (iFIDField != -1)
1992 : {
1993 0 : CPLError(CE_Failure, CPLE_AppDefined,
1994 : "The DeleteFeature() operation is not supported "
1995 : "if the FID option is specified.");
1996 0 : return OGRERR_FAILURE;
1997 : }
1998 :
1999 1 : return poSrcLayer->DeleteFeature(nFID);
2000 : }
2001 :
2002 : /************************************************************************/
2003 : /* SetAttributeFilter() */
2004 : /************************************************************************/
2005 :
2006 1214 : OGRErr OGRVRTLayer::SetAttributeFilter(const char *pszNewQuery)
2007 :
2008 : {
2009 1214 : if (!bHasFullInitialized)
2010 87 : FullInitialize();
2011 1214 : if (!poSrcLayer || poDS->GetRecursionDetected())
2012 41 : return OGRERR_FAILURE;
2013 :
2014 1173 : if (bAttrFilterPassThrough)
2015 : {
2016 1165 : CPLFree(pszAttrFilter);
2017 1165 : if (pszNewQuery == nullptr || strlen(pszNewQuery) == 0)
2018 901 : pszAttrFilter = nullptr;
2019 : else
2020 264 : pszAttrFilter = CPLStrdup(pszNewQuery);
2021 :
2022 1165 : ResetReading();
2023 1165 : return OGRERR_NONE;
2024 : }
2025 : else
2026 : {
2027 : // Setup m_poAttrQuery.
2028 8 : return OGRLayer::SetAttributeFilter(pszNewQuery);
2029 : }
2030 : }
2031 :
2032 : /************************************************************************/
2033 : /* TestCapability() */
2034 : /************************************************************************/
2035 :
2036 1499 : int OGRVRTLayer::TestCapability(const char *pszCap) const
2037 :
2038 : {
2039 1499 : if (EQUAL(pszCap, OLCFastFeatureCount) && nFeatureCount >= 0 &&
2040 0 : m_poFilterGeom == nullptr && m_poAttrQuery == nullptr)
2041 0 : return TRUE;
2042 :
2043 1518 : if (EQUAL(pszCap, OLCFastGetExtent) && apoGeomFieldProps.size() == 1 &&
2044 19 : apoGeomFieldProps[0]->sStaticEnvelope.IsInit())
2045 3 : return TRUE;
2046 :
2047 1496 : if (!bHasFullInitialized)
2048 37 : const_cast<OGRVRTLayer *>(this)->FullInitialize();
2049 1496 : if (!poSrcLayer || poDS->GetRecursionDetected())
2050 9 : return FALSE;
2051 :
2052 1487 : if (EQUAL(pszCap, OLCFastFeatureCount) ||
2053 1081 : EQUAL(pszCap, OLCFastSetNextByIndex))
2054 : {
2055 429 : if (m_poAttrQuery == nullptr)
2056 : {
2057 429 : bool bForward = true;
2058 1270 : for (size_t i = 0; i < apoGeomFieldProps.size(); i++)
2059 : {
2060 902 : if (!(apoGeomFieldProps[i]->eGeometryStyle == VGS_Direct ||
2061 39 : (apoGeomFieldProps[i]->poSrcRegion == nullptr &&
2062 31 : m_poFilterGeom == nullptr)))
2063 : {
2064 22 : bForward = false;
2065 22 : break;
2066 : }
2067 : }
2068 429 : if (bForward)
2069 : {
2070 407 : return poSrcLayer->TestCapability(pszCap);
2071 : }
2072 : }
2073 22 : return FALSE;
2074 : }
2075 :
2076 1058 : else if (EQUAL(pszCap, OLCFastSpatialFilter))
2077 9 : return apoGeomFieldProps.size() == 1 &&
2078 8 : apoGeomFieldProps[0]->eGeometryStyle == VGS_Direct &&
2079 17 : m_poAttrQuery == nullptr && poSrcLayer->TestCapability(pszCap);
2080 :
2081 1049 : else if (EQUAL(pszCap, OLCFastGetExtent))
2082 42 : return apoGeomFieldProps.size() == 1 &&
2083 19 : apoGeomFieldProps[0]->eGeometryStyle == VGS_Direct &&
2084 38 : m_poAttrQuery == nullptr &&
2085 19 : (apoGeomFieldProps[0]->poSrcRegion == nullptr ||
2086 61 : apoGeomFieldProps[0]->bSrcClip) &&
2087 61 : poSrcLayer->TestCapability(pszCap);
2088 :
2089 1007 : else if (EQUAL(pszCap, OLCRandomRead))
2090 6 : return iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
2091 :
2092 1001 : else if (EQUAL(pszCap, OLCSequentialWrite) ||
2093 991 : EQUAL(pszCap, OLCRandomWrite) || EQUAL(pszCap, OLCDeleteFeature))
2094 28 : return bUpdate && iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
2095 :
2096 973 : else if (EQUAL(pszCap, OLCStringsAsUTF8))
2097 146 : return poSrcLayer->TestCapability(pszCap);
2098 :
2099 827 : else if (EQUAL(pszCap, OLCTransactions))
2100 1 : return bUpdate && poSrcLayer->TestCapability(pszCap);
2101 :
2102 826 : else if (EQUAL(pszCap, OLCIgnoreFields) ||
2103 186 : EQUAL(pszCap, OLCCurveGeometries) ||
2104 138 : EQUAL(pszCap, OLCZGeometries) ||
2105 114 : EQUAL(pszCap, OLCMeasuredGeometries))
2106 760 : return poSrcLayer->TestCapability(pszCap);
2107 :
2108 66 : return FALSE;
2109 : }
2110 :
2111 : /************************************************************************/
2112 : /* IGetExtent() */
2113 : /************************************************************************/
2114 :
2115 102 : OGRErr OGRVRTLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
2116 : bool bForce)
2117 : {
2118 102 : if (static_cast<size_t>(iGeomField) >= apoGeomFieldProps.size())
2119 0 : return OGRERR_FAILURE;
2120 :
2121 102 : if (apoGeomFieldProps[iGeomField]->sStaticEnvelope.IsInit())
2122 : {
2123 5 : *psExtent = apoGeomFieldProps[iGeomField]->sStaticEnvelope;
2124 5 : return OGRERR_NONE;
2125 : }
2126 :
2127 97 : if (!bHasFullInitialized)
2128 0 : FullInitialize();
2129 97 : if (!poSrcLayer || poDS->GetRecursionDetected())
2130 0 : return OGRERR_FAILURE;
2131 :
2132 97 : if (apoGeomFieldProps[iGeomField]->eGeometryStyle == VGS_Direct &&
2133 191 : m_poAttrQuery == nullptr &&
2134 93 : (apoGeomFieldProps[iGeomField]->poSrcRegion == nullptr ||
2135 1 : apoGeomFieldProps[iGeomField]->bSrcClip))
2136 : {
2137 92 : if (bNeedReset)
2138 32 : ResetSourceReading();
2139 :
2140 92 : OGRErr eErr = poSrcLayer->GetExtent(
2141 92 : apoGeomFieldProps[iGeomField]->iGeomField, psExtent, bForce);
2142 178 : if (eErr != OGRERR_NONE ||
2143 86 : apoGeomFieldProps[iGeomField]->poSrcRegion == nullptr)
2144 92 : return eErr;
2145 :
2146 0 : OGREnvelope sSrcRegionEnvelope;
2147 0 : apoGeomFieldProps[iGeomField]->poSrcRegion->getEnvelope(
2148 0 : &sSrcRegionEnvelope);
2149 :
2150 0 : psExtent->Intersect(sSrcRegionEnvelope);
2151 0 : return eErr;
2152 : }
2153 :
2154 5 : return OGRLayer::IGetExtent(iGeomField, psExtent, bForce);
2155 : }
2156 :
2157 : /************************************************************************/
2158 : /* GetFeatureCount() */
2159 : /************************************************************************/
2160 :
2161 404 : GIntBig OGRVRTLayer::GetFeatureCount(int bForce)
2162 :
2163 : {
2164 404 : if (m_bEmptyResultSet)
2165 0 : return 0;
2166 404 : if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
2167 2 : m_poAttrQuery == nullptr)
2168 : {
2169 2 : return nFeatureCount;
2170 : }
2171 :
2172 402 : if (!bHasFullInitialized)
2173 5 : FullInitialize();
2174 402 : if (!poSrcLayer || poDS->GetRecursionDetected())
2175 6 : return 0;
2176 :
2177 396 : if (TestCapability(OLCFastFeatureCount))
2178 : {
2179 86 : if (bNeedReset)
2180 80 : ResetSourceReading();
2181 :
2182 86 : return poSrcLayer->GetFeatureCount(bForce);
2183 : }
2184 :
2185 310 : return OGRLayer::GetFeatureCount(bForce);
2186 : }
2187 :
2188 : /************************************************************************/
2189 : /* ISetSpatialFilter() */
2190 : /************************************************************************/
2191 :
2192 1147 : OGRErr OGRVRTLayer::ISetSpatialFilter(int iGeomField,
2193 : const OGRGeometry *poGeomIn)
2194 : {
2195 1147 : if (!bHasFullInitialized)
2196 2 : FullInitialize();
2197 1147 : if (!poSrcLayer || poDS->GetRecursionDetected())
2198 41 : return OGRERR_FAILURE;
2199 :
2200 2159 : if (iGeomField >= 0 && iGeomField < GetLayerDefn()->GetGeomFieldCount() &&
2201 1053 : apoGeomFieldProps[iGeomField]->eGeometryStyle == VGS_Direct)
2202 1029 : bNeedReset = true;
2203 :
2204 1106 : m_iGeomFieldFilter = iGeomField;
2205 1106 : if (InstallFilter(poGeomIn))
2206 392 : ResetReading();
2207 1106 : return OGRERR_NONE;
2208 : }
2209 :
2210 : /************************************************************************/
2211 : /* SyncToDisk() */
2212 : /************************************************************************/
2213 :
2214 3 : OGRErr OGRVRTLayer::SyncToDisk()
2215 : {
2216 3 : if (!bHasFullInitialized)
2217 2 : FullInitialize();
2218 3 : if (!poSrcLayer || poDS->GetRecursionDetected())
2219 1 : return OGRERR_FAILURE;
2220 :
2221 2 : return poSrcLayer->SyncToDisk();
2222 : }
2223 :
2224 : /************************************************************************/
2225 : /* GetLayerDefn() */
2226 : /************************************************************************/
2227 :
2228 67723 : const OGRFeatureDefn *OGRVRTLayer::GetLayerDefn() const
2229 : {
2230 67723 : if (!bHasFullInitialized)
2231 318 : const_cast<OGRVRTLayer *>(this)->FullInitialize();
2232 :
2233 67723 : return poFeatureDefn.get();
2234 : }
2235 :
2236 : /************************************************************************/
2237 : /* GetGeomType() */
2238 : /************************************************************************/
2239 :
2240 75 : OGRwkbGeometryType OGRVRTLayer::GetGeomType() const
2241 : {
2242 90 : if (CPLGetXMLValue(psLTree, "GeometryType", nullptr) != nullptr ||
2243 15 : CPLGetXMLValue(psLTree, "GeometryField.GeometryType", nullptr) !=
2244 : nullptr)
2245 : {
2246 62 : if (apoGeomFieldProps.size() >= 1)
2247 60 : return apoGeomFieldProps[0]->eGeomType;
2248 2 : return wkbNone;
2249 : }
2250 :
2251 13 : return GetLayerDefn()->GetGeomType();
2252 : }
2253 :
2254 : /************************************************************************/
2255 : /* GetFIDColumn() */
2256 : /************************************************************************/
2257 :
2258 215 : const char *OGRVRTLayer::GetFIDColumn() const
2259 : {
2260 215 : if (!bHasFullInitialized)
2261 6 : const_cast<OGRVRTLayer *>(this)->FullInitialize();
2262 :
2263 215 : if (!poSrcLayer || poDS->GetRecursionDetected())
2264 35 : return "";
2265 :
2266 180 : return osFIDFieldName;
2267 : }
2268 :
2269 : /************************************************************************/
2270 : /* StartTransaction() */
2271 : /************************************************************************/
2272 :
2273 3 : OGRErr OGRVRTLayer::StartTransaction()
2274 : {
2275 3 : if (!bHasFullInitialized)
2276 1 : FullInitialize();
2277 3 : if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected())
2278 1 : return OGRERR_FAILURE;
2279 :
2280 2 : return poSrcLayer->StartTransaction();
2281 : }
2282 :
2283 : /************************************************************************/
2284 : /* CommitTransaction() */
2285 : /************************************************************************/
2286 :
2287 2 : OGRErr OGRVRTLayer::CommitTransaction()
2288 : {
2289 2 : if (!bHasFullInitialized)
2290 1 : FullInitialize();
2291 2 : if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected())
2292 1 : return OGRERR_FAILURE;
2293 :
2294 1 : return poSrcLayer->CommitTransaction();
2295 : }
2296 :
2297 : /************************************************************************/
2298 : /* RollbackTransaction() */
2299 : /************************************************************************/
2300 :
2301 2 : OGRErr OGRVRTLayer::RollbackTransaction()
2302 : {
2303 2 : if (!bHasFullInitialized)
2304 1 : FullInitialize();
2305 2 : if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected())
2306 1 : return OGRERR_FAILURE;
2307 :
2308 1 : return poSrcLayer->RollbackTransaction();
2309 : }
2310 :
2311 : /************************************************************************/
2312 : /* SetIgnoredFields() */
2313 : /************************************************************************/
2314 :
2315 1202 : OGRErr OGRVRTLayer::SetIgnoredFields(CSLConstList papszFields)
2316 : {
2317 1202 : if (!bHasFullInitialized)
2318 1 : FullInitialize();
2319 1202 : if (!poSrcLayer || poDS->GetRecursionDetected())
2320 98 : return OGRERR_FAILURE;
2321 :
2322 1104 : if (!poSrcLayer->TestCapability(OLCIgnoreFields))
2323 6 : return OGRERR_FAILURE;
2324 :
2325 1098 : OGRErr eErr = OGRLayer::SetIgnoredFields(papszFields);
2326 1098 : if (eErr != OGRERR_NONE)
2327 0 : return eErr;
2328 :
2329 2196 : CPLStringList aosFieldsSrc;
2330 :
2331 : // Translate explicitly ignored fields of VRT layers to their equivalent
2332 : // source fields.
2333 2302 : for (const char *pszFieldName : cpl::Iterate(papszFields))
2334 : {
2335 1204 : if (EQUAL(pszFieldName, "OGR_GEOMETRY") ||
2336 1183 : EQUAL(pszFieldName, "OGR_STYLE"))
2337 : {
2338 21 : aosFieldsSrc.AddString(pszFieldName);
2339 : }
2340 : else
2341 : {
2342 : int iVRTField =
2343 1183 : GetFieldIndexCaseSensitiveFirst(GetLayerDefn(), pszFieldName);
2344 1183 : if (iVRTField >= 0)
2345 : {
2346 799 : int iSrcField = anSrcField[iVRTField];
2347 799 : if (iSrcField >= 0)
2348 : {
2349 : // If we are asked to ignore x or y for a
2350 : // VGS_PointFromColumns geometry field, we must NOT pass
2351 : // that order to the underlying layer.
2352 799 : bool bOKToIgnore = true;
2353 3157 : for (int iGeomVRTField = 0;
2354 3157 : iGeomVRTField < GetLayerDefn()->GetGeomFieldCount();
2355 : iGeomVRTField++)
2356 : {
2357 2360 : if (iSrcField ==
2358 2360 : apoGeomFieldProps[iGeomVRTField]->iGeomXField ||
2359 : iSrcField ==
2360 2359 : apoGeomFieldProps[iGeomVRTField]->iGeomYField ||
2361 : iSrcField ==
2362 7077 : apoGeomFieldProps[iGeomVRTField]->iGeomZField ||
2363 : iSrcField ==
2364 2358 : apoGeomFieldProps[iGeomVRTField]->iGeomMField)
2365 : {
2366 2 : bOKToIgnore = false;
2367 2 : break;
2368 : }
2369 : }
2370 799 : if (bOKToIgnore)
2371 : {
2372 : const OGRFieldDefn *poSrcDefn =
2373 797 : GetSrcLayerDefn()->GetFieldDefn(iSrcField);
2374 797 : aosFieldsSrc.AddString(poSrcDefn->GetNameRef());
2375 : }
2376 : }
2377 : }
2378 : else
2379 : {
2380 384 : iVRTField = GetLayerDefn()->GetGeomFieldIndex(pszFieldName);
2381 768 : if (iVRTField >= 0 &&
2382 384 : apoGeomFieldProps[iVRTField]->eGeometryStyle == VGS_Direct)
2383 : {
2384 383 : int iSrcField = apoGeomFieldProps[iVRTField]->iGeomField;
2385 383 : if (iSrcField >= 0)
2386 : {
2387 : const OGRGeomFieldDefn *poSrcDefn =
2388 383 : GetSrcLayerDefn()->GetGeomFieldDefn(iSrcField);
2389 383 : aosFieldsSrc.AddString(poSrcDefn->GetNameRef());
2390 : }
2391 : }
2392 : }
2393 : }
2394 : }
2395 :
2396 : // Add source fields that are not referenced by VRT layer.
2397 2196 : std::vector<bool> abSrcFieldUsed(GetSrcLayerDefn()->GetFieldCount());
2398 5003 : for (int iVRTField = 0; iVRTField < GetLayerDefn()->GetFieldCount();
2399 : iVRTField++)
2400 : {
2401 3905 : const int iSrcField = anSrcField[iVRTField];
2402 3905 : if (iSrcField >= 0)
2403 3902 : abSrcFieldUsed[iSrcField] = true;
2404 : }
2405 3073 : for (int iVRTField = 0; iVRTField < GetLayerDefn()->GetGeomFieldCount();
2406 : iVRTField++)
2407 : {
2408 : OGRVRTGeometryStyle eGeometryStyle =
2409 1975 : apoGeomFieldProps[iVRTField]->eGeometryStyle;
2410 : // For a VGS_PointFromColumns geometry field, we must not ignore
2411 : // the fields that help building it.
2412 1975 : if (eGeometryStyle == VGS_PointFromColumns)
2413 : {
2414 75 : int iSrcField = apoGeomFieldProps[iVRTField]->iGeomXField;
2415 75 : if (iSrcField >= 0)
2416 75 : abSrcFieldUsed[iSrcField] = true;
2417 75 : iSrcField = apoGeomFieldProps[iVRTField]->iGeomYField;
2418 75 : if (iSrcField >= 0)
2419 75 : abSrcFieldUsed[iSrcField] = true;
2420 75 : iSrcField = apoGeomFieldProps[iVRTField]->iGeomZField;
2421 75 : if (iSrcField >= 0)
2422 54 : abSrcFieldUsed[iSrcField] = true;
2423 75 : iSrcField = apoGeomFieldProps[iVRTField]->iGeomMField;
2424 75 : if (iSrcField >= 0)
2425 1 : abSrcFieldUsed[iSrcField] = true;
2426 : }
2427 : // Similarly for other kinds of geometry fields.
2428 1900 : else if (eGeometryStyle == VGS_WKT || eGeometryStyle == VGS_WKB ||
2429 : eGeometryStyle == VGS_Shape)
2430 : {
2431 58 : int iSrcField = apoGeomFieldProps[iVRTField]->iGeomField;
2432 58 : if (iSrcField >= 0)
2433 58 : abSrcFieldUsed[iSrcField] = true;
2434 : }
2435 : }
2436 1098 : if (iStyleField >= 0)
2437 3 : abSrcFieldUsed[iStyleField] = true;
2438 1098 : if (iFIDField >= 0)
2439 28 : abSrcFieldUsed[iFIDField] = true;
2440 5096 : for (int iSrcField = 0; iSrcField < GetSrcLayerDefn()->GetFieldCount();
2441 : iSrcField++)
2442 : {
2443 3998 : if (!abSrcFieldUsed[iSrcField])
2444 : {
2445 : const OGRFieldDefn *poSrcDefn =
2446 39 : GetSrcLayerDefn()->GetFieldDefn(iSrcField);
2447 39 : aosFieldsSrc.AddString(poSrcDefn->GetNameRef());
2448 : }
2449 : }
2450 :
2451 : // Add source geometry fields that are not referenced by VRT layer.
2452 1098 : abSrcFieldUsed.clear();
2453 1098 : abSrcFieldUsed.resize(GetSrcLayerDefn()->GetGeomFieldCount());
2454 3073 : for (int iVRTField = 0; iVRTField < GetLayerDefn()->GetGeomFieldCount();
2455 : iVRTField++)
2456 : {
2457 1975 : if (apoGeomFieldProps[iVRTField]->eGeometryStyle == VGS_Direct)
2458 : {
2459 1842 : const int iSrcField = apoGeomFieldProps[iVRTField]->iGeomField;
2460 1842 : if (iSrcField >= 0)
2461 1842 : abSrcFieldUsed[iSrcField] = true;
2462 : }
2463 : }
2464 3098 : for (int iSrcField = 0; iSrcField < GetSrcLayerDefn()->GetGeomFieldCount();
2465 : iSrcField++)
2466 : {
2467 2000 : if (!abSrcFieldUsed[iSrcField])
2468 : {
2469 : const OGRGeomFieldDefn *poSrcDefn =
2470 158 : GetSrcLayerDefn()->GetGeomFieldDefn(iSrcField);
2471 158 : aosFieldsSrc.AddString(poSrcDefn->GetNameRef());
2472 : }
2473 : }
2474 :
2475 1098 : return poSrcLayer->SetIgnoredFields(aosFieldsSrc.List());
2476 : }
2477 :
2478 : /************************************************************************/
2479 : /* GetSrcDataset() */
2480 : /************************************************************************/
2481 :
2482 7 : GDALDataset *OGRVRTLayer::GetSrcDataset()
2483 : {
2484 7 : if (!bHasFullInitialized)
2485 0 : FullInitialize();
2486 7 : if (!poSrcLayer || poDS->GetRecursionDetected())
2487 0 : return nullptr;
2488 7 : return poSrcDS.get();
2489 : }
|