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