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