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