Coverage Report

Created: 2025-06-13 06:29

/src/gdal/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
Line
Count
Source (jump to first uncovered line)
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
OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
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
                    OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
251
0
                    int nIndex = poSrcFeatureDefn->GetGeomFieldIndex(
252
0
                        poGeomFieldDefn->GetNameRef());
253
0
                    if (nIndex >= 0)
254
0
                    {
255
0
                        OGRGeomFieldDefn *poSrcGeomFieldDefn =
256
0
                            poSrcFeatureDefn->GetGeomFieldDefn(nIndex);
257
0
                        if (poGeomFieldDefn->bGeomTypeSet == FALSE)
258
0
                        {
259
0
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
260
0
                            poGeomFieldDefn->SetType(
261
0
                                poSrcGeomFieldDefn->GetType());
262
0
                        }
263
0
                        if (poGeomFieldDefn->bSRSSet == FALSE)
264
0
                        {
265
0
                            poGeomFieldDefn->bSRSSet = TRUE;
266
0
                            poGeomFieldDefn->SetSpatialRef(
267
0
                                poSrcGeomFieldDefn->GetSpatialRef());
268
0
                            if (i == 0 && poGlobalSRS == nullptr)
269
0
                            {
270
0
                                poGlobalSRS =
271
0
                                    poSrcGeomFieldDefn->GetSpatialRef();
272
0
                                if (poGlobalSRS != nullptr)
273
0
                                    const_cast<OGRSpatialReference *>(
274
0
                                        poGlobalSRS)
275
0
                                        ->Reference();
276
0
                            }
277
0
                        }
278
0
                        break;
279
0
                    }
280
0
                }
281
0
            }
282
0
        }
283
0
    }
284
0
    else if (eFieldStrategy == FIELD_FROM_FIRST_LAYER)
285
0
    {
286
0
        const OGRFeatureDefn *poSrcFeatureDefn =
287
0
            m_apoSrcLayers[0]->GetLayerDefn();
288
0
        const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
289
0
        for (int i = 0; i < nSrcFieldCount; i++)
290
0
            poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
291
0
        for (int i = 0;
292
0
             nGeomFields != -1 && i < poSrcFeatureDefn->GetGeomFieldCount();
293
0
             i++)
294
0
        {
295
0
            const OGRGeomFieldDefn *poFldDefn =
296
0
                poSrcFeatureDefn->GetGeomFieldDefn(i);
297
0
            poFeatureDefn->AddGeomFieldDefn(
298
0
                std::make_unique<OGRUnionLayerGeomFieldDefn>(poFldDefn));
299
0
        }
300
0
    }
301
0
    else if (eFieldStrategy == FIELD_UNION_ALL_LAYERS)
302
0
    {
303
0
        if (nGeomFields == 1)
304
0
        {
305
0
            poFeatureDefn->AddGeomFieldDefn(
306
0
                std::make_unique<OGRUnionLayerGeomFieldDefn>(
307
0
                    papoGeomFields[0]));
308
0
        }
309
310
0
        int nDstFieldCount = 0;
311
0
        std::map<std::string, int> oMapDstFieldNameToIdx;
312
313
0
        for (auto &oLayer : m_apoSrcLayers)
314
0
        {
315
0
            const OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
316
317
            /* Add any field that is found in the source layers */
318
0
            const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
319
0
            for (int i = 0; i < nSrcFieldCount; i++)
320
0
            {
321
0
                const OGRFieldDefn *poSrcFieldDefn =
322
0
                    poSrcFeatureDefn->GetFieldDefn(i);
323
0
                const auto oIter =
324
0
                    oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
325
0
                const int nIndex =
326
0
                    oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
327
0
                if (nIndex < 0)
328
0
                {
329
0
                    oMapDstFieldNameToIdx[poSrcFieldDefn->GetNameRef()] =
330
0
                        nDstFieldCount;
331
0
                    nDstFieldCount++;
332
0
                    poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
333
0
                }
334
0
                else
335
0
                {
336
0
                    OGRFieldDefn *poFieldDefn =
337
0
                        poFeatureDefn->GetFieldDefn(nIndex);
338
0
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
339
0
                }
340
0
            }
341
342
0
            for (int i = 0;
343
0
                 nGeomFields != -1 && i < poSrcFeatureDefn->GetGeomFieldCount();
344
0
                 i++)
345
0
            {
346
0
                const OGRGeomFieldDefn *poSrcFieldDefn =
347
0
                    poSrcFeatureDefn->GetGeomFieldDefn(i);
348
0
                int nIndex = poFeatureDefn->GetGeomFieldIndex(
349
0
                    poSrcFieldDefn->GetNameRef());
350
0
                if (nIndex < 0)
351
0
                {
352
0
                    poFeatureDefn->AddGeomFieldDefn(
353
0
                        std::make_unique<OGRUnionLayerGeomFieldDefn>(
354
0
                            poSrcFieldDefn));
355
0
                    if (poFeatureDefn->GetGeomFieldCount() == 1 &&
356
0
                        nGeomFields == 0 && GetSpatialRef() != nullptr)
357
0
                    {
358
0
                        OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
359
0
                            cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
360
0
                                poFeatureDefn->GetGeomFieldDefn(0));
361
0
                        poGeomFieldDefn->bSRSSet = TRUE;
362
0
                        poGeomFieldDefn->SetSpatialRef(GetSpatialRef());
363
0
                    }
364
0
                }
365
0
                else
366
0
                {
367
0
                    if (nIndex == 0 && nGeomFields == 1)
368
0
                    {
369
0
                        OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
370
0
                            cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
371
0
                                poFeatureDefn->GetGeomFieldDefn(0));
372
0
                        if (poGeomFieldDefn->bGeomTypeSet == FALSE)
373
0
                        {
374
0
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
375
0
                            poGeomFieldDefn->SetType(poSrcFieldDefn->GetType());
376
0
                        }
377
0
                        if (poGeomFieldDefn->bSRSSet == FALSE)
378
0
                        {
379
0
                            poGeomFieldDefn->bSRSSet = TRUE;
380
0
                            poGeomFieldDefn->SetSpatialRef(
381
0
                                poSrcFieldDefn->GetSpatialRef());
382
0
                        }
383
0
                    }
384
                    /* TODO: merge type, SRS, extent ? */
385
0
                }
386
0
            }
