LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/generic - ogrunionlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 561 670 83.7 %
Date: 2025-05-31 00:00:17 Functions: 34 36 94.4 %

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

Generated by: LCOV version 1.14