Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements OGRUnionLayer class
5
 * Author:   Even Rouault, even dot rouault at spatialys.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2012-2014, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef DOXYGEN_SKIP
14
15
#include "ogrunionlayer.h"
16
#include "ogrwarpedlayer.h"
17
#include "ogr_p.h"
18
19
#include <limits>
20
21
/************************************************************************/
22
/*                     OGRUnionLayerGeomFieldDefn()                     */
23
/************************************************************************/
24
25
OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(const char *pszNameIn,
26
                                                       OGRwkbGeometryType eType)
27
0
    : OGRGeomFieldDefn(pszNameIn, eType)
28
0
{
29
0
}
30
31
/************************************************************************/
32
/*                     OGRUnionLayerGeomFieldDefn()                     */
33
/************************************************************************/
34
35
OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
36
    const OGRGeomFieldDefn &oSrc)
37
0
    : OGRGeomFieldDefn(oSrc)
38
0
{
39
0
    SetSpatialRef(oSrc.GetSpatialRef());
40
0
}
41
42
/************************************************************************/
43
/*                     OGRUnionLayerGeomFieldDefn()                     */
44
/************************************************************************/
45
46
// cppcheck-suppress missingMemberCopy
47
OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
48
    const OGRUnionLayerGeomFieldDefn &oSrc)
49
0
    : OGRGeomFieldDefn(oSrc), bGeomTypeSet(oSrc.bGeomTypeSet),
50
0
      bSRSSet(oSrc.bSRSSet), sStaticEnvelope(oSrc.sStaticEnvelope)
51
0
{
52
0
    SetSpatialRef(oSrc.GetSpatialRef());
53
0
}
54
55
/************************************************************************/
56
/*                    ~OGRUnionLayerGeomFieldDefn()                     */
57
/************************************************************************/
58
59
0
OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn() = default;
60
61
/************************************************************************/
62
/*                           OGRUnionLayer()                            */
63
/************************************************************************/
64
65
// cppcheck-suppress uninitMemberVar
66
OGRUnionLayer::OGRUnionLayer(const char *pszName, int nSrcLayersIn,
67
                             OGRLayer **papoSrcLayersIn,
68
                             int bTakeLayerOwnership)
69
0
    : osName(pszName)
70
0
{
71
0
    CPLAssert(nSrcLayersIn > 0);
72
73
0
    SetDescription(pszName);
74
75
0
    for (int i = 0; i < nSrcLayersIn; ++i)
76
0
    {
77
0
        m_apoSrcLayers.emplace_back(papoSrcLayersIn[i],
78
0
                                    CPL_TO_BOOL(bTakeLayerOwnership));
79
0
    }
80
0
    CPLFree(papoSrcLayersIn);
81
0
}
82
83
/************************************************************************/
84
/*                           ~OGRUnionLayer()                           */
85
/************************************************************************/
86
87
OGRUnionLayer::~OGRUnionLayer()
88
0
{
89
0
    m_apoSrcLayers.clear();
90
91
0
    CPLFree(pszAttributeFilter);
92
0
    CPLFree(panMap);
93
94
0
    if (poFeatureDefn)
95
0
        poFeatureDefn->Release();
96
0
    if (poGlobalSRS != nullptr)
97
0
        const_cast<OGRSpatialReference *>(poGlobalSRS)->Release();
98
0
}
99
100
/************************************************************************/
101
/*                             SetFields()                              */
102
/************************************************************************/
103
104
void OGRUnionLayer::SetFields(FieldUnionStrategy eFieldStrategyIn,
105
                              int nFieldsIn, const OGRFieldDefn *paoFieldsIn,
106
                              int nGeomFieldsIn,
107
                              const OGRUnionLayerGeomFieldDefn *paoGeomFieldsIn)
108
0
{
109
0
    CPLAssert(apoFields.empty());
110
0
    CPLAssert(poFeatureDefn == nullptr);
111
112
0
    eFieldStrategy = eFieldStrategyIn;
113
0
    for (int i = 0; i < nFieldsIn; i++)
114
0
    {
115
0
        apoFields.push_back(std::make_unique<OGRFieldDefn>(paoFieldsIn[i]));
116
0
    }
117
0
    bUseGeomFields = nGeomFieldsIn >= 0;
118
0
    for (int i = 0; i < nGeomFieldsIn; i++)
119
0
    {
120
0
        apoGeomFields.push_back(
121
0
            std::make_unique<OGRUnionLayerGeomFieldDefn>(paoGeomFieldsIn[i]));
122
0
    }
123
0
}
124
125
/************************************************************************/
126
/*                             SetFields()                              */
127
/************************************************************************/
128
129
void OGRUnionLayer::SetFields(FieldUnionStrategy eFieldStrategyIn,
130
                              const OGRFeatureDefn *poFeatureDefnIn)
131
0
{
132
0
    CPLAssert(apoFields.empty());
133
0
    CPLAssert(poFeatureDefn == nullptr);
134
135
0
    eFieldStrategy = eFieldStrategyIn;
136
0
    for (const auto *poSrcFieldDefn : poFeatureDefnIn->GetFields())
137
0
    {
138
0
        apoFields.push_back(std::make_unique<OGRFieldDefn>(*poSrcFieldDefn));
139
0
    }
140
0
    for (const auto *poSrcGeomFieldDefn : poFeatureDefnIn->GetGeomFields())
141
0
    {
142
0
        apoGeomFields.push_back(
143
0
            std::make_unique<OGRUnionLayerGeomFieldDefn>(*poSrcGeomFieldDefn));
144
0
    }
145
0
}
146
147
/************************************************************************/
148
/*                      SetSourceLayerFieldName()                       */
149
/************************************************************************/
150
151
void OGRUnionLayer::SetSourceLayerFieldName(const char *pszSourceLayerFieldName)
152
0
{
153
0
    CPLAssert(poFeatureDefn == nullptr);
154
155
0
    CPLAssert(osSourceLayerFieldName.empty());
156
0
    if (pszSourceLayerFieldName != nullptr)
157
0
        osSourceLayerFieldName = pszSourceLayerFieldName;
158
0
}
159
160
/************************************************************************/
161
/*                         SetPreserveSrcFID()                          */
162
/************************************************************************/
163
164
void OGRUnionLayer::SetPreserveSrcFID(int bPreserveSrcFIDIn)
165
0
{
166
0
    CPLAssert(poFeatureDefn == nullptr);
167
168
0
    bPreserveSrcFID = bPreserveSrcFIDIn;
169
0
}
170
171
/************************************************************************/
172
/*                          SetFeatureCount()                           */
173
/************************************************************************/
174
175
void OGRUnionLayer::SetFeatureCount(int nFeatureCountIn)
176
0
{
177
0
    CPLAssert(poFeatureDefn == nullptr);
178
179
0
    nFeatureCount = nFeatureCountIn;
180
0
}
181
182
/************************************************************************/
183
/*                           MergeFieldDefn()                           */
184
/************************************************************************/
185
186
static void MergeFieldDefn(OGRFieldDefn *poFieldDefn,
187
                           const OGRFieldDefn *poSrcFieldDefn)
