• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 14784588603

01 May 2025 10:21PM UTC coverage: 70.78% (+0.003%) from 70.777%
14784588603

Pull #12246

github

web-flow
Merge ca591d9cb into 7f3406edd
Pull Request #12246: gdal vector concat: fix memleak

102 of 114 new or added lines in 2 files covered. (89.47%)

59 existing lines in 27 files now uncovered.

563062 of 795511 relevant lines covered (70.78%)

222874.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.63
/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
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
/************************************************************************/
20
/*                      OGRUnionLayerGeomFieldDefn()                    */
21
/************************************************************************/
22

23
OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(const char *pszNameIn,
21✔
24
                                                       OGRwkbGeometryType eType)
21✔
25
    : OGRGeomFieldDefn(pszNameIn, eType)
21✔
26
{
27
}
21✔
28

29
/************************************************************************/
30
/*                      OGRUnionLayerGeomFieldDefn()                    */
31
/************************************************************************/
32

33
OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
115✔
34
    const OGRGeomFieldDefn *poSrc)
115✔
35
    : OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType())
115✔
36
{
37
    SetSpatialRef(poSrc->GetSpatialRef());
115✔
38
}
115✔
39

40
/************************************************************************/
41
/*                      OGRUnionLayerGeomFieldDefn()                    */
42
/************************************************************************/
43

44
OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
31✔
45
    const OGRUnionLayerGeomFieldDefn *poSrc)
31✔
46
    : OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType()),
47
      bGeomTypeSet(poSrc->bGeomTypeSet), bSRSSet(poSrc->bSRSSet)
31✔
48
{
49
    SetSpatialRef(poSrc->GetSpatialRef());
31✔
50
    sStaticEnvelope = poSrc->sStaticEnvelope;
31✔
51
}
31✔
52

53
/************************************************************************/
54
/*                     ~OGRUnionLayerGeomFieldDefn()                    */
55
/************************************************************************/
56

57
OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn()
334✔
58
{
59
}
334✔
60

61
/************************************************************************/
62
/*                          OGRUnionLayer()                             */
63
/************************************************************************/
64

65
// cppcheck-suppress uninitMemberVar
66
OGRUnionLayer::OGRUnionLayer(const char *pszName, int nSrcLayersIn,
122✔
67
                             OGRLayer **papoSrcLayersIn,
68
                             int bTakeLayerOwnership)
122✔
69
    : osName(pszName)
122✔
70
{
71
    CPLAssert(nSrcLayersIn > 0);
122✔
72

73
    SetDescription(pszName);
122✔
74

75
    for (int i = 0; i < nSrcLayersIn; ++i)
342✔
76
    {
77
        m_apoSrcLayers.emplace_back(papoSrcLayersIn[i],
220✔
78
                                    CPL_TO_BOOL(bTakeLayerOwnership));
220✔
79
    }
80
    CPLFree(papoSrcLayersIn);
122✔
81
}
122✔
82

83
/************************************************************************/
84
/*                         ~OGRUnionLayer()                             */
85
/************************************************************************/
86

87
OGRUnionLayer::~OGRUnionLayer()
244✔
88
{
89
    m_apoSrcLayers.clear();
122✔
90

91
    for (int i = 0; i < nFields; i++)
154✔
92
        delete papoFields[i];
32✔
93
    CPLFree(papoFields);
122✔
94
    for (int i = 0; i < nGeomFields; i++)
145✔
95
        delete papoGeomFields[i];
23✔
96
    CPLFree(papoGeomFields);
122✔
97

98
    CPLFree(pszAttributeFilter);
122✔
99
    CPLFree(panMap);
122✔
100

101
    if (poFeatureDefn)
122✔
102
        poFeatureDefn->Release();
107✔
103
    if (poGlobalSRS != nullptr)
122✔
104
        const_cast<OGRSpatialReference *>(poGlobalSRS)->Release();
34✔
105
}
244✔
106

107
/************************************************************************/
108
/*                              SetFields()                             */
109
/************************************************************************/
110

111
void OGRUnionLayer::SetFields(FieldUnionStrategy eFieldStrategyIn,
117✔
112
                              int nFieldsIn, OGRFieldDefn **papoFieldsIn,
113
                              int nGeomFieldsIn,
114
                              OGRUnionLayerGeomFieldDefn **papoGeomFieldsIn)
115
{
116
    CPLAssert(nFields == 0);
117✔
117
    CPLAssert(poFeatureDefn == nullptr);
117✔
118

119
    eFieldStrategy = eFieldStrategyIn;
117✔
120
    if (nFieldsIn)
117✔
121
    {
122
        nFields = nFieldsIn;
2✔
123
        papoFields = static_cast<OGRFieldDefn **>(
2✔
124
            CPLMalloc(nFields * sizeof(OGRFieldDefn *)));
2✔
125
        for (int i = 0; i < nFields; i++)
34✔
126
            papoFields[i] = new OGRFieldDefn(papoFieldsIn[i]);
32✔
127
    }
128
    nGeomFields = nGeomFieldsIn;
117✔
129
    if (nGeomFields > 0)
117✔
130
    {
131
        papoGeomFields = static_cast<OGRUnionLayerGeomFieldDefn **>(
17✔
132
            CPLMalloc(nGeomFields * sizeof(OGRUnionLayerGeomFieldDefn *)));
17✔
133
        for (int i = 0; i < nGeomFields; i++)
40✔
134
            papoGeomFields[i] =
23✔
135
                new OGRUnionLayerGeomFieldDefn(papoGeomFieldsIn[i]);
23✔
136
    }
137
}
117✔
138

139
/************************************************************************/
140
/*                        SetSourceLayerFieldName()                     */
141
/************************************************************************/
142

143
void OGRUnionLayer::SetSourceLayerFieldName(const char *pszSourceLayerFieldName)
91✔
144
{
145
    CPLAssert(poFeatureDefn == nullptr);
91✔
146

147
    CPLAssert(osSourceLayerFieldName.empty());
91✔
148
    if (pszSourceLayerFieldName != nullptr)
91✔
149
        osSourceLayerFieldName = pszSourceLayerFieldName;
17✔
150
}
91✔
151

152
/************************************************************************/
153
/*                           SetPreserveSrcFID()                        */
154
/************************************************************************/
155

156
void OGRUnionLayer::SetPreserveSrcFID(int bPreserveSrcFIDIn)
84✔
157
{
158
    CPLAssert(poFeatureDefn == nullptr);
84✔
159

160
    bPreserveSrcFID = bPreserveSrcFIDIn;
84✔
161
}
84✔
162

163
/************************************************************************/
164
/*                          SetFeatureCount()                           */
165
/************************************************************************/
166

167
void OGRUnionLayer::SetFeatureCount(int nFeatureCountIn)
9✔
168
{
169
    CPLAssert(poFeatureDefn == nullptr);
9✔
170

171
    nFeatureCount = nFeatureCountIn;
9✔
172
}
9✔
173

174
/************************************************************************/
175
/*                         MergeFieldDefn()                             */
176
/************************************************************************/
177

178
static void MergeFieldDefn(OGRFieldDefn *poFieldDefn,
66✔
179
                           const OGRFieldDefn *poSrcFieldDefn)
