Coverage Report

Created: 2026-08-11 08:26

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