188
0
{
189
0
    if (poFieldDefn->GetType() != poSrcFieldDefn->GetType())
190
0
    {
191
0
        if (poSrcFieldDefn->GetType() == OFTReal &&
192
0
            (poFieldDefn->GetType() == OFTInteger ||
193
0
             poFieldDefn->GetType() == OFTInteger64))
194
0
            poFieldDefn->SetType(OFTReal);
195
0
        if (poFieldDefn->GetType() == OFTReal &&
196
0
            (poSrcFieldDefn->GetType() == OFTInteger ||
197
0
             poSrcFieldDefn->GetType() == OFTInteger64))
198
0
            poFieldDefn->SetType(OFTReal);
199
0
        else if (poSrcFieldDefn->GetType() == OFTInteger64 &&
200
0
                 poFieldDefn->GetType() == OFTInteger)
201
0
            poFieldDefn->SetType(OFTInteger64);
202
0
        else if (poFieldDefn->GetType() == OFTInteger64 &&
203
0
                 poSrcFieldDefn->GetType() == OFTInteger)
204
0
            poFieldDefn->SetType(OFTInteger64);
205
0
        else
206
0
            poFieldDefn->SetType(OFTString);
207
0
    }
208
209
0
    if (poFieldDefn->GetWidth() != poSrcFieldDefn->GetWidth() ||
210
0
        poFieldDefn->GetPrecision() != poSrcFieldDefn->GetPrecision())
211
0
    {
212
0
        poFieldDefn->SetWidth(0);
213
0
        poFieldDefn->SetPrecision(0);
214
0
    }
215
0
}
216
217
/************************************************************************/
218
/*                            GetLayerDefn()                            */
219
/************************************************************************/
220
221
const OGRFeatureDefn *OGRUnionLayer::GetLayerDefn() const
222
0
{
223
0
    if (poFeatureDefn != nullptr)
224
0
        return poFeatureDefn;
225
226
0
    poFeatureDefn = new OGRFeatureDefn(osName);
227
0
    poFeatureDefn->Reference();
228
0
    poFeatureDefn->SetGeomType(wkbNone);
229
230
0
    int iCompareFirstIndex = 0;
231
0
    if (!osSourceLayerFieldName.empty())
232
0
    {
233
0
        OGRFieldDefn oField(osSourceLayerFieldName, OFTString);
234
0
        poFeatureDefn->AddFieldDefn(&oField);
235
0
        iCompareFirstIndex = 1;
236
0
    }
237
238
0
    if (eFieldStrategy == FIELD_SPECIFIED)
239
0
    {
240
0
        for (const auto &poFieldDefn : apoFields)
241
0
            poFeatureDefn->AddFieldDefn(poFieldDefn.get());
242
0
        for (const auto &poGeomFieldDefnIn : apoGeomFields)
243
0
        {
244
0
            poFeatureDefn->AddGeomFieldDefn(
245
0
                std::make_unique<OGRUnionLayerGeomFieldDefn>(
246
0
                    *(poGeomFieldDefnIn.get())));
247
0
            OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
248
0
                cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
249
0
                    poFeatureDefn->GetGeomFieldDefn(
250
0
                        poFeatureDefn->GetGeomFieldCount() - 1));
251
252
0
            if (poGeomFieldDefn->bGeomTypeSet == FALSE ||
253
0
                poGeomFieldDefn->bSRSSet == FALSE)
254
0
            {
255
0
                for (auto &oLayer : m_apoSrcLayers)
256
0
                {
257
0
                    const OGRFeatureDefn *poSrcFeatureDefn =
258
0
                        oLayer->GetLayerDefn();
259
0
                    int nIndex = poSrcFeatureDefn->GetGeomFieldIndex(
260
0
                        poGeomFieldDefn->GetNameRef());
261
0
                    if (nIndex >= 0)
262
0
                    {
263
0
                        const OGRGeomFieldDefn *poSrcGeomFieldDefn =
264
0
                            poSrcFeatureDefn->GetGeomFieldDefn(nIndex);
265
0
                        if (poGeomFieldDefn->bGeomTypeSet == FALSE)
266
0
                        {
267
0
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
268
0
                            poGeomFieldDefn->SetType(
269
0
                                poSrcGeomFieldDefn->GetType());
270
0
                        }
271
0
                        if (poGeomFieldDefn->bSRSSet == FALSE)
272
0
                        {
273
0
                            poGeomFieldDefn->bSRSSet = TRUE;
274
0
                            poGeomFieldDefn->SetSpatialRef(
275
0
                                poSrcGeomFieldDefn->GetSpatialRef());
276
0
                            if (poFeatureDefn->GetGeomFieldCount() == 1 &&
277
0
                                poGlobalSRS == nullptr)
278
0
                            {
279
0
                                poGlobalSRS =
280
0
                                    poSrcGeomFieldDefn->GetSpatialRef();
281
0
                                if (poGlobalSRS != nullptr)
282
0
                                    const_cast<OGRSpatialReference *>(
283
0
                                        poGlobalSRS)
284
0
                                        ->Reference();
285
0
                            }
286
0
                        }
287
0
                        break;
288
0
                    }
289
0
                }
290
0
            }
291
0
        }
292
0
    }
293
0
    else if (eFieldStrategy == FIELD_FROM_FIRST_LAYER)
294
0
    {
295
0
        const OGRFeatureDefn *poSrcFeatureDefn =
296
0
            m_apoSrcLayers[0]->GetLayerDefn();
297
0
        for (const auto *poSrcFieldDefn : poSrcFeatureDefn->GetFields())
298
0
            poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
299
0
        if (bUseGeomFields)
300
0
        {
301
0
            for (const auto *poSrcGeomFieldDefn :
302
0
                 poSrcFeatureDefn->GetGeomFields())
303
0
            {
304
0
                poFeatureDefn->AddGeomFieldDefn(
305
0
                    std::make_unique<OGRUnionLayerGeomFieldDefn>(
306
0
                        *poSrcGeomFieldDefn));
307
0
            }
308
0
        }
309
0
    }
310
0
    else if (eFieldStrategy == FIELD_UNION_ALL_LAYERS)
311
0
    {
312
0
        if (apoGeomFields.size() == 1)
313
0
        {
314
0
            poFeatureDefn->AddGeomFieldDefn(
315
0
                std::make_unique<OGRUnionLayerGeomFieldDefn>(
316
0
                    *(apoGeomFields[0].get())));
317
0
        }
318
319
0
        int nDstFieldCount = 0;
320
0
        std::map<std::string, int> oMapDstFieldNameToIdx;
321
322
0
        for (auto &oLayer : m_apoSrcLayers)
323
0
        {
324
0
            const OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
325
326
            /* Add any field that is found in the source layers */
327
0
            const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
328
0
            for (int i = 0; i < nSrcFieldCount; i++)
329
0
            {
330
0
                const OGRFieldDefn *poSrcFieldDefn =
331
0
                    poSrcFeatureDefn->GetFieldDefn(i);
332
0
                const auto oIter =
333
0
                    oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
334
0
                const int nIndex =
335
0
                    oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
336
0
                if (nIndex < 0)
337
0
                {
338
0
                    oMapDstFieldNameToIdx[poSrcFieldDefn->GetNameRef()] =
339
0
                        nDstFieldCount;
340
0
                    nDstFieldCount++;
341
0
                    poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
342
0
                }
343
0
                else
344
0
                {
345
0
                    OGRFieldDefn *poFieldDefn =
346
0
                        poFeatureDefn->GetFieldDefn(nIndex);
347
0
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
348
0
                }
349
0
            }
350
351
0
            for (int i = 0;
352
0
                 bUseGeomFields && i < poSrcFeatureDefn->GetGeomFieldCount();
353
0
                 i++)
354
0
            {
355
0
                const OGRGeomFieldDefn *poSrcFieldDefn =
356
0
                    poSrcFeatureDefn->GetGeomFieldDefn(i);
357
0
                int nIndex = poFeatureDefn->GetGeomFieldIndex(
358
0
                    poSrcFieldDefn->GetNameRef());
359
0
                if (nIndex < 0)
360
0
                {
361
0
                    poFeatureDefn->AddGeomFieldDefn(
362
0
                        std::make_unique<OGRUnionLayerGeomFieldDefn>(
363
0
                            *poSrcFieldDefn));
364
0
                    if (poFeatureDefn->GetGeomFieldCount() == 1 &&
365
0
                        apoGeomFields.empty() && GetSpatialRef() != nullptr)
366
0
                    {
367
0
                        OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
368
0
                            cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
369
0
                                poFeatureDefn->GetGeomFieldDefn(0));
370
0
                        poGeomFieldDefn->bSRSSet = TRUE;
371
0
                        poGeomFieldDefn->SetSpatialRef(GetSpatialRef());
372
0
                    }
373
0
                }
374
0
                else
375
0
                {
376
0
                    if (nIndex == 0 && apoGeomFields.size() == 1)
377
0
                    {
378
0
                        OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
379
0
                            cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
380
0
                                poFeatureDefn->GetGeomFieldDefn(0));
381
0
                        if (poGeomFieldDefn->bGeomTypeSet == FALSE)
382
0
                        {
383
0
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
384
0
                            poGeomFieldDefn->SetType(poSrcFieldDefn->GetType());
385
0
                        }
386
0
                        if (poGeomFieldDefn->bSRSSet == FALSE)
387
0
                        {
388
0
                            poGeomFieldDefn->bSRSSet = TRUE;
389
0
                            poGeomFieldDefn->SetSpatialRef(
390
0
                                poSrcFieldDefn->GetSpatialRef());
391
0
                        }
392
0
                    }
393
                    /* TODO: merge type, SRS, extent ? */
394
0
                }
395
0
            }
