LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/generic - ogrunionlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 569 677 84.0 %
Date: 2024-11-21 22:18:42 Functions: 36 38 94.7 %

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

Generated by: LCOV version 1.14