180
{
181
    if (poFieldDefn->GetType() != poSrcFieldDefn->GetType())
66✔
182
    {
183
        if (poSrcFieldDefn->GetType() == OFTReal &&
21✔
184
            (poFieldDefn->GetType() == OFTInteger ||
×
185
             poFieldDefn->GetType() == OFTInteger64))
×
186
            poFieldDefn->SetType(OFTReal);
×
187
        if (poFieldDefn->GetType() == OFTReal &&
21✔
188
            (poSrcFieldDefn->GetType() == OFTInteger ||
×
189
             poSrcFieldDefn->GetType() == OFTInteger64))
×
190
            poFieldDefn->SetType(OFTReal);
×
191
        else if (poSrcFieldDefn->GetType() == OFTInteger64 &&
38✔
192
                 poFieldDefn->GetType() == OFTInteger)
17✔
193
            poFieldDefn->SetType(OFTInteger64);
17✔
194
        else if (poFieldDefn->GetType() == OFTInteger64 &&
4✔
195
                 poSrcFieldDefn->GetType() == OFTInteger)
×
196
            poFieldDefn->SetType(OFTInteger64);
×
197
        else
198
            poFieldDefn->SetType(OFTString);
4✔
199
    }
200

201
    if (poFieldDefn->GetWidth() != poSrcFieldDefn->GetWidth() ||
107✔
202
        poFieldDefn->GetPrecision() != poSrcFieldDefn->GetPrecision())
41✔
203
    {
204
        poFieldDefn->SetWidth(0);
25✔
205
        poFieldDefn->SetPrecision(0);
25✔
206
    }
207
}
66✔
208

209
/************************************************************************/
210
/*                             GetLayerDefn()                           */
211
/************************************************************************/
212

213
OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
7,647✔
214
{
215
    if (poFeatureDefn != nullptr)
7,647✔
216
        return poFeatureDefn;
7,540✔
217

218
    poFeatureDefn = new OGRFeatureDefn(osName);
107✔
219
    poFeatureDefn->Reference();
107✔
220
    poFeatureDefn->SetGeomType(wkbNone);
107✔
221

222
    int iCompareFirstIndex = 0;
107✔
223
    if (!osSourceLayerFieldName.empty())
107✔
224
    {
225
        OGRFieldDefn oField(osSourceLayerFieldName, OFTString);
14✔
226
        poFeatureDefn->AddFieldDefn(&oField);
14✔
227
        iCompareFirstIndex = 1;
14✔
228
    }
229

230
    if (eFieldStrategy == FIELD_SPECIFIED)
107✔
231
    {
232
        for (int i = 0; i < nFields; i++)
4✔
233
            poFeatureDefn->AddFieldDefn(papoFields[i]);
×
234
        for (int i = 0; i < nGeomFields; i++)
12✔
235
        {
236
            poFeatureDefn->AddGeomFieldDefn(
8✔
237
                std::make_unique<OGRUnionLayerGeomFieldDefn>(
8✔
238
                    papoGeomFields[i]));
8✔
239
            OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
240
                cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
8✔
241
                    poFeatureDefn->GetGeomFieldDefn(i));
8✔
242

243
            if (poGeomFieldDefn->bGeomTypeSet == FALSE ||
8✔
244
                poGeomFieldDefn->bSRSSet == FALSE)
2✔
245
            {
246
                for (auto &oLayer : m_apoSrcLayers)
8✔
247
                {
248
                    OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
8✔
249
                    int nIndex = poSrcFeatureDefn->GetGeomFieldIndex(
8✔
250
                        poGeomFieldDefn->GetNameRef());
8✔
251
                    if (nIndex >= 0)
8✔
252
                    {
253
                        OGRGeomFieldDefn *poSrcGeomFieldDefn =
254
                            poSrcFeatureDefn->GetGeomFieldDefn(nIndex);
8✔
255
                        if (poGeomFieldDefn->bGeomTypeSet == FALSE)
8✔
256
                        {
257
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
6✔
258
                            poGeomFieldDefn->SetType(
6✔
259
                                poSrcGeomFieldDefn->GetType());
260
                        }
261
                        if (poGeomFieldDefn->bSRSSet == FALSE)
8✔
262
                        {
263
                            poGeomFieldDefn->bSRSSet = TRUE;
6✔
264
                            poGeomFieldDefn->SetSpatialRef(
6✔
265
                                poSrcGeomFieldDefn->GetSpatialRef());
6✔
266
                            if (i == 0 && poGlobalSRS == nullptr)
6✔
267
                            {
268
                                poGlobalSRS =
4✔
269
                                    poSrcGeomFieldDefn->GetSpatialRef();
4✔
270
                                if (poGlobalSRS != nullptr)
4✔
271
                                    const_cast<OGRSpatialReference *>(
272
                                        poGlobalSRS)
4✔
273
                                        ->Reference();
4✔
274
                            }
275
                        }
276
                        break;
8✔
277
                    }
278
                }
279
            }
280
        }
281
    }
282
    else if (eFieldStrategy == FIELD_FROM_FIRST_LAYER)
103✔
283
    {
284
        const OGRFeatureDefn *poSrcFeatureDefn =
285
            m_apoSrcLayers[0]->GetLayerDefn();
4✔
286
        const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
4✔
287
        for (int i = 0; i < nSrcFieldCount; i++)
46✔
288
            poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
42✔
289
        for (int i = 0;
4✔
290
             nGeomFields != -1 && i < poSrcFeatureDefn->GetGeomFieldCount();
12✔
291
             i++)
292
        {
293
            const OGRGeomFieldDefn *poFldDefn =
294
                poSrcFeatureDefn->GetGeomFieldDefn(i);
8✔
295
            poFeatureDefn->AddGeomFieldDefn(
8✔
296
                std::make_unique<OGRUnionLayerGeomFieldDefn>(poFldDefn));
16✔
297
        }
298
    }
299
    else if (eFieldStrategy == FIELD_UNION_ALL_LAYERS)