396
0
        }
397
0
    }
398
0
    else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS)
399
0
    {
400
0
        const OGRFeatureDefn *poSrcFeatureDefn =
401
0
            m_apoSrcLayers[0]->GetLayerDefn();
402
0
        for (const auto *poSrcFieldDefn : poSrcFeatureDefn->GetFields())
403
0
            poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
404
0
        for (const auto *poSrcGeomFieldDefn : poSrcFeatureDefn->GetGeomFields())
405
0
        {
406
0
            poFeatureDefn->AddGeomFieldDefn(
407
0
                std::make_unique<OGRUnionLayerGeomFieldDefn>(
408
0
                    *poSrcGeomFieldDefn));
409
0
        }
410
411
        /* Remove any field that is not found in the source layers */
412
0
        auto oIterSrcLayer = std::next(m_apoSrcLayers.begin());
413
0
        for (; oIterSrcLayer != m_apoSrcLayers.end(); ++oIterSrcLayer)
414
0
        {
415
0
            const OGRFeatureDefn *l_poSrcFeatureDefn =
416
0
                (*oIterSrcLayer)->GetLayerDefn();
417
0
            for (int i = iCompareFirstIndex; i < poFeatureDefn->GetFieldCount();
418
                 // No increment.
419
0
            )
420
0
            {
421
0
                OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
422
0
                int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
423
0
                    poFieldDefn->GetNameRef());
424
0
                if (nSrcIndex < 0)
425
0
                {
426
0
                    poFeatureDefn->DeleteFieldDefn(i);
427
0
                }
428
0
                else
429
0
                {
430
0
                    const OGRFieldDefn *poSrcFieldDefn =
431
0
                        l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
432
0
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
433
434
0
                    i++;
435
0
                }
436
0
            }
437
0
            for (int i = 0; i < poFeatureDefn->GetGeomFieldCount();
438
                 // No increment.
439
0
            )
440
0
            {
441
0
                const OGRGeomFieldDefn *poFieldDefn =
442
0
                    poFeatureDefn->GetGeomFieldDefn(i);
443
0
                int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
444
0
                    poFieldDefn->GetNameRef());
445
0
                if (nSrcIndex < 0)
446
0
                {
447
0
                    poFeatureDefn->DeleteGeomFieldDefn(i);
448
0
                }
449
0
                else
450
0
                {
451
                    /* TODO: merge type, SRS, extent ? */
452
453
0
                    i++;
454
0
                }
455
0
            }
456
0
        }
457
0
    }
458
459
0
    return poFeatureDefn;
