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