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