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 88 : GDALVectorSelectAlgorithm::GDALVectorSelectAlgorithm(bool standaloneStep)
32 : : GDALVectorPipelineStepAlgorithm(
33 : NAME, DESCRIPTION, HELP_URL,
34 0 : ConstructorOptions()
35 88 : .SetStandaloneStep(standaloneStep)
36 176 : .SetOutputLayerNameAvailableInPipelineStep(true))
37 : {
38 88 : AddActiveLayerArg(&m_activeLayer);
39 88 : if (!standaloneStep)
40 : {
41 37 : AddOutputLayerNameArg(/* hiddenForCLI = */ false,
42 : /* shortNameOutputLayerAllowed = */ false);
43 : }
44 : AddArg("fields", 0, _("Fields to select (or exclude if --exclude)"),
45 176 : &m_fields)
46 88 : .SetDuplicateValuesAllowed(false)
47 88 : .SetPositional()
48 88 : .SetRequired();
49 176 : AddArg("exclude", 0, _("Exclude specified fields"), &m_exclude)
50 88 : .SetDuplicateValuesAllowed(false)
51 88 : .SetMutualExclusionGroup("exclude-ignore");
52 : AddArg("ignore-missing-fields", 0, _("Ignore missing fields"),
53 176 : &m_ignoreMissingFields)
54 88 : .SetMutualExclusionGroup("exclude-ignore");
55 :
56 88 : AddValidationAction(
57 37 : [this]()
58 : {
59 28 : if (!m_outputLayerName.empty() && m_activeLayer.empty() &&
60 4 : m_inputDataset.size() == 1)
61 : {
62 2 : auto poSrcDS = m_inputDataset[0].GetDatasetRef();
63 2 : if (poSrcDS && poSrcDS->GetLayerCount() > 1)
64 : {
65 1 : ReportError(CE_Failure, CPLE_IllegalArg,
66 : "Argument 'output-layer' cannot be used when "
67 : "the input dataset has multiple layers, unless "
68 : "argument 'active-layer' is specified");
69 1 : return false;
70 : }
71 : }
72 23 : return true;
73 : });
74 88 : }
75 :
76 : namespace
77 : {
78 :
79 : /************************************************************************/
80 : /* GDALVectorSelectAlgorithmLayer */
81 : /************************************************************************/
82 :
83 : class GDALVectorSelectAlgorithmLayer final
84 : : public GDALVectorPipelineOutputLayer
85 : {
86 : private:
87 : const OGRFeatureDefnRefCountedPtr m_poFeatureDefn;
88 : std::vector<int> m_anMapSrcFieldsToDstFields{};
89 : std::vector<int> m_anMapDstGeomFieldsToSrcGeomFields{};
90 :
91 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorSelectAlgorithmLayer)
92 :
93 : std::unique_ptr<OGRFeature>
94 102 : TranslateFeature(std::unique_ptr<OGRFeature> poSrcFeature) const
95 : {
96 102 : auto poFeature = std::make_unique<OGRFeature>(m_poFeatureDefn.get());
97 102 : poFeature->SetFID(poSrcFeature->GetFID());
98 102 : const auto styleString = poSrcFeature->GetStyleString();
99 102 : if (styleString)
100 0 : poFeature->SetStyleString(styleString);
101 102 : poFeature->SetFieldsFrom(poSrcFeature.get(),
102 : m_anMapSrcFieldsToDstFields.data(), false,
103 : false);
104 102 : int iDstGeomField = 0;
105 184 : for (int nSrcGeomField : m_anMapDstGeomFieldsToSrcGeomFields)
106 : {
107 82 : poFeature->SetGeomFieldDirectly(
108 : iDstGeomField, poSrcFeature->StealGeometry(nSrcGeomField));
109 82 : ++iDstGeomField;
110 : }
111 102 : return poFeature;
112 : }
113 :
114 101 : void TranslateFeature(
115 : std::unique_ptr<OGRFeature> poSrcFeature,
116 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override
117 : {
118 101 : apoOutFeatures.push_back(TranslateFeature(std::move(poSrcFeature)));
119 101 : }
120 :
121 : public:
122 11 : explicit GDALVectorSelectAlgorithmLayer(
123 : OGRLayer &oSrcLayer, const std::string &osOutputLayerName)
124 11 : : GDALVectorPipelineOutputLayer(oSrcLayer),
125 : m_poFeatureDefn(OGRFeatureDefnRefCountedPtr::makeInstance(
126 9 : osOutputLayerName.empty() ? oSrcLayer.GetName()
127 20 : : osOutputLayerName.c_str()))
128 : {
129 11 : SetDescription(m_poFeatureDefn->GetName());
130 11 : SetMetadata(oSrcLayer.GetMetadata());
131 11 : m_poFeatureDefn->SetGeomType(wkbNone);
132 11 : }
133 :
134 7 : bool IncludeFields(const std::vector<std::string> &selectedFields,
135 : bool bStrict)
136 : {
137 14 : std::set<std::string> oSetSelFields;
138 14 : std::set<std::string> oSetSelFieldsUC;
139 18 : for (const std::string &osFieldName : selectedFields)
140 : {
141 11 : oSetSelFields.insert(osFieldName);
142 11 : oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
143 : }
144 :
145 14 : std::set<std::string> oSetUsedSetFieldsUC;
146 :
147 7 : const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
148 23 : for (const auto poSrcFieldDefn : poSrcLayerDefn->GetFields())
149 : {
150 : const auto oIter = oSetSelFieldsUC.find(
151 16 : CPLString(poSrcFieldDefn->GetNameRef()).toupper());
152 16 : if (oIter != oSetSelFieldsUC.end())
153 : {
154 12 : m_anMapSrcFieldsToDstFields.push_back(
155 6 : m_poFeatureDefn->GetFieldCount());
156 12 : OGRFieldDefn oDstFieldDefn(*poSrcFieldDefn);
157 6 : m_poFeatureDefn->AddFieldDefn(&oDstFieldDefn);
158 6 : oSetUsedSetFieldsUC.insert(*oIter);
159 : }
160 : else
161 : {
162 10 : m_anMapSrcFieldsToDstFields.push_back(-1);
163 : }
164 : }
165 :
166 15 : for (const auto poSrcFieldDefn : poSrcLayerDefn->GetGeomFields())
167 : {
168 : const auto oIter = oSetSelFieldsUC.find(
169 8 : CPLString(poSrcFieldDefn->GetNameRef()).toupper());
170 8 : if (oIter != oSetSelFieldsUC.end())
171 : {
172 2 : m_anMapDstGeomFieldsToSrcGeomFields.push_back(
173 1 : m_poFeatureDefn->GetGeomFieldCount());
174 2 : OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
175 1 : m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
176 1 : oSetUsedSetFieldsUC.insert(*oIter);
177 : }
178 : }
179 :
180 : const auto oIter = oSetSelFieldsUC.find(
181 7 : CPLString(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME).toupper());
182 13 : if (m_poFeatureDefn->GetGeomFieldCount() == 0 &&
183 13 : oIter != oSetSelFieldsUC.end() &&
184 2 : poSrcLayerDefn->GetGeomFieldCount() == 1)
185 : {
186 2 : const auto poSrcFieldDefn = poSrcLayerDefn->GetGeomFieldDefn(0);
187 2 : m_anMapDstGeomFieldsToSrcGeomFields.push_back(0);
188 4 : OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
189 2 : m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
190 2 : oSetUsedSetFieldsUC.insert(*oIter);
191 : }
192 :
193 7 : if (oSetUsedSetFieldsUC.size() != oSetSelFields.size())
194 : {
195 6 : for (const std::string &osName : oSetSelFields)
196 : {
197 15 : if (!cpl::contains(oSetUsedSetFieldsUC,
198 5 : CPLString(osName).toupper()))
199 : {
200 4 : CPLError(bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
201 : "Field '%s' does not exist in layer '%s'.%s",
202 2 : osName.c_str(), m_srcLayer.GetDescription(),
203 : bStrict ? " You may specify "
204 : "--ignore-missing-fields to skip it"
205 : : " It will be ignored");
206 2 : if (bStrict)
207 1 : return false;
208 : }
209 : }
210 : }
211 :
212 6 : return true;
213 : }
214 :
215 4 : void ExcludeFields(const std::vector<std::string> &fields)
216 : {
217 8 : std::set<std::string> oSetSelFields;
218 8 : std::set<std::string> oSetSelFieldsUC;
219 9 : for (const std::string &osFieldName : fields)
220 : {
221 5 : oSetSelFields.insert(osFieldName);
222 5 : oSetSelFieldsUC.insert(CPLString(osFieldName).toupper());
223 : }
224 :
225 4 : const auto poSrcLayerDefn = m_srcLayer.GetLayerDefn();
226 16 : for (const auto poSrcFieldDefn : poSrcLayerDefn->GetFields())
227 : {
228 : const auto oIter = oSetSelFieldsUC.find(
229 12 : CPLString(poSrcFieldDefn->GetNameRef()).toupper());
230 12 : if (oIter != oSetSelFieldsUC.end())
231 : {
232 1 : m_anMapSrcFieldsToDstFields.push_back(-1);
233 : }
234 : else
235 : {
236 22 : m_anMapSrcFieldsToDstFields.push_back(
237 11 : m_poFeatureDefn->GetFieldCount());
238 22 : OGRFieldDefn oDstFieldDefn(*poSrcFieldDefn);
239 11 : m_poFeatureDefn->AddFieldDefn(&oDstFieldDefn);
240 : }
241 : }
242 :
243 0 : if (oSetSelFieldsUC.find(
244 8 : CPLString(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME).toupper()) !=
245 13 : oSetSelFieldsUC.end() &&
246 1 : poSrcLayerDefn->GetGeomFieldCount() == 1)
247 : {
248 : // exclude default geometry field
249 : }
250 : else
251 : {
252 6 : for (const auto poSrcFieldDefn : poSrcLayerDefn->GetGeomFields())
253 : {
254 : const auto oIter = oSetSelFieldsUC.find(
255 3 : CPLString(poSrcFieldDefn->GetNameRef()).toupper());
256 3 : if (oIter == oSetSelFieldsUC.end())
257 : {
258 4 : m_anMapDstGeomFieldsToSrcGeomFields.push_back(
259 2 : m_poFeatureDefn->GetGeomFieldCount());
260 4 : OGRGeomFieldDefn oDstFieldDefn(*poSrcFieldDefn);
261 2 : m_poFeatureDefn->AddGeomFieldDefn(&oDstFieldDefn);
262 : }
263 : }
264 : }
265 4 : }
266 :
267 52 : const OGRFeatureDefn *GetLayerDefn() const override
268 : {
269 52 : return m_poFeatureDefn.get();
270 : }
271 :
272 3 : GIntBig GetFeatureCount(int bForce) override
273 : {
274 3 : if (!m_poAttrQuery && !m_poFilterGeom)
275 1 : return m_srcLayer.GetFeatureCount(bForce);
276 2 : return OGRLayer::GetFeatureCount(bForce);
277 : }
278 :
279 2 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
280 : bool bForce) override
281 : {
282 2 : return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
283 : }
284 :
285 2 : OGRFeature *GetFeature(GIntBig nFID) override
286 : {
287 : auto poSrcFeature =
288 4 : std::unique_ptr<OGRFeature>(m_srcLayer.GetFeature(nFID));
289 2 : if (!poSrcFeature)
290 1 : return nullptr;
291 1 : return TranslateFeature(std::move(poSrcFeature)).release();
292 : }
293 :
294 12 : int TestCapability(const char *pszCap) const override
295 : {
296 12 : if (EQUAL(pszCap, OLCRandomRead) || EQUAL(pszCap, OLCCurveGeometries) ||
297 12 : EQUAL(pszCap, OLCMeasuredGeometries) ||
298 12 : EQUAL(pszCap, OLCZGeometries) ||
299 12 : (EQUAL(pszCap, OLCFastFeatureCount) && !m_poAttrQuery &&
300 2 : !m_poFilterGeom) ||
301 11 : EQUAL(pszCap, OLCFastGetExtent) || EQUAL(pszCap, OLCStringsAsUTF8))
302 : {
303 2 : return m_srcLayer.TestCapability(pszCap);
304 : }
305 10 : return false;
306 : }
307 : };
308 :
309 : } // namespace
310 :
311 : /************************************************************************/
312 : /* GDALVectorSelectAlgorithm::RunStep() */
313 : /************************************************************************/
314 :
315 11 : bool GDALVectorSelectAlgorithm::RunStep(GDALPipelineStepRunContext &)
316 : {
317 11 : auto poSrcDS = m_inputDataset[0].GetDatasetRef();
318 11 : CPLAssert(poSrcDS);
319 :
320 11 : CPLAssert(m_outputDataset.GetName().empty());
321 11 : CPLAssert(!m_outputDataset.GetDatasetRef());
322 :
323 22 : auto outDS = std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS);
324 :
325 23 : for (auto &&poSrcLayer : poSrcDS->GetLayers())
326 : {
327 17 : if (m_activeLayer.empty() ||
328 4 : m_activeLayer == poSrcLayer->GetDescription())
329 : {
330 : auto poLayer = std::make_unique<GDALVectorSelectAlgorithmLayer>(
331 11 : *poSrcLayer, m_outputLayerName);
332 11 : if (m_exclude)
333 : {
334 4 : poLayer->ExcludeFields(m_fields);
335 : }
336 : else
337 : {
338 7 : if (!poLayer->IncludeFields(m_fields, !m_ignoreMissingFields))
339 1 : return false;
340 : }
341 10 : outDS->AddLayer(*poSrcLayer, std::move(poLayer));
342 : }
343 : else
344 : {
345 4 : outDS->AddLayer(
346 : *poSrcLayer,
347 4 : std::make_unique<GDALVectorPipelinePassthroughLayer>(
348 : *poSrcLayer));
349 : }
350 : }
351 :
352 10 : m_outputDataset.Set(std::move(outDS));
353 :
354 10 : return true;
355 : }
356 :
357 : GDALVectorSelectAlgorithmStandalone::~GDALVectorSelectAlgorithmStandalone() =
358 : default;
359 :
360 : //! @endcond
|