460
0
}
461
462
/************************************************************************/
463
/*                            GetGeomType()                             */
464
/************************************************************************/
465
466
OGRwkbGeometryType OGRUnionLayer::GetGeomType() const
467
0
{
468
0
    if (!bUseGeomFields)
469
0
        return wkbNone;
470
0
    if (!apoGeomFields.empty() && apoGeomFields[0]->bGeomTypeSet)
471
0
    {
472
0
        return apoGeomFields[0]->GetType();
473
0
    }
474
475
0
    return OGRLayer::GetGeomType();
476
0
}
477
478
/************************************************************************/
479
/*                   SetSpatialFilterToSourceLayer()                    */
480
/************************************************************************/
481
482
void OGRUnionLayer::SetSpatialFilterToSourceLayer(OGRLayer *poSrcLayer)
483
0
{
484
0
    if (m_iGeomFieldFilter >= 0 &&
485
0
        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
486
0
    {
487
0
        int iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
488
0
            GetLayerDefn()->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
489
0
        if (iSrcGeomField >= 0)
490
0
        {
491
0
            poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
492
0
        }
493
0
        else
494
0
        {
495
0
            poSrcLayer->SetSpatialFilter(nullptr);
496
0
        }
497
0
    }
498
0
    else
499
0
    {
500
0
        poSrcLayer->SetSpatialFilter(nullptr);
501
0
    }
502
0
}
503
504
/************************************************************************/
505
/*                        ConfigureActiveLayer()                        */
506
/************************************************************************/
507
508
void OGRUnionLayer::ConfigureActiveLayer()
509
0
{
510
0
    AutoWarpLayerIfNecessary(iCurLayer);
511
0
    ApplyAttributeFilterToSrcLayer(iCurLayer);
512
0
    SetSpatialFilterToSourceLayer(m_apoSrcLayers[iCurLayer].poLayer);
513
0
    m_apoSrcLayers[iCurLayer]->ResetReading();
514
515
    /* Establish map */
516
0
    GetLayerDefn();
517
0
    const OGRFeatureDefn *poSrcFeatureDefn =
518
0
        m_apoSrcLayers[iCurLayer]->GetLayerDefn();
519
0
    const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
520
0
    const int nDstFieldCount = poFeatureDefn->GetFieldCount();
521
522
0
    std::map<std::string, int> oMapDstFieldNameToIdx;
523
0
    for (int i = 0; i < nDstFieldCount; i++)
524
0
    {
525
0
        const OGRFieldDefn *poDstFieldDefn = poFeatureDefn->GetFieldDefn(i);
526
0
        oMapDstFieldNameToIdx[poDstFieldDefn->GetNameRef()] = i;
527
0
    }
528
529
0
    CPLFree(panMap);
530
0
    panMap = static_cast<int *>(CPLMalloc(nSrcFieldCount * sizeof(int)));
531
0
    for (int i = 0; i < nSrcFieldCount; i++)
532
0
    {
533
0
        const OGRFieldDefn *poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
534
0
        if (m_aosIgnoredFields.FindString(poSrcFieldDefn->GetNameRef()) == -1)
535
0
        {
536
0
            const auto oIter =
537
0
                oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
538
0
            panMap[i] =
539
0
                oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
540
0
        }
541
0
        else
542
0
        {
543
0
            panMap[i] = -1;
544
0
        }
545
0
    }
546
547
0
    if (m_apoSrcLayers[iCurLayer]->TestCapability(OLCIgnoreFields))
548
0
    {
549
0
        CPLStringList aosFieldSrc;
550
0
        for (const char *pszFieldName : cpl::Iterate(m_aosIgnoredFields))
551
0
        {
552
0
            if (EQUAL(pszFieldName, "OGR_GEOMETRY") ||
553
0
                EQUAL(pszFieldName, "OGR_STYLE") ||
554
0
                poSrcFeatureDefn->GetFieldIndex(pszFieldName) >= 0 ||
555
0
                poSrcFeatureDefn->GetGeomFieldIndex(pszFieldName) >= 0)
556
0
            {
557
0
                aosFieldSrc.AddString(pszFieldName);
558
0
            }
559
0
        }
560
561
0
        std::map<std::string, int> oMapSrcFieldNameToIdx;
562
0
        for (int i = 0; i < nSrcFieldCount; i++)
563
0
        {
564
0
            const OGRFieldDefn *poSrcFieldDefn =
565
0
                poSrcFeatureDefn->GetFieldDefn(i);
566
0
            oMapSrcFieldNameToIdx[poSrcFieldDefn->GetNameRef()] = i;
567
0
        }
568
569
        /* Attribute fields */
570
0
        std::vector<bool> abSrcFieldsUsed(nSrcFieldCount);
571
0
        for (int iField = 0; iField < nDstFieldCount; iField++)
572
0
        {
573
0
            const OGRFieldDefn *poFieldDefn =
574
0
                poFeatureDefn->GetFieldDefn(iField);
575
0
            const auto oIter =
576
0
                oMapSrcFieldNameToIdx.find(poFieldDefn->GetNameRef());
577
0
            const int iSrcField =
578
0
                oIter == oMapSrcFieldNameToIdx.end() ? -1 : oIter->second;
579
0
            if (iSrcField >= 0)
580
0
                abSrcFieldsUsed[iSrcField] = true;
581
0
        }
582
0
        for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
583
0
        {
584
0
            if (!abSrcFieldsUsed[iSrcField])
585
0
            {
586
0
                const OGRFieldDefn *poSrcDefn =
587
0
                    poSrcFeatureDefn->GetFieldDefn(iSrcField);
588
0
                aosFieldSrc.AddString(poSrcDefn->GetNameRef());
589
0
            }
590
0
        }
591
592
        /* geometry fields now */
593
0
        abSrcFieldsUsed.clear();
594
0
        abSrcFieldsUsed.resize(poSrcFeatureDefn->GetGeomFieldCount());
595
0
        for (int iField = 0; iField < poFeatureDefn->GetGeomFieldCount();
596
0
             iField++)
597
0
        {
598
0
            const OGRGeomFieldDefn *poFieldDefn =
599
0
                poFeatureDefn->GetGeomFieldDefn(iField);
600
0
            const int iSrcField =
601
0
                poSrcFeatureDefn->GetGeomFieldIndex(poFieldDefn->GetNameRef());
602
0
            if (iSrcField >= 0)
603
0
                abSrcFieldsUsed[iSrcField] = true;
604
0
        }
605
0
        for (int iSrcField = 0;
606
0
             iSrcField < poSrcFeatureDefn->GetGeomFieldCount(); iSrcField++)
607
0
        {
608
0
            if (!abSrcFieldsUsed[iSrcField])
609
0
            {
610
0
                const OGRGeomFieldDefn *poSrcDefn =
611
0
                    poSrcFeatureDefn->GetGeomFieldDefn(iSrcField);
612
0
                aosFieldSrc.AddString(poSrcDefn->GetNameRef());
613
0
            }
614
0
        }
615
616
0
        m_apoSrcLayers[iCurLayer]->SetIgnoredFields(aosFieldSrc.List());
617
0
    }
618
0
}
619
620
/************************************************************************/
621
/*                            ResetReading()                            */
622
/************************************************************************/
623
624
void OGRUnionLayer::ResetReading()
625
0
{
626
0
    iCurLayer = -1;
627
0
}
628
629
/************************************************************************/
630
/*                      AutoWarpLayerIfNecessary()                      */
631
/************************************************************************/
632
633
void OGRUnionLayer::AutoWarpLayerIfNecessary(int iLayer)
634
0
{
635
0
    std::lock_guard oLock(m_oMutex);
636
637
0
    if (!m_apoSrcLayers[iLayer].bCheckIfAutoWrap)
638
0
    {
639
0
        m_apoSrcLayers[iLayer].bCheckIfAutoWrap = true;
640
641
0
        for (int iField = 0; iField < GetLayerDefn()->GetGeomFieldCount();
642
0
             iField++)
643
0
        {
644
0
            const OGRSpatialReference *poSRS =
645
0
                GetLayerDefn()->GetGeomFieldDefn(iField)->GetSpatialRef();
646
647
0
            OGRFeatureDefn *poSrcFeatureDefn =
648
0
                m_apoSrcLayers[iLayer]->GetLayerDefn();
649
0
            int iSrcGeomField = poSrcFeatureDefn->GetGeomFieldIndex(
650
0
                GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef());
651
0
            if (iSrcGeomField >= 0)
652
0
            {
653
0
                const OGRSpatialReference *poSRS2 =
654
0
                    poSrcFeatureDefn->GetGeomFieldDefn(iSrcGeomField)
655
0
                        ->GetSpatialRef();
656
657
0
                if ((poSRS == nullptr && poSRS2 != nullptr) ||
658
0
                    (poSRS != nullptr && poSRS2 == nullptr))
659
0
                {
660
0
                    CPLError(
661
0
                        CE_Warning, CPLE_AppDefined,
662
0
                        "SRS of geometry field '%s' layer %s not "
663
0
                        "consistent with UnionLayer SRS",
664
0
                        GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef(),
665
0
                        m_apoSrcLayers[iLayer]->GetName());
666
0
                }
667
0
                else if (poSRS != nullptr && poSRS2 != nullptr &&
668
0
                         poSRS != poSRS2 && !poSRS->IsSame(poSRS2))
669
0
                {
670
0
                    CPLDebug(
671
0
                        "VRT",
672
0
                        "SRS of geometry field '%s' layer %s not "
673
0
                        "consistent with UnionLayer SRS. "
674
0
                        "Trying auto warping",
675
0
                        GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef(),
676
0
                        m_apoSrcLayers[iLayer]->GetName());
677
0
                    std::unique_ptr<OGRCoordinateTransformation> poCT(
678
0
                        OGRCreateCoordinateTransformation(poSRS2, poSRS));
679
0
                    std::unique_ptr<OGRCoordinateTransformation> poReversedCT(
680
0
                        (poCT != nullptr) ? poCT->GetInverse() : nullptr);
681
0
                    if (poReversedCT != nullptr)
682
0
                    {
683
0
                        auto [poSrcLayer, bOwned] =
684
0
                            m_apoSrcLayers[iLayer].release();
685
0
                        m_apoSrcLayers[iLayer].reset(
686
0
                            std::make_unique<OGRWarpedLayer>(
687
0
                                poSrcLayer, iSrcGeomField, bOwned,
688
0
                                std::move(poCT), std::move(poReversedCT)));
689
0
                    }
690
0
                    else
691
0
                    {
692
0
                        CPLError(CE_Warning, CPLE_AppDefined,
693
0
                                 "AutoWarpLayerIfNecessary failed to create "
694
0
                                 "poCT or poReversedCT.");
695
0
                    }
696
0
                }
697
0
            }
698
0
        }
699
0
    }
700
0
}
701
702
/************************************************************************/
703
/*                           GetNextFeature()                           */
704
/************************************************************************/
705
706
OGRFeature *OGRUnionLayer::GetNextFeature()
707
0
{
708
0
    if (poFeatureDefn == nullptr)
709
0
        GetLayerDefn();
710
711
0
    if (iCurLayer < 0)
712
0
    {
713
0
        iCurLayer = 0;
714
0
        ConfigureActiveLayer();
715
0
        nNextFID = 0;
716
0
    }
717
0
    else if (iCurLayer == static_cast<int>(m_apoSrcLayers.size()))
718
0
        return nullptr;
719
720
0
    m_bHasAlreadyIteratedOverFeatures = true;
721
722
0
    while (true)
723
0
    {
724
0
        auto poSrcFeature = std::unique_ptr<OGRFeature>(
725
0
            m_apoSrcLayers[iCurLayer]->GetNextFeature());
726
0
        if (poSrcFeature == nullptr)
727
0
        {
728
0
            iCurLayer++;
729
0
            if (iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
730
0
            {
731
0
                ConfigureActiveLayer();
732
0
                continue;
733
0
            }
734
0
            else
735
0
            {
736
0
                if (!m_fidRangesInvalid && !bPreserveSrcFID)
737
0
                {
738
0
                    m_fidRangesComplete = true;
739
0
                }
740
0
                break;
741
0
            }
742
0
        }
743
744
0
        auto poFeature = TranslateFromSrcLayer(poSrcFeature.get(), -1);
745
746
        // When iterating over all features, build a ma
747
0
        if (!m_fidRangesInvalid && !bPreserveSrcFID && !m_fidRangesComplete)
748
0
        {
749
0
            if (m_fidRanges.empty() ||
750
0
                m_fidRanges.back().nLayerIdx != iCurLayer ||
751
0
                poSrcFeature->GetFID() > m_fidRanges.back().nSrcFIDStart +
752
0
                                             m_fidRanges.back().nFIDCount)
753
0
            {
754
0
                FIDRange range;
755
0
                range.nDstFIDStart = poFeature->GetFID();
756
0
                range.nFIDCount = 1;
757
0
                range.nSrcFIDStart = poSrcFeature->GetFID();
758
0
                range.nLayerIdx = iCurLayer;
759
0
                m_fidRanges.push_back(std::move(range));
760
0
                if (m_fidRanges.size() > 1000 * 1000)
761
0
                {
762
0
                    m_fidRangesInvalid = true;
763
0
                    m_fidRanges.clear();
764
0
                }
765
0
            }
766
0
            else if (poSrcFeature->GetFID() == m_fidRanges.back().nSrcFIDStart +
767
0
                                                   m_fidRanges.back().nFIDCount)
768
0
            {
769
0
                ++m_fidRanges.back().nFIDCount;
770
0
            }
771
0
            else
772
0
            {
773
                // Decreasing src FID
774
0
                m_fidRangesInvalid = true;
775
0
                m_fidRanges.clear();
776
0
            }
777
0
        }
778
779
0
        if ((m_poFilterGeom == nullptr ||
780
0
             FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
781
0
            (m_poAttrQuery == nullptr ||
782
0
             m_poAttrQuery->Evaluate(poFeature.get())))
783
0
        {
784
0
            return poFeature.release();
785
0
        }
786
0
    }
787
0
    return nullptr;
788
0
}
789
790
/************************************************************************/
791
/*                             GetFeature()                             */
792
/************************************************************************/
793
794
OGRFeature *OGRUnionLayer::GetFeature(GIntBig nFeatureId)
795
0
{
796
0
    std::unique_ptr<OGRFeature> poFeature;
797
798
0
    if (!bPreserveSrcFID)
799
0
    {
800
0
        if (m_fidRangesComplete)
801
0
        {
802
0
            if (!m_fidRanges.empty() &&
803
0
                nFeatureId >= m_fidRanges[0].nDstFIDStart &&
804
0
                nFeatureId < m_fidRanges.back().nDstFIDStart +
805
0
                                 m_fidRanges.back().nFIDCount)
806
0
            {
807
                // Dichotomic search
808
0
                size_t iStart = 0;
809
0
                size_t iEnd = m_fidRanges.size() - 1;
810
0
                while (iEnd - iStart > 1)
811
0
                {
812
0
                    size_t iMiddle = (iStart + iEnd) / 2;
813
0
                    if (nFeatureId < m_fidRanges[iMiddle].nDstFIDStart)
814
0
                    {
815
0
                        iEnd = iMiddle;
816
0
                    }
817
0
                    else
818
0
                    {
819
0
                        iStart = iMiddle;
820
0
                    }
821
0
                }
822
823
0
                size_t iRange = iStart;
824
0
                CPLAssert(nFeatureId >= m_fidRanges[iStart].nDstFIDStart);
825
0
                CPLAssert(nFeatureId < m_fidRanges[iEnd].nDstFIDStart +
826
0
                                           m_fidRanges[iEnd].nFIDCount);
827
0
                if (iStart < iEnd &&
828
0
                    nFeatureId >= m_fidRanges[iEnd].nDstFIDStart)
829
0
                    ++iRange;
830
0
                if (nFeatureId < m_fidRanges[iRange].nDstFIDStart +
831
0
                                     m_fidRanges[iRange].nFIDCount)
832
0
                {
833
0
                    iCurLayer = m_fidRanges[iRange].nLayerIdx;
834
0
                    ConfigureActiveLayer();
835
836
0
                    const auto nSrcFID = nFeatureId -
837
0
                                         m_fidRanges[iRange].nDstFIDStart +
838
0
                                         m_fidRanges[iRange].nSrcFIDStart;
839
840
0
                    auto poSrcFeature = std::unique_ptr<OGRFeature>(
841
0
                        m_apoSrcLayers[iCurLayer]->GetFeature(nSrcFID));
842
                    // In theory below assertion should be true, unless the
843
                    // dataset has been modified behind our back.
844
                    // CPLAssert(poSrcFeature);
845
0
                    if (poSrcFeature)
846
0
                    {
847
0
                        poFeature = TranslateFromSrcLayer(poSrcFeature.get(),
848
0
                                                          nFeatureId);
849
0
                    }
850
0
                }
851
0
            }
852
0
        }
853
0
        else
854
0
        {
855
0
            poFeature.reset(OGRLayer::GetFeature(nFeatureId));
856
0
        }
857
0
    }
858
0
    else
859
0
    {
860
0
        const int iGeomFieldFilterSave = m_iGeomFieldFilter;
861
0
        std::unique_ptr<OGRGeometry> poGeomSave(m_poFilterGeom);
862
0
        m_poFilterGeom = nullptr;
863
0
        SetSpatialFilter(nullptr);
864
865
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
866
0
        {
867
0
            iCurLayer = i;
868
0
            ConfigureActiveLayer();
869
870
0
            auto poSrcFeature = std::unique_ptr<OGRFeature>(
871
0
                m_apoSrcLayers[i]->GetFeature(nFeatureId));
872
0
            if (poSrcFeature != nullptr)
873
0
            {
874
0
                poFeature =
875
0
                    TranslateFromSrcLayer(poSrcFeature.get(), nFeatureId);
876
0
                break;
877
0
            }
878
0
        }
879
880
0
        SetSpatialFilter(iGeomFieldFilterSave, poGeomSave.get());
881
882
0
        ResetReading();
883
0
    }
884
885
0
    return poFeature.release();
886
0
}
887
888
/************************************************************************/
889
/*                           ICreateFeature()                           */
890
/************************************************************************/
891
892
OGRErr OGRUnionLayer::ICreateFeature(OGRFeature *poFeature)
893
0
{
894
0
    if (osSourceLayerFieldName.empty())
895
0
    {
896
0
        CPLError(CE_Failure, CPLE_NotSupported,
897
0
                 "CreateFeature() not supported when SourceLayerFieldName is "
898
0
                 "not set");
899
0
        return OGRERR_FAILURE;
900
0
    }
901
902
0
    if (poFeature->GetFID() != OGRNullFID)
903
0
    {
904
0
        CPLError(CE_Failure, CPLE_NotSupported,
905
0
                 "CreateFeature() not supported when FID is set");
906
0
        return OGRERR_FAILURE;
907
0
    }
908
909
0
    if (!poFeature->IsFieldSetAndNotNull(0))
910
0
    {
911
0
        CPLError(CE_Failure, CPLE_NotSupported,
912
0
                 "CreateFeature() not supported when '%s' field is not set",
913
0
                 osSourceLayerFieldName.c_str());
914
0
        return OGRERR_FAILURE;
915
0
    }
916
917
0
    m_fidRangesComplete = false;
918
0
    m_fidRanges.clear();
919
920
0
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
921
0
    for (auto &oLayer : m_apoSrcLayers)
922
0
    {
923
0
        if (strcmp(pszSrcLayerName, oLayer->GetName()) == 0)
924
0
        {
925
0
            oLayer.bModified = true;
926
927
0
            OGRFeature *poSrcFeature = new OGRFeature(oLayer->GetLayerDefn());
928
0
            poSrcFeature->SetFrom(poFeature, TRUE);
929
0
            OGRErr eErr = oLayer->CreateFeature(poSrcFeature);
930
0
            if (eErr == OGRERR_NONE)
931
0
                poFeature->SetFID(poSrcFeature->GetFID());
932
0
            delete poSrcFeature;
933
0
            return eErr;
934
0
        }
935
0
    }
936
937
0
    CPLError(CE_Failure, CPLE_NotSupported,
938
0
             "CreateFeature() not supported : '%s' source layer does not exist",
939
0
             pszSrcLayerName);
940
0
    return OGRERR_FAILURE;
941
0
}
942
943
/************************************************************************/
944
/*                            ISetFeature()                             */
945
/************************************************************************/
946
947
OGRErr OGRUnionLayer::ISetFeature(OGRFeature *poFeature)
948
0
{
949
0
    if (!bPreserveSrcFID)
950
0
    {
951
0
        CPLError(CE_Failure, CPLE_NotSupported,
952
0
                 "SetFeature() not supported when PreserveSrcFID is OFF");
953
0
        return OGRERR_FAILURE;
954
0
    }
955
956
0
    if (osSourceLayerFieldName.empty())
957
0
    {
958
0
        CPLError(
959
0
            CE_Failure, CPLE_NotSupported,
960
0
            "SetFeature() not supported when SourceLayerFieldName is not set");
961
0
        return OGRERR_FAILURE;
962
0
    }
963
964
0
    if (poFeature->GetFID() == OGRNullFID)
965
0
    {
966
0
        CPLError(CE_Failure, CPLE_NotSupported,
967
0
                 "SetFeature() not supported when FID is not set");
968
0
        return OGRERR_FAILURE;
969
0
    }
970
971
0
    if (!poFeature->IsFieldSetAndNotNull(0))
972
0
    {
973
0
        CPLError(CE_Failure, CPLE_NotSupported,
974
0
                 "SetFeature() not supported when '%s' field is not set",
975
0
                 osSourceLayerFieldName.c_str());
976
0
        return OGRERR_FAILURE;
977
0
    }
978
979
0
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
980
0
    for (auto &oLayer : m_apoSrcLayers)
981
0
    {
982
0
        if (strcmp(pszSrcLayerName, oLayer->GetName()) == 0)
983
0
        {
984
0
            oLayer.bModified = true;
985
986
0
            OGRFeature *poSrcFeature = new OGRFeature(oLayer->GetLayerDefn());
987
0
            poSrcFeature->SetFrom(poFeature, TRUE);
988
0
            poSrcFeature->SetFID(poFeature->GetFID());
989
0
            OGRErr eErr = oLayer->SetFeature(poSrcFeature);
990
0
            delete poSrcFeature;
991
0
            return eErr;
992
0
        }
993
0
    }
994
995
0
    CPLError(CE_Failure, CPLE_NotSupported,
996
0
             "SetFeature() not supported : '%s' source layer does not exist",
997
0
             pszSrcLayerName);
998
0
    return OGRERR_FAILURE;
999
0
}
1000
1001
/************************************************************************/
1002
/*                           IUpsertFeature()                           */
1003
/************************************************************************/
1004
1005
OGRErr OGRUnionLayer::IUpsertFeature(OGRFeature *poFeature)
1006
0
{
1007
0
    if (std::unique_ptr<OGRFeature>(GetFeature(poFeature->GetFID())))
1008
0
    {
1009
0
        return ISetFeature(poFeature);
1010
0
    }
1011
0
    else
1012
0
    {
1013
0
        return ICreateFeature(poFeature);
1014
0
    }
1015
0
}
1016
1017
/************************************************************************/
1018
/*                           IUpdateFeature()                           */
1019
/************************************************************************/
1020
1021
OGRErr OGRUnionLayer::IUpdateFeature(OGRFeature *poFeature,
1022
                                     int nUpdatedFieldsCount,
1023
                                     const int *panUpdatedFieldsIdx,
1024
                                     int nUpdatedGeomFieldsCount,
1025
                                     const int *panUpdatedGeomFieldsIdx,
1026
                                     bool bUpdateStyleString)
1027
0
{
1028
0
    if (!bPreserveSrcFID)
1029
0
    {
1030
0
        CPLError(CE_Failure, CPLE_NotSupported,
1031
0
                 "UpdateFeature() not supported when PreserveSrcFID is OFF");
1032
0
        return OGRERR_FAILURE;
1033
0
    }
1034
1035
0
    if (osSourceLayerFieldName.empty())
1036
0
    {
1037
0
        CPLError(CE_Failure, CPLE_NotSupported,
1038
0
                 "UpdateFeature() not supported when SourceLayerFieldName is "
1039
0
                 "not set");
1040
0
        return OGRERR_FAILURE;
1041
0
    }
1042
1043
0
    if (poFeature->GetFID() == OGRNullFID)
1044
0
    {
1045
0
        CPLError(CE_Failure, CPLE_NotSupported,
1046
0
                 "UpdateFeature() not supported when FID is not set");
1047
0
        return OGRERR_FAILURE;
1048
0
    }
1049
1050
0
    if (!poFeature->IsFieldSetAndNotNull(0))
1051
0
    {
1052
0
        CPLError(CE_Failure, CPLE_NotSupported,
1053
0
                 "UpdateFeature() not supported when '%s' field is not set",
1054
0
                 osSourceLayerFieldName.c_str());
1055
0
        return OGRERR_FAILURE;
1056
0
    }
1057
1058
0
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
1059
0
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1060
0
    {
1061
0
        if (strcmp(pszSrcLayerName, m_apoSrcLayers[i]->GetName()) == 0)
1062
0
        {
1063
0
            m_apoSrcLayers[i].bModified = true;
1064
1065
0
            const auto poSrcLayerDefn = m_apoSrcLayers[i]->GetLayerDefn();
1066
0
            OGRFeature *poSrcFeature = new OGRFeature(poSrcLayerDefn);
1067
0
            poSrcFeature->SetFrom(poFeature, TRUE);
1068
0
            poSrcFeature->SetFID(poFeature->GetFID());
1069
1070
            // We could potentially have a pre-computed map from indices in
1071
            // poLayerDefn to indices in poSrcLayerDefn
1072
0
            std::vector<int> anSrcUpdatedFieldIdx;
1073
0
            const auto poLayerDefn = GetLayerDefn();
1074
0
            for (int j = 0; j < nUpdatedFieldsCount; ++j)
1075
0
            {
1076
0
                if (panUpdatedFieldsIdx[j] != 0)
1077
0
                {
1078
0
                    const int nNewIdx = poSrcLayerDefn->GetFieldIndex(
1079
0
                        poLayerDefn->GetFieldDefn(panUpdatedFieldsIdx[j])
1080
0
                            ->GetNameRef());
1081
0
                    if (nNewIdx >= 0)
1082
0
                    {
1083
0
                        anSrcUpdatedFieldIdx.push_back(nNewIdx);
1084
0
                    }
1085
0
                }
1086
0
            }
1087
0
            std::vector<int> anSrcUpdatedGeomFieldIdx;
1088
0
            for (int j = 0; j < nUpdatedGeomFieldsCount; ++j)
1089
0
            {
1090
0
                if (panUpdatedGeomFieldsIdx[j] != 0)
1091
0
                {
1092
0
                    const int nNewIdx = poSrcLayerDefn->GetGeomFieldIndex(
1093
0
                        poLayerDefn
1094
0
                            ->GetGeomFieldDefn(panUpdatedGeomFieldsIdx[j])
1095
0
                            ->GetNameRef());
1096
0
                    if (nNewIdx >= 0)
1097
0
                    {
1098
0
                        anSrcUpdatedGeomFieldIdx.push_back(nNewIdx);
1099
0
                    }
1100
0
                }
1101
0
            }
1102
1103
0
            OGRErr eErr = m_apoSrcLayers[i]->UpdateFeature(
1104
0
                poSrcFeature, static_cast<int>(anSrcUpdatedFieldIdx.size()),
1105
0
                anSrcUpdatedFieldIdx.data(),
1106
0
                static_cast<int>(anSrcUpdatedGeomFieldIdx.size()),
1107
0
                anSrcUpdatedGeomFieldIdx.data(), bUpdateStyleString);
1108
0
            delete poSrcFeature;
1109
0
            return eErr;
1110
0
        }
1111
0
    }
1112
1113
0
    CPLError(CE_Failure, CPLE_NotSupported,
1114
0
             "UpdateFeature() not supported : '%s' source layer does not exist",
1115
0
             pszSrcLayerName);
1116
0
    return OGRERR_FAILURE;
1117
0
}
1118
1119
/************************************************************************/
1120
/*                           GetSpatialRef()                            */
1121
/************************************************************************/
1122
1123
const OGRSpatialReference *OGRUnionLayer::GetSpatialRef() const
1124
0
{
1125
0
    if (!bUseGeomFields)
1126
0
        return nullptr;
1127
0
    if (!apoGeomFields.empty() && apoGeomFields[0]->bSRSSet)
1128
0
        return apoGeomFields[0]->GetSpatialRef();
1129
1130
0
    if (poGlobalSRS == nullptr)
1131
0
    {
1132
0
        poGlobalSRS = m_apoSrcLayers[0]->GetSpatialRef();
1133
0
        if (poGlobalSRS != nullptr)
1134
0
            const_cast<OGRSpatialReference *>(poGlobalSRS)->Reference();
1135
0
    }
1136
0
    return poGlobalSRS;
1137
0
}
1138
1139
/************************************************************************/
1140
/*                   GetAttrFilterPassThroughValue()                    */
1141
/************************************************************************/
1142
1143
int OGRUnionLayer::GetAttrFilterPassThroughValue() const
1144
0
{
1145
0
    if (m_poAttrQuery == nullptr)
1146
0
        return TRUE;
1147
1148
0
    if (bAttrFilterPassThroughValue >= 0)
1149
0
        return bAttrFilterPassThroughValue;
1150
1151
0
    char **papszUsedFields = m_poAttrQuery->GetUsedFields();
1152
0
    int bRet = TRUE;
1153
1154
0
    for (auto &oLayer : m_apoSrcLayers)
1155
0
    {
1156
0
        const OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
1157
0
        char **papszIter = papszUsedFields;
1158
0
        while (papszIter != nullptr && *papszIter != nullptr)
1159
0
        {
1160
0
            int bIsSpecial = FALSE;
1161
0
            for (int i = 0; i < SPECIAL_FIELD_COUNT; i++)
1162
0
            {
1163
0
                if (EQUAL(*papszIter, SpecialFieldNames[i]))
1164
0
                {
1165
0
                    bIsSpecial = TRUE;
1166
0
                    break;
1167
0
                }
1168
0
            }
1169
0
            if (!bIsSpecial && poSrcFeatureDefn->GetFieldIndex(*papszIter) < 0)
1170
0
            {
1171
0
                bRet = FALSE;
1172
0
                break;
1173
0
            }
1174
0
            papszIter++;
1175
0
        }
1176
0
    }
1177
1178
0
    CSLDestroy(papszUsedFields);
1179
1180
0
    bAttrFilterPassThroughValue = bRet;
1181
1182
0
    return bRet;
1183
0
}
1184
1185
/************************************************************************/
1186
/*                   ApplyAttributeFilterToSrcLayer()                   */
1187
/************************************************************************/
1188
1189
void OGRUnionLayer::ApplyAttributeFilterToSrcLayer(int iSubLayer)
1190
0
{
1191
0
    std::lock_guard oLock(m_oMutex);
1192
1193
0
    CPLAssert(iSubLayer >= 0 &&
1194
0
              iSubLayer < static_cast<int>(m_apoSrcLayers.size()));
1195
1196
0
    if (GetAttrFilterPassThroughValue())
1197
0
        m_apoSrcLayers[iSubLayer]->SetAttributeFilter(pszAttributeFilter);
1198
0
    else
1199
0
        m_apoSrcLayers[iSubLayer]->SetAttributeFilter(nullptr);
1200
0
}
1201
1202
/************************************************************************/
1203
/*                          GetFeatureCount()                           */
1204
/************************************************************************/
1205
1206
GIntBig OGRUnionLayer::GetFeatureCount(int bForce)
1207
0
{
1208
0
    if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
1209
0
        m_poAttrQuery == nullptr)
1210
0
    {
1211
0
        return nFeatureCount;
1212
0
    }
1213
1214
0
    if (!GetAttrFilterPassThroughValue())
1215
0
        return OGRLayer::GetFeatureCount(bForce);
1216
1217
0
    GIntBig nRet = 0;
1218
0
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1219
0
    {
1220
0
        AutoWarpLayerIfNecessary(i);
1221
0
        ApplyAttributeFilterToSrcLayer(i);
1222
0
        SetSpatialFilterToSourceLayer(m_apoSrcLayers[i].poLayer);
1223
0
        const GIntBig nThisLayerFC = m_apoSrcLayers[i]->GetFeatureCount(bForce);
1224
0
        if (nThisLayerFC < 0 ||
1225
0
            nThisLayerFC > std::numeric_limits<GIntBig>::max() - nRet)
1226
0
            return 0;
1227
0
        nRet += nThisLayerFC;
1228
0
    }
1229
0
    ResetReading();
1230
0
    return nRet;
1231
0
}
1232
1233
/************************************************************************/
1234
/*                         SetAttributeFilter()                         */
1235
/************************************************************************/
1236
1237
OGRErr OGRUnionLayer::SetAttributeFilter(const char *pszAttributeFilterIn)
1238
0
{
1239
0
    if (pszAttributeFilterIn == nullptr && pszAttributeFilter == nullptr)
1240
0
        return OGRERR_NONE;
1241
0
    if (pszAttributeFilterIn != nullptr && pszAttributeFilter != nullptr &&
1242
0
        strcmp(pszAttributeFilterIn, pszAttributeFilter) == 0)
1243
0
        return OGRERR_NONE;
1244
1245
0
    if (m_bHasAlreadyIteratedOverFeatures)
1246
0
    {
1247
0
        m_fidRanges.clear();
1248
0
        m_fidRangesComplete = false;
1249
0
        m_fidRangesInvalid = true;
1250
0
    }
1251
1252
0
    if (poFeatureDefn == nullptr)
1253
0
        GetLayerDefn();
1254
1255
0
    bAttrFilterPassThroughValue = -1;
1256
1257
0
    OGRErr eErr = OGRLayer::SetAttributeFilter(pszAttributeFilterIn);
1258
0
    if (eErr != OGRERR_NONE)
1259
0
        return eErr;
1260
1261
0
    CPLFree(pszAttributeFilter);
1262
0
    pszAttributeFilter =
1263
0
        pszAttributeFilterIn ? CPLStrdup(pszAttributeFilterIn) : nullptr;
1264
1265
0
    if (iCurLayer >= 0 && iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
1266
0
        ApplyAttributeFilterToSrcLayer(iCurLayer);
1267
1268
0
    return OGRERR_NONE;
1269
0
}
1270
1271
/************************************************************************/
1272
/*                           TestCapability()                           */
1273
/************************************************************************/
1274
1275
int OGRUnionLayer::TestCapability(const char *pszCap) const
1276
0
{
1277
0
    if (EQUAL(pszCap, OLCFastFeatureCount))
1278
0
    {
1279
0
        if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
1280
0
            m_poAttrQuery == nullptr)
1281
0
            return TRUE;
1282
1283
0
        if (!GetAttrFilterPassThroughValue())
1284
0
            return FALSE;
1285
1286
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1287
0
        {
1288
0
            const_cast<OGRUnionLayer *>(this)->AutoWarpLayerIfNecessary(i);
1289
0
            const_cast<OGRUnionLayer *>(this)->ApplyAttributeFilterToSrcLayer(
1290
0
                i);
1291
0
            const_cast<OGRUnionLayer *>(this)->SetSpatialFilterToSourceLayer(
1292
0
                m_apoSrcLayers[i].poLayer);
1293
0
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
1294
0
                return FALSE;
1295
0
        }
1296
0
        return TRUE;
1297
0
    }
1298
1299
0
    if (EQUAL(pszCap, OLCFastGetExtent))
1300
0
    {
1301
0
        if (!apoGeomFields.empty() &&
1302
0
            apoGeomFields[0]->sStaticEnvelope.IsInit())
1303
0
            return TRUE;
1304
1305
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1306
0
        {
1307
0
            const_cast<OGRUnionLayer *>(this)->AutoWarpLayerIfNecessary(i);
1308
0
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
1309
0
                return FALSE;
1310
0
        }
1311
0
        return TRUE;
1312
0
    }
1313
1314
0
    if (EQUAL(pszCap, OLCFastSpatialFilter))
1315
0
    {
1316
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1317
0
        {
1318
0
            const_cast<OGRUnionLayer *>(this)->AutoWarpLayerIfNecessary(i);
1319
0
            const_cast<OGRUnionLayer *>(this)->ApplyAttributeFilterToSrcLayer(
1320
0
                i);
1321
0
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
1322
0
                return FALSE;
1323
0
        }
1324
0
        return TRUE;
1325
0
    }
1326
1327
0
    if (EQUAL(pszCap, OLCStringsAsUTF8))
1328
0
    {
1329
0
        for (auto &oLayer : m_apoSrcLayers)
1330
0
        {
1331
0
            if (!oLayer->TestCapability(pszCap))
1332
0
                return FALSE;
1333
0
        }
1334
0
        return TRUE;
1335
0
    }
1336
1337
0
    if (EQUAL(pszCap, OLCRandomRead))
1338
0
    {
1339
0
        if (!bPreserveSrcFID && !m_fidRangesComplete)
1340
0
            return FALSE;
1341
1342
0
        for (auto &oLayer : m_apoSrcLayers)
1343
0
        {
1344
0
            if (!oLayer->TestCapability(pszCap))
1345
0
                return FALSE;
1346
0
        }
1347
0
        return TRUE;
1348
0
    }
1349
1350
0
    if (EQUAL(pszCap, OLCRandomWrite))
1351
0
    {
1352
0
        if (!bPreserveSrcFID || osSourceLayerFieldName.empty())
1353
0
            return FALSE;
1354
1355
0
        for (auto &oLayer : m_apoSrcLayers)
1356
0
        {
1357
0
            if (!oLayer->TestCapability(pszCap))
1358
0
                return FALSE;
1359
0
        }
1360
0
        return TRUE;
1361
0
    }
1362
1363
0
    if (EQUAL(pszCap, OLCSequentialWrite))
1364
0
    {
1365
0
        if (osSourceLayerFieldName.empty())
1366
0
            return FALSE;
1367
1368
0
        for (auto &oLayer : m_apoSrcLayers)
1369
0
        {
1370
0
            if (!oLayer->TestCapability(pszCap))
1371
0
                return FALSE;
1372
0
        }
1373
0
        return TRUE;
1374
0
    }
1375
1376
0
    if (EQUAL(pszCap, OLCIgnoreFields))
1377
0
        return TRUE;
1378
1379
0
    if (EQUAL(pszCap, OLCCurveGeometries))
1380
0
        return TRUE;
1381
1382
0
    return FALSE;
1383
0
}
1384
1385
/************************************************************************/
1386
/*                             IGetExtent()                             */
1387
/************************************************************************/
1388
1389
OGRErr OGRUnionLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
1390
                                 bool bForce)
1391
0
{
1392
0
    if (iGeomField >= 0 &&
1393
0
        static_cast<size_t>(iGeomField) < apoGeomFields.size() &&
1394
0
        apoGeomFields[iGeomField]->sStaticEnvelope.IsInit())
1395
0
    {
1396
0
        *psExtent = apoGeomFields[iGeomField]->sStaticEnvelope;
1397
0
        return OGRERR_NONE;
1398
0
    }
1399
1400
0
    if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount())
1401
0
    {
1402
0
        if (iGeomField != 0)
1403
0
        {
1404
0
            CPLError(CE_Failure, CPLE_AppDefined,
1405
0
                     "Invalid geometry field index : %d", iGeomField);
1406
0
        }
1407
0
        return OGRERR_FAILURE;
1408
0
    }
1409
1410
0
    int bInit = FALSE;
1411
0
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1412
0
    {
1413
0
        AutoWarpLayerIfNecessary(i);
1414
0
        int iSrcGeomField =
1415
0
            m_apoSrcLayers[i]->GetLayerDefn()->GetGeomFieldIndex(
1416
0
                GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetNameRef());
1417
0
        if (iSrcGeomField >= 0)
1418
0
        {
1419
0
            if (!bInit)
1420
0
            {
1421
0
                if (m_apoSrcLayers[i]->GetExtent(iSrcGeomField, psExtent,
1422
0
                                                 bForce) == OGRERR_NONE)
1423
0
                    bInit = TRUE;
1424
0
            }
1425
0
            else
1426
0
            {
1427
0
                OGREnvelope sExtent;
1428
0
                if (m_apoSrcLayers[i]->GetExtent(iSrcGeomField, &sExtent,
1429
0
                                                 bForce) == OGRERR_NONE)
1430
0
                {
1431
0
                    psExtent->Merge(sExtent);
1432
0
                }
1433
0
            }
1434
0
        }
1435
0
    }
1436
0
    return (bInit) ? OGRERR_NONE : OGRERR_FAILURE;
1437
0
}
1438
1439
/************************************************************************/
1440
/*                         ISetSpatialFilter()                          */
1441
/************************************************************************/
1442
1443
OGRErr OGRUnionLayer::ISetSpatialFilter(int iGeomField,
1444
                                        const OGRGeometry *poGeom)