99✔
300
    {
301
        if (nGeomFields == 1)
90✔
302
        {
303
            poFeatureDefn->AddGeomFieldDefn(
×
304
                std::make_unique<OGRUnionLayerGeomFieldDefn>(
×
305
                    papoGeomFields[0]));
×
306
        }
307

308
        int nDstFieldCount = 0;
90✔
309
        std::map<std::string, int> oMapDstFieldNameToIdx;
180✔
310

311
        for (auto &oLayer : m_apoSrcLayers)
249✔
312
        {
313
            const OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
159✔
314

315
            /* Add any field that is found in the source layers */
316
            const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
159✔
317
            for (int i = 0; i < nSrcFieldCount; i++)
339✔
318
            {
319
                const OGRFieldDefn *poSrcFieldDefn =
320
                    poSrcFeatureDefn->GetFieldDefn(i);
180✔
321
                const auto oIter =
322
                    oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
180✔
323
                const int nIndex =
324
                    oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
180✔
325
                if (nIndex < 0)
180✔
326
                {
327
                    oMapDstFieldNameToIdx[poSrcFieldDefn->GetNameRef()] =
129✔
328
                        nDstFieldCount;
329
                    nDstFieldCount++;
129✔
330
                    poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
129✔
331
                }
332
                else
333
                {
334
                    OGRFieldDefn *poFieldDefn =
335
                        poFeatureDefn->GetFieldDefn(nIndex);
51✔
336
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
51✔
337
                }
338
            }
339

340
            for (int i = 0;
314✔
341
                 nGeomFields != -1 && i < poSrcFeatureDefn->GetGeomFieldCount();
314✔
342
                 i++)
343
            {
344
                const OGRGeomFieldDefn *poSrcFieldDefn =
345
                    poSrcFeatureDefn->GetGeomFieldDefn(i);
155✔
346
                int nIndex = poFeatureDefn->GetGeomFieldIndex(
155✔
347
                    poSrcFieldDefn->GetNameRef());
155✔
348
                if (nIndex < 0)
155✔
349
                {
350
                    poFeatureDefn->AddGeomFieldDefn(
92✔
351
                        std::make_unique<OGRUnionLayerGeomFieldDefn>(
92✔
352
                            poSrcFieldDefn));
92✔
353
                    if (poFeatureDefn->GetGeomFieldCount() == 1 &&
92✔
354
                        nGeomFields == 0 && GetSpatialRef() != nullptr)
92✔
355
                    {
356
                        OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
357
                            cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
27✔
358
                                poFeatureDefn->GetGeomFieldDefn(0));
27✔
359
                        poGeomFieldDefn->bSRSSet = TRUE;
27✔
360
                        poGeomFieldDefn->SetSpatialRef(GetSpatialRef());
27✔
361
                    }
362
                }
363
                else
364
                {
365
                    if (nIndex == 0 && nGeomFields == 1)
63✔
366
                    {
367
                        OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
368
                            cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
×
369
                                poFeatureDefn->GetGeomFieldDefn(0));
×
370
                        if (poGeomFieldDefn->bGeomTypeSet == FALSE)
×
371
                        {
372
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
×
373
                            poGeomFieldDefn->SetType(poSrcFieldDefn->GetType());
×
374
                        }
375
                        if (poGeomFieldDefn->bSRSSet == FALSE)
×
376
                        {
377
                            poGeomFieldDefn->bSRSSet = TRUE;
×
378
                            poGeomFieldDefn->SetSpatialRef(
×
379
                                poSrcFieldDefn->GetSpatialRef());
×
380
                        }
381
                    }
382
                    /* TODO: merge type, SRS, extent ? */
383
                }
384
            }
385
        }
386
    }
387
    else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS)
9✔
388
    {
389
        OGRFeatureDefn *poSrcFeatureDefn = m_apoSrcLayers[0]->GetLayerDefn();
9✔
390
        for (int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
33✔
391
            poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
24✔
392
        for (int i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
22✔
393
        {
394
            OGRGeomFieldDefn *poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
13✔
395
            poFeatureDefn->AddGeomFieldDefn(
13✔
396
                std::make_unique<OGRUnionLayerGeomFieldDefn>(poFldDefn));
26✔
397
        }
398

399
        /* Remove any field that is not found in the source layers */
400
        for (int iLayer = 1; iLayer < static_cast<int>(m_apoSrcLayers.size());
18✔
401
             iLayer++)
402
        {
403
            OGRFeatureDefn *l_poSrcFeatureDefn =
404
                m_apoSrcLayers[iLayer]->GetLayerDefn();
9✔
405
            for (int i = iCompareFirstIndex; i < poFeatureDefn->GetFieldCount();
33✔
406
                 // No increment.
407
            )
408
            {
409
                OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
24✔
410
                int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
24✔
411
                    poFieldDefn->GetNameRef());
24✔
412
                if (nSrcIndex < 0)
24✔
413
                {
414
                    poFeatureDefn->DeleteFieldDefn(i);
9✔
415
                }
416
                else
417
                {
418
                    OGRFieldDefn *poSrcFieldDefn =
419
                        l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
15✔
420
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
15✔
421

422
                    i++;
15✔
423
                }
424
            }
425
            for (int i = 0; i < poFeatureDefn->GetGeomFieldCount();
22✔
426
                 // No increment.
427
            )
428
            {
429
                OGRGeomFieldDefn *poFieldDefn =
430
                    poFeatureDefn->GetGeomFieldDefn(i);
13✔
431
                int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
13✔
432
                    poFieldDefn->GetNameRef());
13✔
433
                if (nSrcIndex < 0)
13✔
434
                {
435
                    poFeatureDefn->DeleteGeomFieldDefn(i);
2✔
436
                }
437
                else
438
                {
439
                    /* TODO: merge type, SRS, extent ? */
440

441
                    i++;
11✔
442
                }
443
            }
444
        }
445
    }
446

447
    return poFeatureDefn;
107✔
448
}
449

450
/************************************************************************/
451
/*                             GetGeomType()                            */
452
/************************************************************************/
453

454
OGRwkbGeometryType OGRUnionLayer::GetGeomType()
11✔
455
{
456
    if (nGeomFields < 0)
11✔
457
        return wkbNone;
1✔
458
    if (nGeomFields >= 1 && papoGeomFields[0]->bGeomTypeSet)
10✔
459
    {
460
        return papoGeomFields[0]->GetType();
2✔
461
    }
462

463
    return OGRLayer::GetGeomType();
8✔
464
}
465

466
/************************************************************************/
467
/*                    SetSpatialFilterToSourceLayer()                   */
468
/************************************************************************/
469