387
0
        }
388
0
    }
389
0
    else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS)
390
0
    {
391
0
        OGRFeatureDefn *poSrcFeatureDefn = m_apoSrcLayers[0]->GetLayerDefn();
392
0
        for (int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
393
0
            poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
394
0
        for (int i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
395
0
        {
396
0
            OGRGeomFieldDefn *poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
397
0
            poFeatureDefn->AddGeomFieldDefn(
398
0
                std::make_unique<OGRUnionLayerGeomFieldDefn>(poFldDefn));
399
0
        }
400
401
        /* Remove any field that is not found in the source layers */
402
0
        for (int iLayer = 1; iLayer < static_cast<int>(m_apoSrcLayers.size());
403
0
             iLayer++)
404
0
        {
405
0
            OGRFeatureDefn *l_poSrcFeatureDefn =
406
0
                m_apoSrcLayers[iLayer]->GetLayerDefn();
407
0
            for (int i = iCompareFirstIndex; i < poFeatureDefn->GetFieldCount();
408
                 // No increment.
409
0
            )
410
0
            {
411
0
                OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
412
0
                int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
413
0
                    poFieldDefn->GetNameRef());
414
0
                if (nSrcIndex < 0)
415
0
                {
416
0
                    poFeatureDefn->DeleteFieldDefn(i);
417
0
                }
418
0
                else
419
0
                {
420
0
                    OGRFieldDefn *poSrcFieldDefn =
421
0
                        l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
422
0
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
423
424
0
                    i++;
425
0
                }
426
0
            }
427
0
            for (int i = 0; i < poFeatureDefn->GetGeomFieldCount();
428
                 // No increment.
429
0
            )
430
0
            {
431
0
                OGRGeomFieldDefn *poFieldDefn =
432
0
                    poFeatureDefn->GetGeomFieldDefn(i);
433
0
                int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
434
0
                    poFieldDefn->GetNameRef());
435
0
                if (nSrcIndex < 0)
436
0
                {
437
0
                    poFeatureDefn->DeleteGeomFieldDefn(i);
438
0
                }
439
0
                else
440
0
                {
441
                    /* TODO: merge type, SRS, extent ? */
442
443
0
                    i++;
444
0
                }
445
0
            }
446
0
        }
447
0
    }
448
449
0
    return poFeatureDefn;