1445
0
{
1446
0
    if (!(m_iGeomFieldFilter == iGeomField &&
1447
0
          ((poGeom == nullptr && m_poFilterGeom == nullptr) ||
1448
0
           (poGeom && m_poFilterGeom && poGeom->Equals(m_poFilterGeom)))))
1449
0
    {
1450
0
        if (m_bHasAlreadyIteratedOverFeatures)
1451
0
        {
1452
0
            m_fidRanges.clear();
1453
0
            m_fidRangesComplete = false;
1454
0
            m_fidRangesInvalid = true;
1455
0
        }
1456
1457
0
        m_iGeomFieldFilter = iGeomField;
1458
0
        if (InstallFilter(poGeom))
1459
0
            ResetReading();
1460
1461
0
        if (iCurLayer >= 0 &&
1462
0
            iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
1463
0
        {
1464
0
            SetSpatialFilterToSourceLayer(m_apoSrcLayers[iCurLayer].poLayer);
1465
0
        }
1466
0
    }
1467
1468
0
    return OGRERR_NONE;
1469
0
}
1470
1471
/************************************************************************/
1472
/*                       TranslateFromSrcLayer()                        */
1473
/************************************************************************/
1474
1475
std::unique_ptr<OGRFeature>
1476
OGRUnionLayer::TranslateFromSrcLayer(OGRFeature *poSrcFeature, GIntBig nFID)
1477
0
{
1478
0
    CPLAssert(poSrcFeature->GetFieldCount() == 0 || panMap != nullptr);
1479
0
    CPLAssert(iCurLayer >= 0 &&
1480
0
              iCurLayer < static_cast<int>(m_apoSrcLayers.size()));
1481
1482
0
    auto poFeature = std::make_unique<OGRFeature>(poFeatureDefn);
1483
0
    poFeature->SetFrom(poSrcFeature, panMap, TRUE);
1484
1485
0
    if (!osSourceLayerFieldName.empty() &&
1486
0
        !poFeatureDefn->GetFieldDefn(0)->IsIgnored())
1487
0
    {
1488
0
        poFeature->SetField(0, m_apoSrcLayers[iCurLayer]->GetName());
1489
0
    }
1490
1491
0
    for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1492
0
    {
1493
0
        if (poFeatureDefn->GetGeomFieldDefn(i)->IsIgnored())
1494
0
            poFeature->SetGeomFieldDirectly(i, nullptr);
1495
0
        else
1496
0
        {
1497
0
            OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
1498
0
            if (poGeom != nullptr)
1499
0
            {
1500
0
                poGeom->assignSpatialReference(
1501
0
                    poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
1502
0
            }
1503
0
        }
1504
0
    }
1505
1506
0
    if (nFID >= 0)
1507
0
        poFeature->SetFID(nFID);
1508
0
    else if (bPreserveSrcFID)
1509
0
        poFeature->SetFID(poSrcFeature->GetFID());
1510
0
    else
1511
0
        poFeature->SetFID(nNextFID++);
1512
0
    return poFeature;
1513
0
}
1514
1515
/************************************************************************/
1516
/*                          SetIgnoredFields()                          */
1517
/************************************************************************/
1518
1519
OGRErr OGRUnionLayer::SetIgnoredFields(CSLConstList papszFields)
1520
0
{
1521
0
    OGRErr eErr = OGRLayer::SetIgnoredFields(papszFields);
1522
0
    if (eErr != OGRERR_NONE)
1523
0
        return eErr;
1524
1525
0
    m_aosIgnoredFields = papszFields;
1526
1527
0
    return eErr;
1528
0
}
1529
1530
/************************************************************************/
1531
/*                             SyncToDisk()                             */
1532
/************************************************************************/
1533
1534
OGRErr OGRUnionLayer::SyncToDisk()
1535
0
{
1536
0
    for (auto &oLayer : m_apoSrcLayers)
1537
0
    {
1538
0
        if (oLayer.bModified)
1539
0
        {
1540
0
            oLayer->SyncToDisk();
1541
0
            oLayer.bModified = false;
1542
0
        }
1543
0
    }
1544
1545
0
    return OGRERR_NONE;
1546
0
}
1547
1548
#endif /* #ifndef DOXYGEN_SKIP */