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