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

Generated by: LCOV version 1.14