Coverage Report

Created: 2025-11-16 06:25

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