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