450
0
}
451
452
/************************************************************************/
453
/*                             GetGeomType()                            */
454
/************************************************************************/
455
456
OGRwkbGeometryType OGRUnionLayer::GetGeomType()
457
0
{
458
0
    if (nGeomFields < 0)
459
0
        return wkbNone;
460
0
    if (nGeomFields >= 1 && papoGeomFields[0]->bGeomTypeSet)
461
0
    {
462
0
        return papoGeomFields[0]->GetType();
463
0
    }
464
465
0
    return OGRLayer::GetGeomType();
466
0
}
467
468
/************************************************************************/
469
/*                    SetSpatialFilterToSourceLayer()                   */
470
/************************************************************************/
471
472
void OGRUnionLayer::SetSpatialFilterToSourceLayer(OGRLayer *poSrcLayer)
473
0
{
474
0
    if (m_iGeomFieldFilter >= 0 &&
475
0
        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
476
0
    {
477
0
        int iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
478
0
            GetLayerDefn()->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
479
0
        if (iSrcGeomField >= 0)
480
0
        {
481
0
            poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
482
0
        }
483
0
        else
484
0
        {
485
0
            poSrcLayer->SetSpatialFilter(nullptr);
486
0
        }
487
0
    }
488
0
    else
489
0
    {
490
0
        poSrcLayer->SetSpatialFilter(nullptr);
491
0
    }
492
0
}
493
494
/************************************************************************/
495
/*                        ConfigureActiveLayer()                        */
496
/************************************************************************/
497
498
void OGRUnionLayer::ConfigureActiveLayer()
499
0
{
500
0
    AutoWarpLayerIfNecessary(iCurLayer);
501
0
    ApplyAttributeFilterToSrcLayer(iCurLayer);
502
0
    SetSpatialFilterToSourceLayer(m_apoSrcLayers[iCurLayer].poLayer);
503
0
    m_apoSrcLayers[iCurLayer]->ResetReading();
504
505
    /* Establish map */
506
0
    GetLayerDefn();
507
0
    const OGRFeatureDefn *poSrcFeatureDefn =
508
0
        m_apoSrcLayers[iCurLayer]->GetLayerDefn();
509
0
    const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
510
0
    const int nDstFieldCount = poFeatureDefn->GetFieldCount();
511
512
0
    std::map<std::string, int> oMapDstFieldNameToIdx;
513
0
    for (int i = 0; i < nDstFieldCount; i++)
514
0
    {
515
0
        const OGRFieldDefn *poDstFieldDefn = poFeatureDefn->GetFieldDefn(i);
516
0
        oMapDstFieldNameToIdx[poDstFieldDefn->GetNameRef()] = i;
517
0
    }
518
519
0
    CPLFree(panMap);
520
0
    panMap = static_cast<int *>(CPLMalloc(nSrcFieldCount * sizeof(int)));
521
0
    for (int i = 0; i < nSrcFieldCount; i++)
522
0
    {
523
0
        const OGRFieldDefn *poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
524
0
        if (m_aosIgnoredFields.FindString(poSrcFieldDefn->GetNameRef()) == -1)
525
0
        {
526
0
            const auto oIter =
527
0
                oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
528
0
            panMap[i] =
529
0
                oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
530
0
        }
531
0
        else
532
0
        {
533
0
            panMap[i] = -1;
534
0
        }
535
0
    }
536
537
0
    if (m_apoSrcLayers[iCurLayer]->TestCapability(OLCIgnoreFields))
538
0
    {
539
0
        CPLStringList aosFieldSrc;
540
0
        for (const char *pszFieldName : cpl::Iterate(m_aosIgnoredFields))
541
0
        {
542
0
            if (EQUAL(pszFieldName, "OGR_GEOMETRY") ||
543
0
                EQUAL(pszFieldName, "OGR_STYLE") ||
544
0
                poSrcFeatureDefn->GetFieldIndex(pszFieldName) >= 0 ||
545
0
                poSrcFeatureDefn->GetGeomFieldIndex(pszFieldName) >= 0)
546
0
            {
547
0
                aosFieldSrc.AddString(pszFieldName);
548
0
            }
549
0
        }
550
551
0
        std::map<std::string, int> oMapSrcFieldNameToIdx;
552
0
        for (int i = 0; i < nSrcFieldCount; i++)
553
0
        {
554
0
            const OGRFieldDefn *poSrcFieldDefn =
555
0
                poSrcFeatureDefn->GetFieldDefn(i);
556
0
            oMapSrcFieldNameToIdx[poSrcFieldDefn->GetNameRef()] = i;
557
0
        }
558
559
        /* Attribute fields */
560
0
        std::vector<bool> abSrcFieldsUsed(nSrcFieldCount);
561
0
        for (int iField = 0; iField < nDstFieldCount; iField++)
562
0
        {
563
0
            const OGRFieldDefn *poFieldDefn =
564
0
                poFeatureDefn->GetFieldDefn(iField);
565
0
            const auto oIter =
566
0
                oMapSrcFieldNameToIdx.find(poFieldDefn->GetNameRef());
567
0
            const int iSrcField =
568
0
                oIter == oMapSrcFieldNameToIdx.end() ? -1 : oIter->second;
569
0
            if (iSrcField >= 0)
570
0
                abSrcFieldsUsed[iSrcField] = true;
571
0
        }
572
0
        for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
573
0
        {
574
0
            if (!abSrcFieldsUsed[iSrcField])
575
0
            {
576
0
                const OGRFieldDefn *poSrcDefn =
577
0
                    poSrcFeatureDefn->GetFieldDefn(iSrcField);
578
0
                aosFieldSrc.AddString(poSrcDefn->GetNameRef());
579
0
            }
580
0
        }
581
582
        /* geometry fields now */
583
0
        abSrcFieldsUsed.clear();
584
0
        abSrcFieldsUsed.resize(poSrcFeatureDefn->GetGeomFieldCount());
585
0
        for (int iField = 0; iField < poFeatureDefn->GetGeomFieldCount();
586
0
             iField++)
587
0
        {
588
0
            const OGRGeomFieldDefn *poFieldDefn =
589
0
                poFeatureDefn->GetGeomFieldDefn(iField);
590
0
            const int iSrcField =
591
0
                poSrcFeatureDefn->GetGeomFieldIndex(poFieldDefn->GetNameRef());
592
0
            if (iSrcField >= 0)
593
0
                abSrcFieldsUsed[iSrcField] = true;
594
0
        }
595
0
        for (int iSrcField = 0;
596
0
             iSrcField < poSrcFeatureDefn->GetGeomFieldCount(); iSrcField++)
597
0
        {
598
0
            if (!abSrcFieldsUsed[iSrcField])
599
0
            {
600
0
                const OGRGeomFieldDefn *poSrcDefn =
601
0
                    poSrcFeatureDefn->GetGeomFieldDefn(iSrcField);
602
0
                aosFieldSrc.AddString(poSrcDefn->GetNameRef());
603
0
            }
604
0
        }
605
606
0
        m_apoSrcLayers[iCurLayer]->SetIgnoredFields(aosFieldSrc.List());
607
0
    }
608
0
}
609
610
/************************************************************************/
611
/*                             ResetReading()                           */
612
/************************************************************************/
613
614
void OGRUnionLayer::ResetReading()
615
0
{
616
0
    iCurLayer = 0;
617
0
    ConfigureActiveLayer();
618
0
    nNextFID = 0;
619
0
}
620
621
/************************************************************************/
622
/*                         AutoWarpLayerIfNecessary()                   */
623
/************************************************************************/
624
625
void OGRUnionLayer::AutoWarpLayerIfNecessary(int iLayer)
626
0
{
627
0
    if (!m_apoSrcLayers[iLayer].bCheckIfAutoWrap)
628
0
    {
629
0
        m_apoSrcLayers[iLayer].bCheckIfAutoWrap = true;
630
631
0
        for (int iField = 0; iField < GetLayerDefn()->GetGeomFieldCount();
632
0
             iField++)
633
0
        {
634
0
            const OGRSpatialReference *poSRS =
635
0
                GetLayerDefn()->GetGeomFieldDefn(iField)->GetSpatialRef();
636
637
0
            OGRFeatureDefn *poSrcFeatureDefn =
638
0
                m_apoSrcLayers[iLayer]->GetLayerDefn();
639
0
            int iSrcGeomField = poSrcFeatureDefn->GetGeomFieldIndex(
640
0
                GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef());
641
0
            if (iSrcGeomField >= 0)
642
0
            {
643
0
                const OGRSpatialReference *poSRS2 =
644
0
                    poSrcFeatureDefn->GetGeomFieldDefn(iSrcGeomField)
645
0
                        ->GetSpatialRef();
646
647
0
                if ((poSRS == nullptr && poSRS2 != nullptr) ||
648
0
                    (poSRS != nullptr && poSRS2 == nullptr))
649
0
                {
650
0
                    CPLError(
651
0
                        CE_Warning, CPLE_AppDefined,
652
0
                        "SRS of geometry field '%s' layer %s not "
653
0
                        "consistent with UnionLayer SRS",
654
0
                        GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef(),
655
0
                        m_apoSrcLayers[iLayer]->GetName());
656
0
                }
657
0
                else if (poSRS != nullptr && poSRS2 != nullptr &&
658
0
                         poSRS != poSRS2 && !poSRS->IsSame(poSRS2))
659
0
                {
660
0
                    CPLDebug(
661
0
                        "VRT",
662
0
                        "SRS of geometry field '%s' layer %s not "
663
0
                        "consistent with UnionLayer SRS. "
664
0
                        "Trying auto warping",
665
0
                        GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef(),
666
0
                        m_apoSrcLayers[iLayer]->GetName());
667
0
                    std::unique_ptr<OGRCoordinateTransformation> poCT(
668
0
                        OGRCreateCoordinateTransformation(poSRS2, poSRS));
669
0
                    std::unique_ptr<OGRCoordinateTransformation> poReversedCT(
670
0
                        (poCT != nullptr) ? poCT->GetInverse() : nullptr);
671
0
                    if (poReversedCT != nullptr)
672
0
                    {
673
0
                        auto [poSrcLayer, bOwned] =
674
0
                            m_apoSrcLayers[iLayer].release();
675
0
                        m_apoSrcLayers[iLayer].reset(
676
0
                            std::make_unique<OGRWarpedLayer>(
677
0
                                poSrcLayer, iSrcGeomField, bOwned,
678
0
                                poCT.release(), poReversedCT.release()));
679
0
                    }
680
0
                    else
681
0
                    {
682
0
                        CPLError(CE_Warning, CPLE_AppDefined,
683
0
                                 "AutoWarpLayerIfNecessary failed to create "
684
0
                                 "poCT or poReversedCT.");
685
0
                    }
686
0
                }
687
0
            }
688
0
        }
689
0
    }
690
0
}
691
692
/************************************************************************/
693
/*                           GetNextFeature()                           */
694
/************************************************************************/
695
696
OGRFeature *OGRUnionLayer::GetNextFeature()
697
0
{
698
0
    if (poFeatureDefn == nullptr)
699
0
        GetLayerDefn();
700
0
    if (iCurLayer < 0)
701
0
        ResetReading();
702
703
0
    if (iCurLayer == static_cast<int>(m_apoSrcLayers.size()))
704
0
        return nullptr;
705
706
0
    while (true)
707
0
    {
708
0
        OGRFeature *poSrcFeature = m_apoSrcLayers[iCurLayer]->GetNextFeature();
709
0
        if (poSrcFeature == nullptr)
710
0
        {
711
0
            iCurLayer++;
712
0
            if (iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
713
0
            {
714
0
                ConfigureActiveLayer();
715
0
                continue;
716
0
            }
717
0
            else
718
0
                break;
719
0
        }
720
721
0
        OGRFeature *poFeature = TranslateFromSrcLayer(poSrcFeature);
722
0
        delete poSrcFeature;
723
724
0
        if ((m_poFilterGeom == nullptr ||
725
0
             FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
726
0
            (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
727
0
        {
728
0
            return poFeature;
729
0
        }
730
731
0
        delete poFeature;
732
0
    }
733
0
    return nullptr;
734
0
}
735
736
/************************************************************************/
737
/*                             GetFeature()                             */
738
/************************************************************************/
739
740
OGRFeature *OGRUnionLayer::GetFeature(GIntBig nFeatureId)
741
0
{
742
0
    OGRFeature *poFeature = nullptr;
743
744
0
    if (!bPreserveSrcFID)
745
0
    {
746
0
        poFeature = OGRLayer::GetFeature(nFeatureId);
747
0
    }
748
0
    else
749
0
    {
750
0
        int iGeomFieldFilterSave = m_iGeomFieldFilter;
751
0
        OGRGeometry *poGeomSave = m_poFilterGeom;
752
0
        m_poFilterGeom = nullptr;
753
0
        SetSpatialFilter(nullptr);
754
755
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
756
0
        {
757
0
            iCurLayer = i;
758
0
            ConfigureActiveLayer();
759
760
0
            OGRFeature *poSrcFeature =
761
0
                m_apoSrcLayers[i]->GetFeature(nFeatureId);
762
0
            if (poSrcFeature != nullptr)
763
0
            {
764
0
                poFeature = TranslateFromSrcLayer(poSrcFeature);
765
0
                delete poSrcFeature;
766
767
0
                break;
768
0
            }
769
0
        }
770
771
0
        SetSpatialFilter(iGeomFieldFilterSave, poGeomSave);
772
0
        delete poGeomSave;
773
774
0
        ResetReading();
775
0
    }
776
777
0
    return poFeature;
778
0
}
779
780
/************************************************************************/
781
/*                          ICreateFeature()                             */
782
/************************************************************************/
783
784
OGRErr OGRUnionLayer::ICreateFeature(OGRFeature *poFeature)
785
0
{
786
0
    if (osSourceLayerFieldName.empty())
787
0
    {
788
0
        CPLError(CE_Failure, CPLE_NotSupported,
789
0
                 "CreateFeature() not supported when SourceLayerFieldName is "
790
0
                 "not set");
791
0
        return OGRERR_FAILURE;
792
0
    }
793
794
0
    if (poFeature->GetFID() != OGRNullFID)
795
0
    {
796
0
        CPLError(CE_Failure, CPLE_NotSupported,
797
0
                 "CreateFeature() not supported when FID is set");
798
0
        return OGRERR_FAILURE;
799
0
    }
800
801
0
    if (!poFeature->IsFieldSetAndNotNull(0))
802
0
    {
803
0
        CPLError(CE_Failure, CPLE_NotSupported,
804
0
                 "CreateFeature() not supported when '%s' field is not set",
805
0
                 osSourceLayerFieldName.c_str());
806
0
        return OGRERR_FAILURE;
807
0
    }
808
809
0
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
810
0
    for (auto &oLayer : m_apoSrcLayers)
811
0
    {
812
0
        if (strcmp(pszSrcLayerName, oLayer->GetName()) == 0)
813
0
        {
814
0
            oLayer.bModified = true;
815
816
0
            OGRFeature *poSrcFeature = new OGRFeature(oLayer->GetLayerDefn());
817
0
            poSrcFeature->SetFrom(poFeature, TRUE);
818
0
            OGRErr eErr = oLayer->CreateFeature(poSrcFeature);
819
0
            if (eErr == OGRERR_NONE)
820
0
                poFeature->SetFID(poSrcFeature->GetFID());
821
0
            delete poSrcFeature;
822
0
            return eErr;
823
0
        }
824
0
    }
825
826
0
    CPLError(CE_Failure, CPLE_NotSupported,
827
0
             "CreateFeature() not supported : '%s' source layer does not exist",
828
0
             pszSrcLayerName);
829
0
    return OGRERR_FAILURE;
830
0
}
831
832
/************************************************************************/
833
/*                             ISetFeature()                             */
834
/************************************************************************/
835
836
OGRErr OGRUnionLayer::ISetFeature(OGRFeature *poFeature)
837
0
{
838
0
    if (!bPreserveSrcFID)
839
0
    {
840
0
        CPLError(CE_Failure, CPLE_NotSupported,
841
0
                 "SetFeature() not supported when PreserveSrcFID is OFF");
842
0
        return OGRERR_FAILURE;
843
0
    }
844
845
0
    if (osSourceLayerFieldName.empty())
846
0
    {
847
0
        CPLError(
848
0
            CE_Failure, CPLE_NotSupported,
849
0
            "SetFeature() not supported when SourceLayerFieldName is not set");
850
0
        return OGRERR_FAILURE;
851
0
    }
852
853
0
    if (poFeature->GetFID() == OGRNullFID)
854
0
    {
855
0
        CPLError(CE_Failure, CPLE_NotSupported,
856
0
                 "SetFeature() not supported when FID is not set");
857
0
        return OGRERR_FAILURE;
858
0
    }
859
860
0
    if (!poFeature->IsFieldSetAndNotNull(0))
861
0
    {
862
0
        CPLError(CE_Failure, CPLE_NotSupported,
863
0
                 "SetFeature() not supported when '%s' field is not set",
864
0
                 osSourceLayerFieldName.c_str());
865
0
        return OGRERR_FAILURE;
866
0
    }
867
868
0
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
869
0
    for (auto &oLayer : m_apoSrcLayers)
870
0
    {
871
0
        if (strcmp(pszSrcLayerName, oLayer->GetName()) == 0)
872
0
        {
873
0
            oLayer.bModified = true;
874
875
0
            OGRFeature *poSrcFeature = new OGRFeature(oLayer->GetLayerDefn());
876
0
            poSrcFeature->SetFrom(poFeature, TRUE);
877
0
            poSrcFeature->SetFID(poFeature->GetFID());
878
0
            OGRErr eErr = oLayer->SetFeature(poSrcFeature);
879
0
            delete poSrcFeature;
880
0
            return eErr;
881
0
        }
882
0
    }
883
884
0
    CPLError(CE_Failure, CPLE_NotSupported,
885
0
             "SetFeature() not supported : '%s' source layer does not exist",
886
0
             pszSrcLayerName);
887
0
    return OGRERR_FAILURE;
888
0
}
889
890
/************************************************************************/
891
/*                          IUpsertFeature()                            */
892
/************************************************************************/
893
894
OGRErr OGRUnionLayer::IUpsertFeature(OGRFeature *poFeature)
895
0
{
896
0
    if (GetFeature(poFeature->GetFID()))
897
0
    {
898
0
        return ISetFeature(poFeature);
899
0
    }
900
0
    else
901
0
    {
902
0
        return ICreateFeature(poFeature);
903
0
    }
904
0
}
905
906
/************************************************************************/
907
/*                           IUpdateFeature()                           */
908
/************************************************************************/
909
910
OGRErr OGRUnionLayer::IUpdateFeature(OGRFeature *poFeature,
911
                                     int nUpdatedFieldsCount,
912
                                     const int *panUpdatedFieldsIdx,
913
                                     int nUpdatedGeomFieldsCount,
914
                                     const int *panUpdatedGeomFieldsIdx,
915
                                     bool bUpdateStyleString)
916
0
{
917
0
    if (!bPreserveSrcFID)
918
0
    {
919
0
        CPLError(CE_Failure, CPLE_NotSupported,
920
0
                 "UpdateFeature() not supported when PreserveSrcFID is OFF");
921
0
        return OGRERR_FAILURE;
922
0
    }
923
924
0
    if (osSourceLayerFieldName.empty())
925
0
    {
926
0
        CPLError(CE_Failure, CPLE_NotSupported,
927
0
                 "UpdateFeature() not supported when SourceLayerFieldName is "
928
0
                 "not set");
929
0
        return OGRERR_FAILURE;
930
0
    }
931
932
0
    if (poFeature->GetFID() == OGRNullFID)
933
0
    {
934
0
        CPLError(CE_Failure, CPLE_NotSupported,
935
0
                 "UpdateFeature() not supported when FID is not set");
936
0
        return OGRERR_FAILURE;
937
0
    }
938
939
0
    if (!poFeature->IsFieldSetAndNotNull(0))
940
0
    {
941
0
        CPLError(CE_Failure, CPLE_NotSupported,
942
0
                 "UpdateFeature() not supported when '%s' field is not set",
943
0
                 osSourceLayerFieldName.c_str());
944
0
        return OGRERR_FAILURE;
945
0
    }
946
947
0
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
948
0
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
949
0
    {
950
0
        if (strcmp(pszSrcLayerName, m_apoSrcLayers[i]->GetName()) == 0)
951
0
        {
952
0
            m_apoSrcLayers[i].bModified = true;
953
954
0
            const auto poSrcLayerDefn = m_apoSrcLayers[i]->GetLayerDefn();
955
0
            OGRFeature *poSrcFeature = new OGRFeature(poSrcLayerDefn);
956
0
            poSrcFeature->SetFrom(poFeature, TRUE);
957
0
            poSrcFeature->SetFID(poFeature->GetFID());
958
959
            // We could potentially have a pre-computed map from indices in
960
            // poLayerDefn to indices in poSrcLayerDefn
961
0
            std::vector<int> anSrcUpdatedFieldIdx;
962
0
            const auto poLayerDefn = GetLayerDefn();
963
0
            for (int j = 0; j < nUpdatedFieldsCount; ++j)
964
0
            {
965
0
                if (panUpdatedFieldsIdx[j] != 0)
966
0
                {
967
0
                    const int nNewIdx = poSrcLayerDefn->GetFieldIndex(
968
0
                        poLayerDefn->GetFieldDefn(panUpdatedFieldsIdx[j])
969
0
                            ->GetNameRef());
970
0
                    if (nNewIdx >= 0)
971
0
                    {
972
0
                        anSrcUpdatedFieldIdx.push_back(nNewIdx);
973
0
                    }
974
0
                }
975
0
            }
976
0
            std::vector<int> anSrcUpdatedGeomFieldIdx;
977
0
            for (int j = 0; j < nUpdatedGeomFieldsCount; ++j)
978
0
            {
979
0
                if (panUpdatedGeomFieldsIdx[j] != 0)
980
0
                {
981
0
                    const int nNewIdx = poSrcLayerDefn->GetGeomFieldIndex(
982
0
                        poLayerDefn
983
0
                            ->GetGeomFieldDefn(panUpdatedGeomFieldsIdx[j])
984
0
                            ->GetNameRef());
985
0
                    if (nNewIdx >= 0)
986
0
                    {
987
0
                        anSrcUpdatedGeomFieldIdx.push_back(nNewIdx);
988
0
                    }
989
0
                }
990
0
            }
991
992
0
            OGRErr eErr = m_apoSrcLayers[i]->UpdateFeature(
993
0
                poSrcFeature, static_cast<int>(anSrcUpdatedFieldIdx.size()),
994
0
                anSrcUpdatedFieldIdx.data(),
995
0
                static_cast<int>(anSrcUpdatedGeomFieldIdx.size()),
996
0
                anSrcUpdatedGeomFieldIdx.data(), bUpdateStyleString);
997
0
            delete poSrcFeature;
998
0
            return eErr;
999
0
        }
1000
0
    }
1001
1002
0
    CPLError(CE_Failure, CPLE_NotSupported,
1003
0
             "UpdateFeature() not supported : '%s' source layer does not exist",
1004
0
             pszSrcLayerName);
1005
0
    return OGRERR_FAILURE;
1006
0
}
1007
1008
/************************************************************************/
1009
/*                           GetSpatialRef()                            */
1010
/************************************************************************/
1011
1012
OGRSpatialReference *OGRUnionLayer::GetSpatialRef()
1013
0
{
1014
0
    if (nGeomFields < 0)
1015
0
        return nullptr;
1016
0
    if (nGeomFields >= 1 && papoGeomFields[0]->bSRSSet)
1017
0
        return const_cast<OGRSpatialReference *>(
1018
0
            papoGeomFields[0]->GetSpatialRef());
1019
1020
0
    if (poGlobalSRS == nullptr)
1021
0
    {
1022
0
        poGlobalSRS = m_apoSrcLayers[0]->GetSpatialRef();
1023
0
        if (poGlobalSRS != nullptr)
1024
0
            const_cast<OGRSpatialReference *>(poGlobalSRS)->Reference();
1025
0
    }
1026
0
    return const_cast<OGRSpatialReference *>(poGlobalSRS);
1027
0
}
1028
1029
/************************************************************************/
1030
/*                      GetAttrFilterPassThroughValue()                 */
1031
/************************************************************************/
1032
1033
int OGRUnionLayer::GetAttrFilterPassThroughValue()
1034
0
{
1035
0
    if (m_poAttrQuery == nullptr)
1036
0
        return TRUE;
1037
1038
0
    if (bAttrFilterPassThroughValue >= 0)
1039
0
        return bAttrFilterPassThroughValue;
1040
1041
0
    char **papszUsedFields = m_poAttrQuery->GetUsedFields();
1042
0
    int bRet = TRUE;
1043
1044
0
    for (auto &oLayer : m_apoSrcLayers)
1045
0
    {
1046
0
        OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
1047
0
        char **papszIter = papszUsedFields;
1048
0
        while (papszIter != nullptr && *papszIter != nullptr)
1049
0
        {
1050
0
            int bIsSpecial = FALSE;
1051
0
            for (int i = 0; i < SPECIAL_FIELD_COUNT; i++)
1052
0
            {
1053
0
                if (EQUAL(*papszIter, SpecialFieldNames[i]))
1054
0
                {
1055
0
                    bIsSpecial = TRUE;
1056
0
                    break;
1057
0
                }
1058
0
            }
1059
0
            if (!bIsSpecial && poSrcFeatureDefn->GetFieldIndex(*papszIter) < 0)
1060
0
            {
1061
0
                bRet = FALSE;
1062
0
                break;
1063
0
            }
1064
0
            papszIter++;
1065
0
        }
1066
0
    }
1067
1068
0
    CSLDestroy(papszUsedFields);
1069
1070
0
    bAttrFilterPassThroughValue = bRet;
1071
1072
0
    return bRet;
1073
0
}
1074
1075
/************************************************************************/
1076
/*                  ApplyAttributeFilterToSrcLayer()                    */
1077
/************************************************************************/
1078
1079
void OGRUnionLayer::ApplyAttributeFilterToSrcLayer(int iSubLayer)
1080
0
{
1081
0
    CPLAssert(iSubLayer >= 0 &&
1082
0
              iSubLayer < static_cast<int>(m_apoSrcLayers.size()));
1083
1084
0
    if (GetAttrFilterPassThroughValue())
1085
0
        m_apoSrcLayers[iSubLayer]->SetAttributeFilter(pszAttributeFilter);
1086
0
    else
1087
0
        m_apoSrcLayers[iSubLayer]->SetAttributeFilter(nullptr);
1088
0
}
1089
1090
/************************************************************************/
1091
/*                          GetFeatureCount()                           */
1092
/************************************************************************/
1093
1094
GIntBig OGRUnionLayer::GetFeatureCount(int bForce)
1095
0
{
1096
0
    if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
1097
0
        m_poAttrQuery == nullptr)
1098
0
    {
1099
0
        return nFeatureCount;
1100
0
    }
1101
1102
0
    if (!GetAttrFilterPassThroughValue())
1103
0
        return OGRLayer::GetFeatureCount(bForce);
1104
1105
0
    GIntBig nRet = 0;
1106
0
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1107
0
    {
1108
0
        AutoWarpLayerIfNecessary(i);
1109
0
        ApplyAttributeFilterToSrcLayer(i);
1110
0
        SetSpatialFilterToSourceLayer(m_apoSrcLayers[i].poLayer);
1111
0
        const GIntBig nThisLayerFC = m_apoSrcLayers[i]->GetFeatureCount(bForce);
1112
0
        if (nThisLayerFC < 0 ||
1113
0
            nThisLayerFC > std::numeric_limits<GIntBig>::max() - nRet)
1114
0
            return 0;
1115
0
        nRet += nThisLayerFC;
1116
0
    }
1117
0
    ResetReading();
1118
0
    return nRet;
1119
0
}
1120
1121
/************************************************************************/
1122
/*                         SetAttributeFilter()                         */
1123
/************************************************************************/
1124
1125
OGRErr OGRUnionLayer::SetAttributeFilter(const char *pszAttributeFilterIn)
1126
0
{
1127
0
    if (pszAttributeFilterIn == nullptr && pszAttributeFilter == nullptr)
1128
0
        return OGRERR_NONE;
1129
0
    if (pszAttributeFilterIn != nullptr && pszAttributeFilter != nullptr &&
1130
0
        strcmp(pszAttributeFilterIn, pszAttributeFilter) == 0)
1131
0
        return OGRERR_NONE;
1132
1133
0
    if (poFeatureDefn == nullptr)
1134
0
        GetLayerDefn();
1135
1136
0
    bAttrFilterPassThroughValue = -1;
1137
1138
0
    OGRErr eErr = OGRLayer::SetAttributeFilter(pszAttributeFilterIn);
1139
0
    if (eErr != OGRERR_NONE)
1140
0
        return eErr;
1141
1142
0
    CPLFree(pszAttributeFilter);
1143
0
    pszAttributeFilter =
1144
0
        pszAttributeFilterIn ? CPLStrdup(pszAttributeFilterIn) : nullptr;
1145
1146
0
    if (iCurLayer >= 0 && iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
1147
0
        ApplyAttributeFilterToSrcLayer(iCurLayer);
1148
1149
0
    return OGRERR_NONE;
1150
0
}
1151
1152
/************************************************************************/
1153
/*                           TestCapability()                           */
1154
/************************************************************************/
1155
1156
int OGRUnionLayer::TestCapability(const char *pszCap)
1157
0
{
1158
0
    if (EQUAL(pszCap, OLCFastFeatureCount))
1159
0
    {
1160
0
        if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
1161
0
            m_poAttrQuery == nullptr)
1162
0
            return TRUE;
1163
1164
0
        if (!GetAttrFilterPassThroughValue())
1165
0
            return FALSE;
1166
1167
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1168
0
        {
1169
0
            AutoWarpLayerIfNecessary(i);
1170
0
            ApplyAttributeFilterToSrcLayer(i);
1171
0
            SetSpatialFilterToSourceLayer(m_apoSrcLayers[i].poLayer);
1172
0
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
1173
0
                return FALSE;
1174
0
        }
1175
0
        return TRUE;
1176
0
    }
1177
1178
0
    if (EQUAL(pszCap, OLCFastGetExtent))
1179
0
    {
1180
0
        if (nGeomFields >= 1 && papoGeomFields[0]->sStaticEnvelope.IsInit())
1181
0
            return TRUE;
1182
1183
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1184
0
        {
1185
0
            AutoWarpLayerIfNecessary(i);
1186
0
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
1187
0
                return FALSE;
1188
0
        }
1189
0
        return TRUE;
1190
0
    }
1191
1192
0
    if (EQUAL(pszCap, OLCFastSpatialFilter))
1193
0
    {
1194
0
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1195
0
        {
1196
0
            AutoWarpLayerIfNecessary(i);
1197
0
            ApplyAttributeFilterToSrcLayer(i);
1198
0
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
1199
0
                return FALSE;
1200
0
        }
1201
0
        return TRUE;
1202
0
    }
1203
1204
0
    if (EQUAL(pszCap, OLCStringsAsUTF8))
1205
0
    {
1206
0
        for (auto &oLayer : m_apoSrcLayers)
1207
0
        {
1208
0
            if (!oLayer->TestCapability(pszCap))
1209
0
                return FALSE;
1210
0
        }
1211
0
        return TRUE;
1212
0
    }
1213
1214
0
    if (EQUAL(pszCap, OLCRandomRead))
1215
0
    {
1216
0
        if (!bPreserveSrcFID)
1217
0
            return FALSE;
1218
1219
0
        for (auto &oLayer : m_apoSrcLayers)
1220
0
        {
1221
0
            if (!oLayer->TestCapability(pszCap))
1222
0
                return FALSE;
1223
0
        }
1224
0
        return TRUE;
1225
0
    }
1226
1227
0
    if (EQUAL(pszCap, OLCRandomWrite))
1228
0
    {
1229
0
        if (!bPreserveSrcFID || osSourceLayerFieldName.empty())
1230
0
            return FALSE;
1231
1232
0
        for (auto &oLayer : m_apoSrcLayers)
1233
0
        {
1234
0
            if (!oLayer->TestCapability(pszCap))
1235
0
                return FALSE;
1236
0
        }
1237
0
        return TRUE;
1238
0
    }
1239
1240
0
    if (EQUAL(pszCap, OLCSequentialWrite))
1241
0
    {
1242
0
        if (osSourceLayerFieldName.empty())
1243
0
            return FALSE;
1244
1245
0
        for (auto &oLayer : m_apoSrcLayers)
1246
0
        {
1247
0
            if (!oLayer->TestCapability(pszCap))
1248
0
                return FALSE;
1249
0
        }
1250
0
        return TRUE;
1251
0
    }
1252
1253
0
    if (EQUAL(pszCap, OLCIgnoreFields))
1254
0
        return TRUE;
1255
1256
0
    if (EQUAL(pszCap, OLCCurveGeometries))
1257
0
        return TRUE;
1258
1259
0
    return FALSE;
1260
0
}
1261
1262
/************************************************************************/
1263
/*                             IGetExtent()                             */
1264
/************************************************************************/
1265
1266
OGRErr OGRUnionLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
1267
                                 bool bForce)
1268
0
{
1269
0
    if (iGeomField >= 0 && iGeomField < nGeomFields &&
1270
0
        papoGeomFields[iGeomField]->sStaticEnvelope.IsInit())
1271
0
    {
1272
0
        *psExtent = papoGeomFields[iGeomField]->sStaticEnvelope;
1273
0
        return OGRERR_NONE;
1274
0
    }
1275
1276
0
    if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount())
1277
0
    {
1278
0
        if (iGeomField != 0)
1279
0
        {
1280
0
            CPLError(CE_Failure, CPLE_AppDefined,
1281
0
                     "Invalid geometry field index : %d", iGeomField);
1282
0
        }
1283
0
        return OGRERR_FAILURE;
1284
0
    }
1285
1286
0
    int bInit = FALSE;
1287
0
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
1288
0
    {
1289
0
        AutoWarpLayerIfNecessary(i);
1290
0
        int iSrcGeomField =
1291
0
            m_apoSrcLayers[i]->GetLayerDefn()->GetGeomFieldIndex(
1292
0
                GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetNameRef());
1293
0
        if (iSrcGeomField >= 0)
1294
0
        {
1295
0
            if (!bInit)
1296
0
            {
1297
0
                if (m_apoSrcLayers[i]->GetExtent(iSrcGeomField, psExtent,
1298
0
                                                 bForce) == OGRERR_NONE)
1299
0
                    bInit = TRUE;
1300
0
            }
1301
0
            else
1302
0
            {
1303
0
                OGREnvelope sExtent;
1304
0
                if (m_apoSrcLayers[i]->GetExtent(iSrcGeomField, &sExtent,
1305
0
                                                 bForce) == OGRERR_NONE)
1306
0
                {
1307
0
                    psExtent->Merge(sExtent);
1308
0
                }
1309
0
            }
1310
0
        }
1311
0
    }
1312
0
    return (bInit) ? OGRERR_NONE : OGRERR_FAILURE;
1313
0
}
1314
1315
/************************************************************************/
1316
/*                        ISetSpatialFilter()                           */
1317
/************************************************************************/
1318
1319
OGRErr OGRUnionLayer::ISetSpatialFilter(int iGeomField,
1320
                                        const OGRGeometry *poGeom)
1321
0
{
1322
0
    m_iGeomFieldFilter = iGeomField;
1323
0
    if (InstallFilter(poGeom))
1324
0
        ResetReading();
1325
1326
0
    if (iCurLayer >= 0 && iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
1327
0
    {
1328
0
        SetSpatialFilterToSourceLayer(m_apoSrcLayers[iCurLayer].poLayer);
1329
0
    }
1330
1331
0
    return OGRERR_NONE;
1332
0
}
1333
1334
/************************************************************************/
1335
/*                        TranslateFromSrcLayer()                       */
1336
/************************************************************************/
1337
1338
OGRFeature *OGRUnionLayer::TranslateFromSrcLayer(OGRFeature *poSrcFeature)
1339
0
{
1340
0
    CPLAssert(poSrcFeature->GetFieldCount() == 0 || panMap != nullptr);
1341
0
    CPLAssert(iCurLayer >= 0 &&
1342
0
              iCurLayer < static_cast<int>(m_apoSrcLayers.size()));
1343
1344
0
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1345
0
    poFeature->SetFrom(poSrcFeature, panMap, TRUE);
1346
1347
0
    if (!osSourceLayerFieldName.empty() &&
1348
0
        !poFeatureDefn->GetFieldDefn(0)->IsIgnored())
1349
0
    {
1350
0
        poFeature->SetField(0, m_apoSrcLayers[iCurLayer]->GetName());
1351
0
    }
1352
1353
0
    for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1354
0
    {
1355
0
        if (poFeatureDefn->GetGeomFieldDefn(i)->IsIgnored())
1356
0
            poFeature->SetGeomFieldDirectly(i, nullptr);
1357
0
        else
1358
0
        {
1359
0
            OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
1360
0
            if (poGeom != nullptr)
1361
0
            {
1362
0
                poGeom->assignSpatialReference(
1363
0
                    poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
1364
0
            }
1365
0
        }
1366
0
    }
1367
1368
0
    if (bPreserveSrcFID)
1369
0
        poFeature->SetFID(poSrcFeature->GetFID());
1370
0
    else
1371
0
        poFeature->SetFID(nNextFID++);
1372
0
    return poFeature;
1373
0
}
1374
1375
/************************************************************************/
1376
/*                          SetIgnoredFields()                          */
1377
/************************************************************************/
1378
1379
OGRErr OGRUnionLayer::SetIgnoredFields(CSLConstList papszFields)
1380
0
{
1381
0
    OGRErr eErr = OGRLayer::SetIgnoredFields(papszFields);
1382
0
    if (eErr != OGRERR_NONE)
1383
0
        return eErr;
1384
1385
0
    m_aosIgnoredFields = papszFields;
1386
1387
0
    return eErr;
1388
0
}
1389
1390
/************************************************************************/
1391
/*                             SyncToDisk()                             */
1392
/************************************************************************/
1393
1394
OGRErr OGRUnionLayer::SyncToDisk()
1395
0
{
1396
0
    for (auto &oLayer : m_apoSrcLayers)
1397
0
    {
1398
0
        if (oLayer.bModified)
1399
0
        {
1400
0
            oLayer->SyncToDisk();
1401
0
            oLayer.bModified = false;
1402
0
        }
1403
0
    }
1404
1405
0
    return OGRERR_NONE;
1406
0
}
1407
1408
#endif /* #ifndef DOXYGEN_SKIP */