470
void OGRUnionLayer::SetSpatialFilterToSourceLayer(OGRLayer *poSrcLayer)
1,814✔
471
{
472
    if (m_iGeomFieldFilter >= 0 &&
3,628✔
473
        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
1,814✔
474
    {
475
        int iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
3,376✔
476
            GetLayerDefn()->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
1,688✔
477
        if (iSrcGeomField >= 0)
1,688✔
478
        {
479
            poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
1,687✔
480
        }
481
        else
482
        {
483
            poSrcLayer->SetSpatialFilter(nullptr);
1✔
484
        }
485
    }
486
    else
487
    {
488
        poSrcLayer->SetSpatialFilter(nullptr);
126✔
489
    }
490
}
1,814✔
491

492
/************************************************************************/
493
/*                        ConfigureActiveLayer()                        */
494
/************************************************************************/
495

496
void OGRUnionLayer::ConfigureActiveLayer()
1,242✔
497
{
498
    AutoWarpLayerIfNecessary(iCurLayer);
1,242✔
499
    ApplyAttributeFilterToSrcLayer(iCurLayer);
1,242✔
500
    SetSpatialFilterToSourceLayer(m_apoSrcLayers[iCurLayer].poLayer);
1,242✔
501
    m_apoSrcLayers[iCurLayer]->ResetReading();
1,242✔
502

503
    /* Establish map */
504
    GetLayerDefn();
1,242✔
505
    const OGRFeatureDefn *poSrcFeatureDefn =
506
        m_apoSrcLayers[iCurLayer]->GetLayerDefn();
1,242✔
507
    const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
1,242✔
508
    const int nDstFieldCount = poFeatureDefn->GetFieldCount();
1,242✔
509

510
    std::map<std::string, int> oMapDstFieldNameToIdx;
2,484✔
511
    for (int i = 0; i < nDstFieldCount; i++)
5,334✔
512
    {
513
        const OGRFieldDefn *poDstFieldDefn = poFeatureDefn->GetFieldDefn(i);
4,092✔
514
        oMapDstFieldNameToIdx[poDstFieldDefn->GetNameRef()] = i;
4,092✔
515
    }
516

517
    CPLFree(panMap);
1,242✔
518
    panMap = static_cast<int *>(CPLMalloc(nSrcFieldCount * sizeof(int)));
1,242✔
519
    for (int i = 0; i < nSrcFieldCount; i++)
6,204✔
520
    {
521
        const OGRFieldDefn *poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
4,962✔
522
        if (m_aosIgnoredFields.FindString(poSrcFieldDefn->GetNameRef()) == -1)
4,962✔
523
        {
524
            const auto oIter =
525
                oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
4,951✔
526
            panMap[i] =
4,951✔
527
                oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
4,951✔
528
        }
529
        else
530
        {
531
            panMap[i] = -1;
11✔
532
        }
533
    }
534

535
    if (m_apoSrcLayers[iCurLayer]->TestCapability(OLCIgnoreFields))
1,242✔
536
    {
537
        CPLStringList aosFieldSrc;
2,388✔
538
        for (const char *pszFieldName : cpl::Iterate(m_aosIgnoredFields))
1,222✔
539
        {
540
            if (EQUAL(pszFieldName, "OGR_GEOMETRY") ||
69✔
541
                EQUAL(pszFieldName, "OGR_STYLE") ||
13✔
542
                poSrcFeatureDefn->GetFieldIndex(pszFieldName) >= 0 ||
43✔
543
                poSrcFeatureDefn->GetGeomFieldIndex(pszFieldName) >= 0)
2✔
544
            {
545
                aosFieldSrc.AddString(pszFieldName);
26✔
546
            }
547
        }
548

549
        std::map<std::string, int> oMapSrcFieldNameToIdx;
2,388✔
550
        for (int i = 0; i < nSrcFieldCount; i++)
6,090✔
551
        {
552
            const OGRFieldDefn *poSrcFieldDefn =
553
                poSrcFeatureDefn->GetFieldDefn(i);
4,896✔
554
            oMapSrcFieldNameToIdx[poSrcFieldDefn->GetNameRef()] = i;
4,896✔
555
        }
556

557
        /* Attribute fields */
558
        std::vector<bool> abSrcFieldsUsed(nSrcFieldCount);
2,388✔
559
        for (int iField = 0; iField < nDstFieldCount; iField++)
5,187✔
560
        {
561
            const OGRFieldDefn *poFieldDefn =
562
                poFeatureDefn->GetFieldDefn(iField);
3,993✔
563
            const auto oIter =
564
                oMapSrcFieldNameToIdx.find(poFieldDefn->GetNameRef());
3,993✔
565
            const int iSrcField =
566
                oIter == oMapSrcFieldNameToIdx.end() ? -1 : oIter->second;
3,993✔
567
            if (iSrcField >= 0)
3,993✔
568
                abSrcFieldsUsed[iSrcField] = true;
3,442✔
569
        }
570
        for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
6,090✔
571
        {
572
            if (!abSrcFieldsUsed[iSrcField])
4,896✔
573
            {
574
                const OGRFieldDefn *poSrcDefn =
575
                    poSrcFeatureDefn->GetFieldDefn(iSrcField);
1,454✔
576
                aosFieldSrc.AddString(poSrcDefn->GetNameRef());
1,454✔
577
            }
578
        }
579

580
        /* geometry fields now */
581
        abSrcFieldsUsed.clear();
1,194✔
582
        abSrcFieldsUsed.resize(poSrcFeatureDefn->GetGeomFieldCount());
1,194✔
583
        for (int iField = 0; iField < poFeatureDefn->GetGeomFieldCount();
3,492✔
584
             iField++)
585
        {
586
            const OGRGeomFieldDefn *poFieldDefn =
587
                poFeatureDefn->GetGeomFieldDefn(iField);
2,298✔
588
            const int iSrcField =
589
                poSrcFeatureDefn->GetGeomFieldIndex(poFieldDefn->GetNameRef());
2,298✔
590
            if (iSrcField >= 0)
2,298✔
591
                abSrcFieldsUsed[iSrcField] = true;
2,110✔
592
        }
593
        for (int iSrcField = 0;
3,983✔
594
             iSrcField < poSrcFeatureDefn->GetGeomFieldCount(); iSrcField++)
3,983✔
595
        {
596
            if (!abSrcFieldsUsed[iSrcField])
2,789✔
597
            {
598
                const OGRGeomFieldDefn *poSrcDefn =
599
                    poSrcFeatureDefn->GetGeomFieldDefn(iSrcField);
679✔
600
                aosFieldSrc.AddString(poSrcDefn->GetNameRef());
679✔
601
            }
602
        }
603

604
        m_apoSrcLayers[iCurLayer]->SetIgnoredFields(aosFieldSrc.List());
1,194✔
605
    }
606
}
1,242✔
607

608
/************************************************************************/
609
/*                             ResetReading()                           */
610
/************************************************************************/
611

612
void OGRUnionLayer::ResetReading()
1,009✔
613
{
614
    iCurLayer = 0;
1,009✔
615
    ConfigureActiveLayer();
1,009✔
616
    nNextFID = 0;
1,009✔
617
}
1,009✔
618

619
/************************************************************************/
620
/*                         AutoWarpLayerIfNecessary()                   */
621
/************************************************************************/
622

623
void OGRUnionLayer::AutoWarpLayerIfNecessary(int iLayer)
1,632✔
624
{
625
    if (!m_apoSrcLayers[iLayer].bCheckIfAutoWrap)
1,632✔
626
    {
627
        m_apoSrcLayers[iLayer].bCheckIfAutoWrap = true;
116✔
628

629
        for (int iField = 0; iField < GetLayerDefn()->GetGeomFieldCount();
256✔
630
             iField++)
631
        {
632
            const OGRSpatialReference *poSRS =
633
                GetLayerDefn()->GetGeomFieldDefn(iField)->GetSpatialRef();
140✔
634

635
            OGRFeatureDefn *poSrcFeatureDefn =
636
                m_apoSrcLayers[iLayer]->GetLayerDefn();
140✔
637
            int iSrcGeomField = poSrcFeatureDefn->GetGeomFieldIndex(
140✔
638
                GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef());
140✔
639
            if (iSrcGeomField >= 0)
140✔
640
            {
641
                const OGRSpatialReference *poSRS2 =
642
                    poSrcFeatureDefn->GetGeomFieldDefn(iSrcGeomField)
131✔
643
                        ->GetSpatialRef();
131✔
644

645
                if ((poSRS == nullptr && poSRS2 != nullptr) ||
131✔
646
                    (poSRS != nullptr && poSRS2 == nullptr))
97✔
647
                {
NEW
648
                    CPLError(
×
649
                        CE_Warning, CPLE_AppDefined,
650
                        "SRS of geometry field '%s' layer %s not "
651
                        "consistent with UnionLayer SRS",
NEW
652
                        GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef(),
×
NEW
653
                        m_apoSrcLayers[iLayer]->GetName());
×
654
                }
655
                else if (poSRS != nullptr && poSRS2 != nullptr &&
97✔
656
                         poSRS != poSRS2 && !poSRS->IsSame(poSRS2))
228✔
657
                {
658
                    CPLDebug(
4✔
659
                        "VRT",
660
                        "SRS of geometry field '%s' layer %s not "
661
                        "consistent with UnionLayer SRS. "
662
                        "Trying auto warping",
663
                        GetLayerDefn()->GetGeomFieldDefn(iField)->GetNameRef(),
4✔
664
                        m_apoSrcLayers[iLayer]->GetName());
4✔
665
                    std::unique_ptr<OGRCoordinateTransformation> poCT(
666
                        OGRCreateCoordinateTransformation(poSRS2, poSRS));
8✔
667
                    std::unique_ptr<OGRCoordinateTransformation> poReversedCT(
668
                        (poCT != nullptr) ? poCT->GetInverse() : nullptr);
8✔
669
                    if (poReversedCT != nullptr)
4✔
670
                    {
671
                        auto [poSrcLayer, bOwned] =
4✔
672
                            m_apoSrcLayers[iLayer].release();
4✔
673
                        m_apoSrcLayers[iLayer].reset(
8✔
674
                            std::make_unique<OGRWarpedLayer>(
4✔
675
                                poSrcLayer, iSrcGeomField, bOwned,
676
                                poCT.release(), poReversedCT.release()));
8✔
677
                    }
678
                    else
679
                    {
680
                        CPLError(CE_Warning, CPLE_AppDefined,
×
681
                                 "AutoWarpLayerIfNecessary failed to create "
682
                                 "poCT or poReversedCT.");
683
                    }
684
                }
685
            }
686
        }
687
    }
688
}
1,632✔
689

690
/************************************************************************/
691
/*                           GetNextFeature()                           */
692
/************************************************************************/
693

694
OGRFeature *OGRUnionLayer::GetNextFeature()
2,637✔
695
{
696
    if (poFeatureDefn == nullptr)
2,637✔
697
        GetLayerDefn();
3✔
698
    if (iCurLayer < 0)
2,637✔
699
        ResetReading();
10✔
700

701
    if (iCurLayer == static_cast<int>(m_apoSrcLayers.size()))
2,637✔
702
        return nullptr;
9✔
703

704
    while (true)
705
    {
706
        OGRFeature *poSrcFeature = m_apoSrcLayers[iCurLayer]->GetNextFeature();
3,364✔
707
        if (poSrcFeature == nullptr)
3,364✔
708
        {
709
            iCurLayer++;
503✔
710
            if (iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
503✔
711
            {
712
                ConfigureActiveLayer();
233✔
713
                continue;
233✔
714
            }
715
            else
716
                break;
270✔
717
        }
718

719
        OGRFeature *poFeature = TranslateFromSrcLayer(poSrcFeature);
2,861✔
720
        delete poSrcFeature;
2,861✔
721

722
        if ((m_poFilterGeom == nullptr ||
6,038✔
723
             FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
5,722✔
724
            (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
2,861✔
725
        {
726
            return poFeature;
2,358✔
727
        }
728

729
        delete poFeature;
503✔
730
    }
736✔
731
    return nullptr;
270✔
732
}
733

734
/************************************************************************/
735
/*                             GetFeature()                             */
736
/************************************************************************/
737

738
OGRFeature *OGRUnionLayer::GetFeature(GIntBig nFeatureId)
56✔
739
{
740
    OGRFeature *poFeature = nullptr;
56✔
741

742
    if (!bPreserveSrcFID)
56✔
743
    {
744
        poFeature = OGRLayer::GetFeature(nFeatureId);
56✔
745
    }
746
    else
747
    {
748
        int iGeomFieldFilterSave = m_iGeomFieldFilter;
×
749
        OGRGeometry *poGeomSave = m_poFilterGeom;
×
750
        m_poFilterGeom = nullptr;
×
751
        SetSpatialFilter(nullptr);
×
752

NEW
753
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
×
754
        {
755
            iCurLayer = i;
×
756
            ConfigureActiveLayer();
×
757

758
            OGRFeature *poSrcFeature =
NEW
759
                m_apoSrcLayers[i]->GetFeature(nFeatureId);
×
UNCOV
760
            if (poSrcFeature != nullptr)
×
761
            {
762
                poFeature = TranslateFromSrcLayer(poSrcFeature);
×
763
                delete poSrcFeature;
×
764

765
                break;
×
766
            }
767
        }
768

769
        SetSpatialFilter(iGeomFieldFilterSave, poGeomSave);
×
770
        delete poGeomSave;
×
771

772
        ResetReading();
×
773
    }
774

775
    return poFeature;
56✔
776
}
777

778
/************************************************************************/
779
/*                          ICreateFeature()                             */
780
/************************************************************************/
781

782
OGRErr OGRUnionLayer::ICreateFeature(OGRFeature *poFeature)
5✔
783
{
784
    if (osSourceLayerFieldName.empty())
5✔
785
    {
786
        CPLError(CE_Failure, CPLE_NotSupported,
1✔
787
                 "CreateFeature() not supported when SourceLayerFieldName is "
788
                 "not set");
789
        return OGRERR_FAILURE;
1✔
790
    }
791

792
    if (poFeature->GetFID() != OGRNullFID)
4✔
793
    {
794
        CPLError(CE_Failure, CPLE_NotSupported,
1✔
795
                 "CreateFeature() not supported when FID is set");
796
        return OGRERR_FAILURE;
1✔
797
    }
798

799
    if (!poFeature->IsFieldSetAndNotNull(0))
3✔
800
    {
801
        CPLError(CE_Failure, CPLE_NotSupported,
1✔
802
                 "CreateFeature() not supported when '%s' field is not set",
803
                 osSourceLayerFieldName.c_str());
804
        return OGRERR_FAILURE;
1✔
805
    }
806

807
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
2✔
808
    for (auto &oLayer : m_apoSrcLayers)
5✔
809
    {
810
        if (strcmp(pszSrcLayerName, oLayer->GetName()) == 0)
4✔
811
        {
812
            oLayer.bModified = true;
1✔
813

814
            OGRFeature *poSrcFeature = new OGRFeature(oLayer->GetLayerDefn());
1✔
815
            poSrcFeature->SetFrom(poFeature, TRUE);
1✔
816
            OGRErr eErr = oLayer->CreateFeature(poSrcFeature);
1✔
817
            if (eErr == OGRERR_NONE)
1✔
818
                poFeature->SetFID(poSrcFeature->GetFID());
1✔
819
            delete poSrcFeature;
1✔
820
            return eErr;
1✔
821
        }
822
    }
823

824
    CPLError(CE_Failure, CPLE_NotSupported,
1✔
825
             "CreateFeature() not supported : '%s' source layer does not exist",
826
             pszSrcLayerName);
827
    return OGRERR_FAILURE;
1✔
828
}
829

830
/************************************************************************/
831
/*                             ISetFeature()                             */
832
/************************************************************************/
833

834
OGRErr OGRUnionLayer::ISetFeature(OGRFeature *poFeature)
14✔
835
{
836
    if (!bPreserveSrcFID)
14✔
837
    {
838
        CPLError(CE_Failure, CPLE_NotSupported,
10✔
839
                 "SetFeature() not supported when PreserveSrcFID is OFF");
840
        return OGRERR_FAILURE;
10✔
841
    }
842

843
    if (osSourceLayerFieldName.empty())
4✔
844
    {
845
        CPLError(
×
846
            CE_Failure, CPLE_NotSupported,
847
            "SetFeature() not supported when SourceLayerFieldName is not set");
848
        return OGRERR_FAILURE;
×
849
    }
850

851
    if (poFeature->GetFID() == OGRNullFID)
4✔
852
    {
853
        CPLError(CE_Failure, CPLE_NotSupported,
1✔
854
                 "SetFeature() not supported when FID is not set");
855
        return OGRERR_FAILURE;
1✔
856
    }
857

858
    if (!poFeature->IsFieldSetAndNotNull(0))
3✔
859
    {
860
        CPLError(CE_Failure, CPLE_NotSupported,
1✔
861
                 "SetFeature() not supported when '%s' field is not set",
862
                 osSourceLayerFieldName.c_str());
863
        return OGRERR_FAILURE;
1✔
864
    }
865

866
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
2✔
867
    for (auto &oLayer : m_apoSrcLayers)
5✔
868
    {
869
        if (strcmp(pszSrcLayerName, oLayer->GetName()) == 0)
4✔
870
        {
871
            oLayer.bModified = true;
1✔
872

873
            OGRFeature *poSrcFeature = new OGRFeature(oLayer->GetLayerDefn());
1✔
874
            poSrcFeature->SetFrom(poFeature, TRUE);
1✔
875
            poSrcFeature->SetFID(poFeature->GetFID());
1✔
876
            OGRErr eErr = oLayer->SetFeature(poSrcFeature);
1✔
877
            delete poSrcFeature;
1✔
878
            return eErr;
1✔
879
        }
880
    }
881

882
    CPLError(CE_Failure, CPLE_NotSupported,
1✔
883
             "SetFeature() not supported : '%s' source layer does not exist",
884
             pszSrcLayerName);
885
    return OGRERR_FAILURE;
1✔
886
}
887

888
/************************************************************************/
889
/*                          IUpsertFeature()                            */
890
/************************************************************************/
891

892
OGRErr OGRUnionLayer::IUpsertFeature(OGRFeature *poFeature)
×
893
{
894
    if (GetFeature(poFeature->GetFID()))
×
895
    {
896
        return ISetFeature(poFeature);
×
897
    }
898
    else
899
    {
900
        return ICreateFeature(poFeature);
×
901
    }
902
}
903

904
/************************************************************************/
905
/*                           IUpdateFeature()                           */
906
/************************************************************************/
907

908
OGRErr OGRUnionLayer::IUpdateFeature(OGRFeature *poFeature,
×
909
                                     int nUpdatedFieldsCount,
910
                                     const int *panUpdatedFieldsIdx,
911
                                     int nUpdatedGeomFieldsCount,
912
                                     const int *panUpdatedGeomFieldsIdx,
913
                                     bool bUpdateStyleString)
914
{
915
    if (!bPreserveSrcFID)
×
916
    {
917
        CPLError(CE_Failure, CPLE_NotSupported,
×
918
                 "UpdateFeature() not supported when PreserveSrcFID is OFF");
919
        return OGRERR_FAILURE;
×
920
    }
921

922
    if (osSourceLayerFieldName.empty())
×
923
    {
924
        CPLError(CE_Failure, CPLE_NotSupported,
×
925
                 "UpdateFeature() not supported when SourceLayerFieldName is "
926
                 "not set");
927
        return OGRERR_FAILURE;
×
928
    }
929

930
    if (poFeature->GetFID() == OGRNullFID)
×
931
    {
932
        CPLError(CE_Failure, CPLE_NotSupported,
×
933
                 "UpdateFeature() not supported when FID is not set");
934
        return OGRERR_FAILURE;
×
935
    }
936

937
    if (!poFeature->IsFieldSetAndNotNull(0))
×
938
    {
939
        CPLError(CE_Failure, CPLE_NotSupported,
×
940
                 "UpdateFeature() not supported when '%s' field is not set",
941
                 osSourceLayerFieldName.c_str());
942
        return OGRERR_FAILURE;
×
943
    }
944

945
    const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
×
NEW
946
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
×
947
    {
NEW
948
        if (strcmp(pszSrcLayerName, m_apoSrcLayers[i]->GetName()) == 0)
×
949
        {
NEW
950
            m_apoSrcLayers[i].bModified = true;
×
951

NEW
952
            const auto poSrcLayerDefn = m_apoSrcLayers[i]->GetLayerDefn();
×
953
            OGRFeature *poSrcFeature = new OGRFeature(poSrcLayerDefn);
×
954
            poSrcFeature->SetFrom(poFeature, TRUE);
×
955
            poSrcFeature->SetFID(poFeature->GetFID());
×
956

957
            // We could potentially have a pre-computed map from indices in
958
            // poLayerDefn to indices in poSrcLayerDefn
959
            std::vector<int> anSrcUpdatedFieldIdx;
×
960
            const auto poLayerDefn = GetLayerDefn();
×
961
            for (int j = 0; j < nUpdatedFieldsCount; ++j)
×
962
            {
963
                if (panUpdatedFieldsIdx[j] != 0)
×
964
                {
965
                    const int nNewIdx = poSrcLayerDefn->GetFieldIndex(
×
966
                        poLayerDefn->GetFieldDefn(panUpdatedFieldsIdx[j])
×
967
                            ->GetNameRef());
×
968
                    if (nNewIdx >= 0)
×
969
                    {
970
                        anSrcUpdatedFieldIdx.push_back(nNewIdx);
×
971
                    }
972
                }
973
            }
974
            std::vector<int> anSrcUpdatedGeomFieldIdx;
×
975
            for (int j = 0; j < nUpdatedGeomFieldsCount; ++j)
×
976
            {
977
                if (panUpdatedGeomFieldsIdx[j] != 0)
×
978
                {
979
                    const int nNewIdx = poSrcLayerDefn->GetGeomFieldIndex(
×
980
                        poLayerDefn
981
                            ->GetGeomFieldDefn(panUpdatedGeomFieldsIdx[j])
×
982
                            ->GetNameRef());
×
983
                    if (nNewIdx >= 0)
×
984
                    {
985
                        anSrcUpdatedGeomFieldIdx.push_back(nNewIdx);
×
986
                    }
987
                }
988
            }
989

NEW
990
            OGRErr eErr = m_apoSrcLayers[i]->UpdateFeature(
×
991
                poSrcFeature, static_cast<int>(anSrcUpdatedFieldIdx.size()),
×
992
                anSrcUpdatedFieldIdx.data(),
×
993
                static_cast<int>(anSrcUpdatedGeomFieldIdx.size()),
×
994
                anSrcUpdatedGeomFieldIdx.data(), bUpdateStyleString);
×
995
            delete poSrcFeature;
×
996
            return eErr;
×
997
        }
998
    }
999

1000
    CPLError(CE_Failure, CPLE_NotSupported,
×
1001
             "UpdateFeature() not supported : '%s' source layer does not exist",
1002
             pszSrcLayerName);
1003
    return OGRERR_FAILURE;
×
1004
}
1005

1006
/************************************************************************/
1007
/*                           GetSpatialRef()                            */
1008
/************************************************************************/
1009

1010
OGRSpatialReference *OGRUnionLayer::GetSpatialRef()
216✔
1011
{
1012
    if (nGeomFields < 0)
216✔
1013
        return nullptr;
×
1014
    if (nGeomFields >= 1 && papoGeomFields[0]->bSRSSet)
216✔
1015
        return const_cast<OGRSpatialReference *>(
1016
            papoGeomFields[0]->GetSpatialRef());
1✔
1017

1018
    if (poGlobalSRS == nullptr)
215✔
1019
    {
1020
        poGlobalSRS = m_apoSrcLayers[0]->GetSpatialRef();
149✔
1021
        if (poGlobalSRS != nullptr)
149✔
1022
            const_cast<OGRSpatialReference *>(poGlobalSRS)->Reference();
30✔
1023
    }
1024
    return const_cast<OGRSpatialReference *>(poGlobalSRS);
215✔
1025
}
1026

1027
/************************************************************************/
1028
/*                      GetAttrFilterPassThroughValue()                 */
1029
/************************************************************************/
1030

1031
int OGRUnionLayer::GetAttrFilterPassThroughValue()
1,922✔
1032
{
1033
    if (m_poAttrQuery == nullptr)
1,922✔
1034
        return TRUE;
1,382✔
1035

1036
    if (bAttrFilterPassThroughValue >= 0)
540✔
1037
        return bAttrFilterPassThroughValue;
439✔
1038

1039
    char **papszUsedFields = m_poAttrQuery->GetUsedFields();
101✔
1040
    int bRet = TRUE;
101✔
1041

1042
    for (auto &oLayer : m_apoSrcLayers)
292✔
1043
    {
1044
        OGRFeatureDefn *poSrcFeatureDefn = oLayer->GetLayerDefn();
191✔
1045
        char **papszIter = papszUsedFields;
191✔
1046
        while (papszIter != nullptr && *papszIter != nullptr)
257✔
1047
        {
1048
            int bIsSpecial = FALSE;
79✔
1049
            for (int i = 0; i < SPECIAL_FIELD_COUNT; i++)
458✔
1050
            {
1051
                if (EQUAL(*papszIter, SpecialFieldNames[i]))
383✔
1052
                {
1053
                    bIsSpecial = TRUE;
4✔
1054
                    break;
4✔
1055
                }
1056
            }
1057
            if (!bIsSpecial && poSrcFeatureDefn->GetFieldIndex(*papszIter) < 0)
79✔
1058
            {
1059
                bRet = FALSE;
13✔
1060
                break;
13✔
1061
            }
1062
            papszIter++;
66✔
1063
        }
1064
    }
1065

1066
    CSLDestroy(papszUsedFields);
101✔
1067

1068
    bAttrFilterPassThroughValue = bRet;
101✔
1069

1070
    return bRet;
101✔
1071
}
1072

1073
/************************************************************************/
1074
/*                  ApplyAttributeFilterToSrcLayer()                    */
1075
/************************************************************************/
1076

1077
void OGRUnionLayer::ApplyAttributeFilterToSrcLayer(int iSubLayer)
1,764✔
1078
{
1079
    CPLAssert(iSubLayer >= 0 &&
1,764✔
1080
              iSubLayer < static_cast<int>(m_apoSrcLayers.size()));
1081

1082
    if (GetAttrFilterPassThroughValue())
1,764✔
1083
        m_apoSrcLayers[iSubLayer]->SetAttributeFilter(pszAttributeFilter);
1,705✔
1084
    else
1085
        m_apoSrcLayers[iSubLayer]->SetAttributeFilter(nullptr);
59✔
1086
}
1,764✔
1087

1088
/************************************************************************/
1089
/*                          GetFeatureCount()                           */
1090
/************************************************************************/
1091

1092
GIntBig OGRUnionLayer::GetFeatureCount(int bForce)
154✔
1093
{
1094
    if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
154✔
1095
        m_poAttrQuery == nullptr)
1✔
1096
    {
1097
        return nFeatureCount;
1✔
1098
    }
1099

1100
    if (!GetAttrFilterPassThroughValue())
153✔
1101
        return OGRLayer::GetFeatureCount(bForce);
5✔
1102

1103
    GIntBig nRet = 0;
148✔
1104
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
431✔
1105
    {
1106
        AutoWarpLayerIfNecessary(i);
283✔
1107
        ApplyAttributeFilterToSrcLayer(i);
283✔
1108
        SetSpatialFilterToSourceLayer(m_apoSrcLayers[i].poLayer);
283✔
1109
        nRet += m_apoSrcLayers[i]->GetFeatureCount(bForce);
283✔
1110
    }
1111
    ResetReading();
148✔
1112
    return nRet;
148✔
1113
}
1114

1115
/************************************************************************/
1116
/*                         SetAttributeFilter()                         */
1117
/************************************************************************/
1118

1119
OGRErr OGRUnionLayer::SetAttributeFilter(const char *pszAttributeFilterIn)
436✔
1120
{
1121
    if (pszAttributeFilterIn == nullptr && pszAttributeFilter == nullptr)
436✔
1122
        return OGRERR_NONE;
201✔
1123
    if (pszAttributeFilterIn != nullptr && pszAttributeFilter != nullptr &&
235✔
1124
        strcmp(pszAttributeFilterIn, pszAttributeFilter) == 0)
61✔
1125
        return OGRERR_NONE;
8✔
1126

1127
    if (poFeatureDefn == nullptr)
227✔
1128
        GetLayerDefn();
1✔
1129

1130
    bAttrFilterPassThroughValue = -1;
227✔
1131

1132
    OGRErr eErr = OGRLayer::SetAttributeFilter(pszAttributeFilterIn);
227✔
1133
    if (eErr != OGRERR_NONE)
227✔
1134
        return eErr;
×
1135

1136
    CPLFree(pszAttributeFilter);
227✔
1137
    pszAttributeFilter =
227✔
1138
        pszAttributeFilterIn ? CPLStrdup(pszAttributeFilterIn) : nullptr;
227✔
1139

1140
    if (iCurLayer >= 0 && iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
227✔
1141
        ApplyAttributeFilterToSrcLayer(iCurLayer);
227✔
1142

1143
    return OGRERR_NONE;
227✔
1144
}
1145

1146
/************************************************************************/
1147
/*                           TestCapability()                           */
1148
/************************************************************************/
1149

1150
int OGRUnionLayer::TestCapability(const char *pszCap)
375✔
1151
{
1152
    if (EQUAL(pszCap, OLCFastFeatureCount))
375✔
1153
    {
1154
        if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
6✔
1155
            m_poAttrQuery == nullptr)
3✔
1156
            return TRUE;
1✔
1157

1158
        if (!GetAttrFilterPassThroughValue())
5✔
1159
            return FALSE;
1✔
1160

1161
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
12✔
1162
        {
1163
            AutoWarpLayerIfNecessary(i);
8✔
1164
            ApplyAttributeFilterToSrcLayer(i);
8✔
1165
            SetSpatialFilterToSourceLayer(m_apoSrcLayers[i].poLayer);
8✔
1166
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
8✔
UNCOV
1167
                return FALSE;
×
1168
        }
1169
        return TRUE;
4✔
1170
    }
1171

1172
    if (EQUAL(pszCap, OLCFastGetExtent))
369✔
1173
    {
1174
        if (nGeomFields >= 1 && papoGeomFields[0]->sStaticEnvelope.IsInit())
21✔
1175
            return TRUE;
1✔
1176

1177
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
32✔
1178
        {
1179
            AutoWarpLayerIfNecessary(i);
25✔
1180
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
25✔
1181
                return FALSE;
13✔
1182
        }
1183
        return TRUE;
7✔
1184
    }
1185

1186
    if (EQUAL(pszCap, OLCFastSpatialFilter))
348✔
1187
    {
1188
        for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
6✔
1189
        {
1190
            AutoWarpLayerIfNecessary(i);
4✔
1191
            ApplyAttributeFilterToSrcLayer(i);
4✔
1192
            if (!m_apoSrcLayers[i]->TestCapability(pszCap))
4✔
1193
                return FALSE;
×
1194
        }
1195
        return TRUE;
2✔
1196
    }
1197

1198
    if (EQUAL(pszCap, OLCStringsAsUTF8))
346✔
1199
    {
1200
        for (auto &oLayer : m_apoSrcLayers)
172✔
1201
        {
1202
            if (!oLayer->TestCapability(pszCap))
142✔
1203
                return FALSE;
82✔
1204
        }
1205
        return TRUE;
30✔
1206
    }
1207

1208
    if (EQUAL(pszCap, OLCRandomRead))
234✔
1209
    {
1210
        if (!bPreserveSrcFID)
×
1211
            return FALSE;
×
1212

NEW
1213
        for (auto &oLayer : m_apoSrcLayers)
×
1214
        {
NEW
1215
            if (!oLayer->TestCapability(pszCap))
×
1216
                return FALSE;
×
1217
        }
1218
        return TRUE;
×
1219
    }
1220

1221
    if (EQUAL(pszCap, OLCRandomWrite))
234✔
1222
    {
1223
        if (!bPreserveSrcFID || osSourceLayerFieldName.empty())
11✔
1224
            return FALSE;
10✔
1225

1226
        for (auto &oLayer : m_apoSrcLayers)
3✔
1227
        {
1228
            if (!oLayer->TestCapability(pszCap))
2✔
1229
                return FALSE;
×
1230
        }
1231
        return TRUE;
1✔
1232
    }
1233

1234
    if (EQUAL(pszCap, OLCSequentialWrite))
223✔
1235
    {
1236
        if (osSourceLayerFieldName.empty())
11✔
1237
            return FALSE;
10✔
1238

1239
        for (auto &oLayer : m_apoSrcLayers)
3✔
1240
        {
1241
            if (!oLayer->TestCapability(pszCap))
2✔
1242
                return FALSE;
×
1243
        }
1244
        return TRUE;
1✔
1245
    }
1246

1247
    if (EQUAL(pszCap, OLCIgnoreFields))
212✔
1248
        return TRUE;
12✔
1249

1250
    if (EQUAL(pszCap, OLCCurveGeometries))
200✔
1251
        return TRUE;
38✔
1252

1253
    return FALSE;
162✔
1254
}
1255

1256
/************************************************************************/
1257
/*                             IGetExtent()                             */
1258
/************************************************************************/
1259

1260
OGRErr OGRUnionLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
41✔
1261
                                 bool bForce)
1262
{
1263
    if (iGeomField >= 0 && iGeomField < nGeomFields &&
51✔
1264
        papoGeomFields[iGeomField]->sStaticEnvelope.IsInit())
10✔
1265
    {
1266
        *psExtent = papoGeomFields[iGeomField]->sStaticEnvelope;
4✔
1267
        return OGRERR_NONE;
4✔
1268
    }
1269

1270
    if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount())
37✔
1271
    {
1272
        if (iGeomField != 0)
×
1273
        {
1274
            CPLError(CE_Failure, CPLE_AppDefined,
×
1275
                     "Invalid geometry field index : %d", iGeomField);
1276
        }
1277
        return OGRERR_FAILURE;
×
1278
    }
1279

1280
    int bInit = FALSE;
37✔
1281
    for (int i = 0; i < static_cast<int>(m_apoSrcLayers.size()); i++)
107✔
1282
    {
1283
        AutoWarpLayerIfNecessary(i);
70✔
1284
        int iSrcGeomField =
1285
            m_apoSrcLayers[i]->GetLayerDefn()->GetGeomFieldIndex(
140✔
1286
                GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetNameRef());
70✔
1287
        if (iSrcGeomField >= 0)
70✔
1288
        {
1289
            if (!bInit)
64✔
1290
            {
1291
                if (m_apoSrcLayers[i]->GetExtent(iSrcGeomField, psExtent,
37✔
1292
                                                 bForce) == OGRERR_NONE)
37✔
1293
                    bInit = TRUE;
33✔
1294
            }
1295
            else
1296
            {
1297
                OGREnvelope sExtent;
27✔
1298
                if (m_apoSrcLayers[i]->GetExtent(iSrcGeomField, &sExtent,
27✔
1299
                                                 bForce) == OGRERR_NONE)
27✔
1300
                {
1301
                    psExtent->Merge(sExtent);
27✔
1302
                }
1303
            }
1304
        }
1305
    }
1306
    return (bInit) ? OGRERR_NONE : OGRERR_FAILURE;
37✔
1307
}
1308

1309
/************************************************************************/
1310
/*                        ISetSpatialFilter()                           */
1311
/************************************************************************/
1312

1313
OGRErr OGRUnionLayer::ISetSpatialFilter(int iGeomField,
377✔
1314
                                        const OGRGeometry *poGeom)
1315
{
1316
    m_iGeomFieldFilter = iGeomField;
377✔
1317
    if (InstallFilter(poGeom))
377✔
1318
        ResetReading();
129✔
1319

1320
    if (iCurLayer >= 0 && iCurLayer < static_cast<int>(m_apoSrcLayers.size()))
377✔
1321
    {
1322
        SetSpatialFilterToSourceLayer(m_apoSrcLayers[iCurLayer].poLayer);
281✔
1323
    }
1324

1325
    return OGRERR_NONE;
377✔
1326
}
1327

1328
/************************************************************************/
1329
/*                        TranslateFromSrcLayer()                       */
1330
/************************************************************************/
1331

1332
OGRFeature *OGRUnionLayer::TranslateFromSrcLayer(OGRFeature *poSrcFeature)
2,861✔
1333
{
1334
    CPLAssert(poSrcFeature->GetFieldCount() == 0 || panMap != nullptr);
2,861✔
1335
    CPLAssert(iCurLayer >= 0 &&
2,861✔
1336
              iCurLayer < static_cast<int>(m_apoSrcLayers.size()));
1337

1338
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
2,861✔
1339
    poFeature->SetFrom(poSrcFeature, panMap, TRUE);
2,861✔
1340

1341
    if (!osSourceLayerFieldName.empty() &&
2,971✔
1342
        !poFeatureDefn->GetFieldDefn(0)->IsIgnored())
110✔
1343
    {
1344
        poFeature->SetField(0, m_apoSrcLayers[iCurLayer]->GetName());
110✔
1345
    }
1346

1347
    for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
6,140✔
1348
    {
1349
        if (poFeatureDefn->GetGeomFieldDefn(i)->IsIgnored())
3,279✔
1350
            poFeature->SetGeomFieldDirectly(i, nullptr);
120✔
1351
        else
1352
        {
1353
            OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
3,159✔
1354
            if (poGeom != nullptr)
3,159✔
1355
            {
1356
                poGeom->assignSpatialReference(
2,970✔
1357
                    poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
2,970✔
1358
            }
1359
        }
1360
    }
1361

1362
    if (bPreserveSrcFID)
2,861✔
1363
        poFeature->SetFID(poSrcFeature->GetFID());
102✔
1364
    else
1365
        poFeature->SetFID(nNextFID++);
2,759✔
1366
    return poFeature;
2,861✔
1367
}
1368

1369
/************************************************************************/
1370
/*                          SetIgnoredFields()                          */
1371
/************************************************************************/
1372

1373
OGRErr OGRUnionLayer::SetIgnoredFields(CSLConstList papszFields)
142✔
1374
{
1375
    OGRErr eErr = OGRLayer::SetIgnoredFields(papszFields);
142✔
1376
    if (eErr != OGRERR_NONE)
142✔
1377
        return eErr;
×
1378

1379
    m_aosIgnoredFields = papszFields;
142✔
1380

1381
    return eErr;
142✔
1382
}
1383

1384
/************************************************************************/
1385
/*                             SyncToDisk()                             */
1386
/************************************************************************/
1387

1388
OGRErr OGRUnionLayer::SyncToDisk()
1✔
1389
{
1390
    for (auto &oLayer : m_apoSrcLayers)
3✔
1391
    {
1392
        if (oLayer.bModified)
2✔
1393
        {
1394
            oLayer->SyncToDisk();
1✔
1395
            oLayer.bModified = false;
1✔
1396
        }
1397
    }
1398

1399
    return OGRERR_NONE;
1✔
1400
}
1401

1402
#endif /* #ifndef DOXYGEN_SKIP */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc