LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_select.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 290 301 96.3 %
Date: 2026-08-22 15:37:05 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  "select" step of "vector pipeline"
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_vector_select.h"
      14             : 
      15             : #include "gdal_priv.h"
      16             : #include "ogrsf_frmts.h"
      17             : #include "ogr_p.h"
      18             : 
      19             : #include <set>
      20             : 
      21             : //! @cond Doxygen_Suppress
      22             : 
      23             : #ifndef _
      24             : #define _(x) (x)
      25             : #endif
      26             : 
      27             : /************************************************************************/
      28             : /*        GDALVectorSelectAlgorithm::GDALVectorSelectAlgorithm()        */
      29             : /************************************************************************/
      30             : 
      31         106 : GDALVectorSelectAlgorithm::GDALVectorSelectAlgorithm(bool standaloneStep)
      32             :     : GDALVectorPipelineStepAlgorithm(
      33             :           NAME, DESCRIPTION, HELP_URL,
      34           0 :           ConstructorOptions()
      35         106 :               .SetStandaloneStep(standaloneStep)
      36         212 :               .SetOutputLayerNameAvailableInPipelineStep(true))
      37             : {
      38         106 :     AddActiveLayerArg(&m_activeLayer);
      39         106 :     if (!standaloneStep)
      40             :     {
      41          40 :         AddOutputLayerNameArg(/* hiddenForCLI = */ false,
      42             :                               /* shortNameOutputLayerAllowed = */ false);
      43             :     }
      44             :     AddArg("fields", 0, _("Fields to select (or exclude if --exclude)"),
      45         212 :            &m_fieldsDeprecated)
      46         106 :         .SetDuplicateValuesAllowed(false)
      47         106 :         .SetPositional()
      48         106 :         .SetHidden();
      49             : 
      50             :     {
      51             :         auto &arg =
      52         212 :             AddArg("field", 0, _("Attribute fields(s) to select"), &m_fields)
      53         106 :                 .SetDuplicateValuesAllowed(false)
      54         106 :                 .SetMetaVar("FIELD");
      55             : 
      56         212 :         SetAutoCompleteFunctionForFieldName(arg, nullptr, true, false,
      57         106 :                                             m_inputDataset);
      58             :     }
      59             : 
      60         106 :     AddArg("geometry", 0, _("Select default geometry field"), &m_defaultGeom);
      61             : 
      62             :     {
      63             :         auto &arg = AddArg("geometry-field", 0,
      64         212 :                            _("Geometry field(s) to select"), &m_geomFields)
      65         106 :                         .SetDuplicateValuesAllowed(false)
      66         106 :                         .SetMetaVar("GEOMETRY-FIELD");
      67         212 :         SetAutoCompleteFunctionForFieldName(arg, nullptr, false, true,
      68         106 :                                             m_inputDataset);
      69             :     }
      70             : 
      71         212 :     AddArg("exclude", 0, _("Exclude specified fields"), &m_exclude)
      72         106 :         .SetDuplicateValuesAllowed(false)
      73         106 :         .SetMutualExclusionGroup("exclude-ignore");
      74             :     AddArg("ignore-missing-fields", 0, _("Ignore missing fields"),
      75         212 :            &m_ignoreMissingFields)
      76         106 :         .SetMutualExclusionGroup("exclude-ignore");
      77             : 
      78         106 :     AddValidationAction(
      79          62 :         [this]()
      80             :         {
      81          53 :             if (!m_outputLayerName.empty() && m_activeLayer.empty() &&
      82           4 :                 m_inputDataset.size() == 1)
      83             :             {
      84           2 :                 auto poSrcDS = m_inputDataset[0].GetDatasetRef();
      85           2 :                 if (poSrcDS && poSrcDS->GetLayerCount() > 1)
      86             :                 {
      87           1 :                     ReportError(CE_Failure, CPLE_IllegalArg,
      88             :                                 "Argument 'output-layer' cannot be used when "
      89             :                                 "the input dataset has multiple layers, unless "
      90             :                                 "argument 'active-layer' is specified");
      91           1 :                     return false;
      92             :                 }
      93             :             }
      94          48 :             return true;
      95             :         });
      96         106 : }
      97             : 
      98             : namespace
      99             : {
     100             : 
     101             : /************************************************************************/
     102             : /*                    GDALVectorSelectAlgorithmLayer                    */
     103             : /************************************************************************/
     104             : 
     105             : class GDALVectorSelectAlgorithmLayer final
     106             :     : public GDALVectorPipelineOutputLayer
     107             : {
     108             :   private:
     109             :     const OGRFeatureDefnRefCountedPtr m_poFeatureDefn;
     110             :     std::vector<int> m_anMapSrcFieldsToDstFields{};
     111             :     std::vector<int> m_anMapDstGeomFieldsToSrcGeomFields{};
     112             : 
     113             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorSelectAlgorithmLayer)
     114             : 
     115             :     std::unique_ptr<OGRFeature>
     116         210 :     TranslateFeature(std::unique_ptr<OGRFeature> poSrcFeature) const
     117             :     {
     118         210 :         auto poFeature = std::make_unique<OGRFeature>(m_poFeatureDefn.get());
     119         210 :         poFeature->SetFID(poSrcFeature->GetFID());
     120         210 :         const auto styleString = poSrcFeature->GetStyleString();
     121         210 :         if (styleString)
     122           0 :             poFeature->SetStyleString(styleString);
     123         210 :         poFeature->SetFieldsFrom(poSrcFeature.get(),
     124             :                                  m_anMapSrcFieldsToDstFields.data(), false,
     125             :                                  false);
     126         210 :         int iDstGeomField = 0;
     127         380 :         for (int nSrcGeomField : m_anMapDstGeomFieldsToSrcGeomFields)
     128             :         {
     129         170 :             poFeature->SetGeomFieldDirectly(
     130             :                 iDstGeomField, poSrcFeature->StealGeometry(nSrcGeomField));
     131         170 :             ++iDstGeomField;
     132             :         }
     133         210 :         return poFeature;
     134             :     }
     135             : 
     136         208 :     bool TranslateFeature(
     137             :         std::unique_ptr<OGRFeature> poSrcFeature,
     138             :         std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override
     139             :     {
     140         208 :         auto poDstFeature = TranslateFeature(std::move(poSrcFeature));
     141         208 :         if (PassesFilters(poDstFeature.get()))
     142             :         {
     143         131 :             apoOutFeatures.push_back(std::move(poDstFeature));
     144             :         }
     145         416 :         return true;
     146             :     }
     147             : 
     148             :   public:
     149          25 :     explicit GDALVectorSelectAlgorithmLayer(
     150             :         OGRLayer &oSrcLayer, const std::string &osOutputLayerName)
     151          25 :         : GDALVectorPipelineOutputLayer(oSrcLayer),
     152             :           m_poFeatureDefn(OGRFeatureDefnRefCountedPtr::makeInstance(
     153          23 :               osOutputLayerName.empty() ? oSrcLayer.GetName()
     154          48 :                                         : osOutputLayerName.c_str()))
     155             :     {
     156          25 :         SetDescription(m_poFeatureDefn->GetName());
     157          25 :         SetMetadata(oSrcLayer.GetMetadata());
     158          25 :         m_poFeatureDefn->SetGeomType(wkbNone);
     159          25 :     }
     160             : 
     161           9 :     bool IncludeFieldsDeprecated(const std::vector<std::string> &selectedFields,
     162             :                                  bool bStrict)
     163             :     {
     164          18 :         std::set<std::string> oSetSelFields;
     165          18 :         std::set<std::string> oSetSelFieldsUC;
     166          24 :         for (const std::string &osFieldName : selectedFields)
     167             :         {
     168          15 :             oSetSelFields.insert(osFieldName);
     169          15 :             oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
     170             :         }
     171             : 
     172          18 :         std::set<std::string> oSetUsedSetFieldsUC;
     173             : 
     174           9 :         const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
     175          35 :         for (const auto poSrcFieldDefn : poSrcLayerDefn->GetFields())
     176             :         {
     177             :             const auto oIter = oSetSelFieldsUC.find(
     178          26 :                 CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     179          26 :             if (oIter != oSetSelFieldsUC.end())
     180             :             {
     181          16 :                 m_anMapSrcFieldsToDstFields.push_back(
     182           8 :                     m_poFeatureDefn->GetFieldCount());
     183          16 :                 OGRFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     184           8 :                 m_poFeatureDefn->AddFieldDefn(&oDstFieldDefn);
     185           8 :                 oSetUsedSetFieldsUC.insert(*oIter);
     186             :             }
     187             :             else
     188             :             {
     189          18 :                 m_anMapSrcFieldsToDstFields.push_back(-1);
     190             :             }
     191             :         }
     192             : 
     193           9 :         const int nSrcGeomFieldCount = poSrcLayerDefn->GetGeomFieldCount();
     194          20 :         for (int i = 0; i < nSrcGeomFieldCount; ++i)
     195             :         {
     196          11 :             const auto poSrcFieldDefn = poSrcLayerDefn->GetGeomFieldDefn(i);
     197             :             const auto oIter = oSetSelFieldsUC.find(
     198          11 :                 CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     199          11 :             if (oIter != oSetSelFieldsUC.end())
     200             :             {
     201           2 :                 m_anMapDstGeomFieldsToSrcGeomFields.push_back(i);
     202           4 :                 OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     203           2 :                 m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
     204           2 :                 oSetUsedSetFieldsUC.insert(*oIter);
     205             :             }
     206             :         }
     207             : 
     208             :         const auto oIter = oSetSelFieldsUC.find(
     209           9 :             CPLString(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME).toupper());
     210          16 :         if (m_poFeatureDefn->GetGeomFieldCount() == 0 &&
     211          16 :             oIter != oSetSelFieldsUC.end() &&
     212           3 :             poSrcLayerDefn->GetGeomFieldCount() == 1)
     213             :         {
     214           3 :             const auto poSrcFieldDefn = poSrcLayerDefn->GetGeomFieldDefn(0);
     215           3 :             m_anMapDstGeomFieldsToSrcGeomFields.push_back(0);
     216           6 :             OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     217           3 :             m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
     218           3 :             oSetUsedSetFieldsUC.insert(*oIter);
     219             :         }
     220             : 
     221           9 :         if (oSetUsedSetFieldsUC.size() != oSetSelFields.size())
     222             :         {
     223           6 :             for (const std::string &osName : oSetSelFields)
     224             :             {
     225          15 :                 if (!cpl::contains(oSetUsedSetFieldsUC,
     226           5 :                                    CPLString(osName).toupper()))
     227             :                 {
     228           4 :                     CPLError(bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
     229             :                              "Field '%s' does not exist in layer '%s'.%s",
     230           2 :                              osName.c_str(), m_srcLayer.GetDescription(),
     231             :                              bStrict ? " You may specify "
     232             :                                        "--ignore-missing-fields to skip it"
     233             :                                      : " It will be ignored");
     234           2 :                     if (bStrict)
     235           1 :                         return false;
     236             :                 }
     237             :             }
     238             :         }
     239             : 
     240           8 :         return true;
     241             :     }
     242             : 
     243           7 :     bool IncludeAttributeFields(const std::vector<std::string> &selectedFields,
     244             :                                 bool bStrict)
     245             :     {
     246          14 :         std::set<std::string> oSetSelFields;
     247          14 :         std::set<std::string> oSetSelFieldsUC;
     248          11 :         for (const std::string &osFieldName : selectedFields)
     249             :         {
     250           4 :             oSetSelFields.insert(osFieldName);
     251           4 :             oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
     252             :         }
     253             : 
     254          14 :         std::set<std::string> oSetUsedSetFieldsUC;
     255             : 
     256           7 :         const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
     257          22 :         for (const auto poSrcFieldDefn : poSrcLayerDefn->GetFields())
     258             :         {
     259             :             const auto oIter = oSetSelFieldsUC.find(
     260          15 :                 CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     261          15 :             if (oIter != oSetSelFieldsUC.end())
     262             :             {
     263           6 :                 m_anMapSrcFieldsToDstFields.push_back(
     264           3 :                     m_poFeatureDefn->GetFieldCount());
     265           6 :                 OGRFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     266           3 :                 m_poFeatureDefn->AddFieldDefn(&oDstFieldDefn);
     267           3 :                 oSetUsedSetFieldsUC.insert(*oIter);
     268             :             }
     269             :             else
     270             :             {
     271          12 :                 m_anMapSrcFieldsToDstFields.push_back(-1);
     272             :             }
     273             :         }
     274             : 
     275           7 :         if (oSetUsedSetFieldsUC.size() != oSetSelFields.size())
     276             :         {
     277           2 :             for (const std::string &osName : oSetSelFields)
     278             :             {
     279           6 :                 if (!cpl::contains(oSetUsedSetFieldsUC,
     280           2 :                                    CPLString(osName).toupper()))
     281             :                 {
     282           2 :                     CPLError(bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
     283             :                              "Field '%s' does not exist in layer '%s'.%s",
     284           1 :                              osName.c_str(), m_srcLayer.GetDescription(),
     285             :                              bStrict ? " You may specify "
     286             :                                        "--ignore-missing-fields to skip it"
     287             :                                      : " It will be ignored");
     288           1 :                     if (bStrict)
     289           1 :                         return false;
     290             :                 }
     291             :             }
     292             :         }
     293             : 
     294           6 :         return true;
     295             :     }
     296             : 
     297           6 :     bool IncludeGeometryFields(const std::vector<std::string> &selectedFields,
     298             :                                bool bStrict)
     299             :     {
     300          12 :         std::set<std::string> oSetSelFields;
     301          12 :         std::set<std::string> oSetSelFieldsUC;
     302          13 :         for (const std::string &osFieldName : selectedFields)
     303             :         {
     304           7 :             oSetSelFields.insert(osFieldName);
     305           7 :             oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
     306             :         }
     307             : 
     308          12 :         std::set<std::string> oSetUsedSetFieldsUC;
     309             : 
     310           6 :         const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
     311             : 
     312           6 :         const int nSrcGeomFieldCount = poSrcLayerDefn->GetGeomFieldCount();
     313          13 :         for (int i = 0; i < nSrcGeomFieldCount; ++i)
     314             :         {
     315           7 :             const auto poSrcFieldDefn = poSrcLayerDefn->GetGeomFieldDefn(i);
     316             :             const auto oIter = oSetSelFieldsUC.find(
     317           7 :                 CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     318           7 :             if (oIter != oSetSelFieldsUC.end())
     319             :             {
     320           1 :                 m_anMapDstGeomFieldsToSrcGeomFields.push_back(i);
     321           2 :                 OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     322           1 :                 m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
     323           1 :                 oSetUsedSetFieldsUC.insert(*oIter);
     324             :             }
     325             :         }
     326             : 
     327             :         const auto oIter = oSetSelFieldsUC.find(
     328           6 :             CPLString(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME).toupper());
     329          11 :         if (m_poFeatureDefn->GetGeomFieldCount() == 0 &&
     330          11 :             oIter != oSetSelFieldsUC.end() &&
     331           4 :             poSrcLayerDefn->GetGeomFieldCount() == 1)
     332             :         {
     333           4 :             const auto poSrcFieldDefn = poSrcLayerDefn->GetGeomFieldDefn(0);
     334           4 :             m_anMapDstGeomFieldsToSrcGeomFields.push_back(0);
     335           8 :             OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     336           4 :             m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
     337           4 :             oSetUsedSetFieldsUC.insert(*oIter);
     338             :         }
     339             : 
     340           6 :         if (oSetUsedSetFieldsUC.size() != oSetSelFields.size())
     341             :         {
     342           4 :             for (const std::string &osName : oSetSelFields)
     343             :             {
     344           9 :                 if (!cpl::contains(oSetUsedSetFieldsUC,
     345           3 :                                    CPLString(osName).toupper()))
     346             :                 {
     347           4 :                     CPLError(bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
     348             :                              "Field '%s' does not exist in layer '%s'.%s",
     349           2 :                              osName.c_str(), m_srcLayer.GetDescription(),
     350             :                              bStrict ? " You may specify "
     351             :                                        "--ignore-missing-fields to skip it"
     352             :                                      : " It will be ignored");
     353           2 :                     if (bStrict)
     354           0 :                         return false;
     355             :                 }
     356             :             }
     357             :         }
     358             : 
     359           6 :         return true;
     360             :     }
     361             : 
     362           5 :     void ExcludeFieldsDeprecated(const std::vector<std::string> &fields)
     363             :     {
     364          10 :         std::set<std::string> oSetSelFields;
     365          10 :         std::set<std::string> oSetSelFieldsUC;
     366          11 :         for (const std::string &osFieldName : fields)
     367             :         {
     368           6 :             oSetSelFields.insert(osFieldName);
     369           6 :             oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
     370             :         }
     371             : 
     372           5 :         const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
     373          17 :         for (const auto poSrcFieldDefn : poSrcLayerDefn->GetFields())
     374             :         {
     375             :             const auto oIter = oSetSelFieldsUC.find(
     376          12 :                 CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     377          12 :             if (oIter != oSetSelFieldsUC.end())
     378             :             {
     379           1 :                 m_anMapSrcFieldsToDstFields.push_back(-1);
     380             :             }
     381             :             else
     382             :             {
     383          22 :                 m_anMapSrcFieldsToDstFields.push_back(
     384          11 :                     m_poFeatureDefn->GetFieldCount());
     385          22 :                 OGRFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     386          11 :                 m_poFeatureDefn->AddFieldDefn(&oDstFieldDefn);
     387             :             }
     388             :         }
     389             : 
     390           0 :         if (oSetSelFieldsUC.find(
     391          10 :                 CPLString(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME).toupper()) !=
     392          16 :                 oSetSelFieldsUC.end() &&
     393           1 :             poSrcLayerDefn->GetGeomFieldCount() == 1)
     394             :         {
     395             :             // exclude default geometry field
     396             :         }
     397             :         else
     398             :         {
     399           4 :             const int nSrcGeomFieldCount = poSrcLayerDefn->GetGeomFieldCount();
     400           9 :             for (int i = 0; i < nSrcGeomFieldCount; ++i)
     401             :             {
     402           5 :                 const auto poSrcFieldDefn = poSrcLayerDefn->GetGeomFieldDefn(i);
     403             :                 const auto oIter = oSetSelFieldsUC.find(
     404           5 :                     CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     405           5 :                 if (oIter == oSetSelFieldsUC.end())
     406             :                 {
     407           3 :                     m_anMapDstGeomFieldsToSrcGeomFields.push_back(i);
     408           6 :                     OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     409           3 :                     m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
     410             :                 }
     411             :             }
     412             :         }
     413           5 :     }
     414             : 
     415           4 :     void ExcludeAttributeFields(const std::vector<std::string> &fields)
     416             :     {
     417           8 :         std::set<std::string> oSetSelFields;
     418           8 :         std::set<std::string> oSetSelFieldsUC;
     419           7 :         for (const std::string &osFieldName : fields)
     420             :         {
     421           3 :             oSetSelFields.insert(osFieldName);
     422           3 :             oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
     423             :         }
     424             : 
     425           4 :         const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
     426          16 :         for (const auto poSrcFieldDefn : poSrcLayerDefn->GetFields())
     427             :         {
     428             :             const auto oIter = oSetSelFieldsUC.find(
     429          12 :                 CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     430          12 :             if (oIter != oSetSelFieldsUC.end())
     431             :             {
     432           1 :                 m_anMapSrcFieldsToDstFields.push_back(-1);
     433             :             }
     434             :             else
     435             :             {
     436          22 :                 m_anMapSrcFieldsToDstFields.push_back(
     437          11 :                     m_poFeatureDefn->GetFieldCount());
     438          22 :                 OGRFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     439          11 :                 m_poFeatureDefn->AddFieldDefn(&oDstFieldDefn);
     440             :             }
     441             :         }
     442           4 :     }
     443             : 
     444           4 :     void ExcludeGeometryFields(const std::vector<std::string> &fields)
     445             :     {
     446           8 :         std::set<std::string> oSetSelFields;
     447           8 :         std::set<std::string> oSetSelFieldsUC;
     448           7 :         for (const std::string &osFieldName : fields)
     449             :         {
     450           3 :             oSetSelFields.insert(osFieldName);
     451           3 :             oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
     452             :         }
     453             : 
     454           4 :         const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
     455             : 
     456           0 :         if (oSetSelFieldsUC.find(
     457           8 :                 CPLString(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME).toupper()) !=
     458          13 :                 oSetSelFieldsUC.end() &&
     459           1 :             poSrcLayerDefn->GetGeomFieldCount() == 1)
     460             :         {
     461             :             // exclude default geometry field
     462             :         }
     463             :         else
     464             :         {
     465           3 :             const int nSrcGeomFieldCount = poSrcLayerDefn->GetGeomFieldCount();
     466           6 :             for (int i = 0; i < nSrcGeomFieldCount; ++i)
     467             :             {
     468           3 :                 const auto poSrcFieldDefn = poSrcLayerDefn->GetGeomFieldDefn(i);
     469             :                 const auto oIter = oSetSelFieldsUC.find(
     470           3 :                     CPLString(poSrcFieldDefn->GetNameRef()).toupper());
     471           3 :                 if (oIter == oSetSelFieldsUC.end())
     472             :                 {
     473           2 :                     m_anMapDstGeomFieldsToSrcGeomFields.push_back(i);
     474           4 :                     OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
     475           2 :                     m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
     476             :                 }
     477             :             }
     478             :         }
     479           4 :     }
     480             : 
     481         135 :     const OGRFeatureDefn *GetLayerDefn() const override
     482             :     {
     483         135 :         return m_poFeatureDefn.get();
     484             :     }
     485             : 
     486           6 :     GIntBig GetFeatureCount(int bForce) override
     487             :     {
     488           6 :         if (!m_poAttrQuery && !m_poFilterGeom)
     489           2 :             return m_srcLayer.GetFeatureCount(bForce);
     490           4 :         return OGRLayer::GetFeatureCount(bForce);
     491             :     }
     492             : 
     493           4 :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
     494             :                       bool bForce) override
     495             :     {
     496           4 :         return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
     497             :     }
     498             : 
     499           4 :     OGRFeature *GetFeature(GIntBig nFID) override
     500             :     {
     501             :         auto poSrcFeature =
     502           8 :             std::unique_ptr<OGRFeature>(m_srcLayer.GetFeature(nFID));
     503           4 :         if (!poSrcFeature)
     504           2 :             return nullptr;
     505           2 :         return TranslateFeature(std::move(poSrcFeature)).release();
     506             :     }
     507             : 
     508          28 :     int TestCapability(const char *pszCap) const override
     509             :     {
     510          28 :         if (EQUAL(pszCap, OLCRandomRead) || EQUAL(pszCap, OLCCurveGeometries) ||
     511          28 :             EQUAL(pszCap, OLCMeasuredGeometries) ||
     512          28 :             EQUAL(pszCap, OLCZGeometries) ||
     513          28 :             (EQUAL(pszCap, OLCFastFeatureCount) && !m_poAttrQuery &&
     514           4 :              !m_poFilterGeom) ||
     515          26 :             EQUAL(pszCap, OLCFastGetExtent) || EQUAL(pszCap, OLCStringsAsUTF8))
     516             :         {
     517           5 :             return m_srcLayer.TestCapability(pszCap);
     518             :         }
     519          23 :         return false;
     520             :     }
     521             : };
     522             : 
     523             : }  // namespace
     524             : 
     525             : /************************************************************************/
     526             : /*                 GDALVectorSelectAlgorithm::RunStep()                 */
     527             : /************************************************************************/
     528             : 
     529          26 : bool GDALVectorSelectAlgorithm::RunStep(GDALPipelineStepRunContext &)
     530             : {
     531          26 :     auto poSrcDS = m_inputDataset[0].GetDatasetRef();
     532          26 :     CPLAssert(poSrcDS);
     533             : 
     534          26 :     CPLAssert(m_outputDataset.GetName().empty());
     535          26 :     CPLAssert(!m_outputDataset.GetDatasetRef());
     536             : 
     537          52 :     auto outDS = std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS);
     538             : 
     539          26 :     if (!m_fieldsDeprecated.empty())
     540             :     {
     541          14 :         if (!m_fields.empty() || !m_geomFields.empty())
     542             :         {
     543           0 :             ReportError(CE_Failure, CPLE_AppDefined,
     544             :                         "Deprecated --fields argument cannot be used together "
     545             :                         "with --field or --geometry-field");
     546           0 :             return false;
     547             :         }
     548          14 :         CPLErrorOnce(CE_Warning, CPLE_AppDefined,
     549             :                      "--fields is deprecated and will be removed in GDAL 3.15, "
     550             :                      "use --field and/or --geometry-field instead");
     551             : 
     552          14 :         if (m_defaultGeom &&
     553           0 :             std::find(m_fieldsDeprecated.begin(), m_fieldsDeprecated.end(),
     554           0 :                       OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME) ==
     555          14 :                 m_fieldsDeprecated.end())
     556             :         {
     557             :             m_fieldsDeprecated.emplace_back(
     558           0 :                 OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
     559             :         }
     560             :     }
     561             :     else
     562             :     {
     563          14 :         if (m_defaultGeom && std::find(m_geomFields.begin(), m_geomFields.end(),
     564           2 :                                        OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME) ==
     565          14 :                                  m_geomFields.end())
     566             :         {
     567           2 :             m_geomFields.emplace_back(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
     568             :         }
     569             :     }
     570             : 
     571          45 :     if (m_fieldsDeprecated.empty() && m_fields.empty() &&
     572          45 :         m_geomFields.empty() && !m_defaultGeom)
     573             :     {
     574           1 :         ReportError(CE_Failure, CPLE_AppDefined,
     575             :                     "Must specify --field, --geometry-field and/or --geometry");
     576           1 :         return false;
     577             :     }
     578             : 
     579          51 :     for (auto &&poSrcLayer : poSrcDS->GetLayers())
     580             :     {
     581          34 :         if (m_activeLayer.empty() ||
     582           6 :             m_activeLayer == poSrcLayer->GetDescription())
     583             :         {
     584             :             auto poLayer = std::make_unique<GDALVectorSelectAlgorithmLayer>(
     585          25 :                 *poSrcLayer, m_outputLayerName);
     586          25 :             if (m_exclude)
     587             :             {
     588           9 :                 if (!m_fieldsDeprecated.empty())
     589             :                 {
     590           5 :                     poLayer->ExcludeFieldsDeprecated(m_fieldsDeprecated);
     591             :                 }
     592             :                 else
     593             :                 {
     594           4 :                     poLayer->ExcludeAttributeFields(m_fields);
     595           4 :                     poLayer->ExcludeGeometryFields(m_geomFields);
     596             :                 }
     597             :             }
     598             :             else
     599             :             {
     600          16 :                 if (!m_fieldsDeprecated.empty())
     601             :                 {
     602          18 :                     if (!poLayer->IncludeFieldsDeprecated(
     603           9 :                             m_fieldsDeprecated, !m_ignoreMissingFields))
     604           1 :                         return false;
     605             :                 }
     606             :                 else
     607             :                 {
     608          14 :                     if (!poLayer->IncludeAttributeFields(
     609           7 :                             m_fields, !m_ignoreMissingFields))
     610           1 :                         return false;
     611          12 :                     if (!poLayer->IncludeGeometryFields(m_geomFields,
     612           6 :                                                         !m_ignoreMissingFields))
     613           0 :                         return false;
     614             :                 }
     615             :             }
     616          23 :             outDS->AddLayer(*poSrcLayer, std::move(poLayer));
     617             :         }
     618             :         else
     619             :         {
     620           6 :             outDS->AddLayer(
     621             :                 *poSrcLayer,
     622           6 :                 std::make_unique<GDALVectorPipelinePassthroughLayer>(
     623             :                     *poSrcLayer));
     624             :         }
     625             :     }
     626             : 
     627          23 :     m_outputDataset.Set(std::move(outDS));
     628             : 
     629          23 :     return true;
     630             : }
     631             : 
     632             : GDALVectorSelectAlgorithmStandalone::~GDALVectorSelectAlgorithmStandalone() =
     633             :     default;
     634             : 
     635             : //! @endcond

Generated by: LCOV version 1.14