Skip to content

Commit

Permalink
Merge pull request #11794 from rouault/gdal_vector_filter
Browse files Browse the repository at this point in the history
"gdal vector filter": add --where and --fields; add "gdal vector select"
  • Loading branch information
rouault authored Feb 11, 2025
2 parents 37d0621 + 32d4ef0 commit 51ee293
Show file tree
Hide file tree
Showing 22 changed files with 1,060 additions and 110 deletions.
1 change: 1 addition & 0 deletions apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_library(
gdalalg_vector_read.cpp
gdalalg_vector_filter.cpp
gdalalg_vector_reproject.cpp
gdalalg_vector_select.cpp
gdalalg_vector_sql.cpp
gdalalg_vector_write.cpp
gdalinfo_lib.cpp
Expand Down
2 changes: 2 additions & 0 deletions apps/gdalalg_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "gdalalg_vector_pipeline.h"
#include "gdalalg_vector_filter.h"
#include "gdalalg_vector_reproject.h"
#include "gdalalg_vector_select.h"
#include "gdalalg_vector_sql.h"

/************************************************************************/
Expand All @@ -44,6 +45,7 @@ class GDALVectorAlgorithm final : public GDALAlgorithm
RegisterSubAlgorithm<GDALVectorPipelineAlgorithm>();
RegisterSubAlgorithm<GDALVectorFilterAlgorithmStandalone>();
RegisterSubAlgorithm<GDALVectorReprojectAlgorithmStandalone>();
RegisterSubAlgorithm<GDALVectorSelectAlgorithmStandalone>();
RegisterSubAlgorithm<GDALVectorSQLAlgorithmStandalone>();
}

Expand Down
31 changes: 6 additions & 25 deletions apps/gdalalg_vector_clip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,32 +65,13 @@ GDALVectorClipAlgorithm::GDALVectorClipAlgorithm(bool standaloneStep)

namespace
{
class GDALVectorClipAlgorithmDataset final : public GDALDataset
class GDALVectorClipAlgorithmLayer final
: public OGRLayer,
public OGRGetNextFeatureThroughRaw<GDALVectorClipAlgorithmLayer>
{
std::vector<std::unique_ptr<OGRLayer>> m_layers{};

public:
GDALVectorClipAlgorithmDataset() = default;

void AddLayer(std::unique_ptr<OGRLayer> poLayer)
{
m_layers.push_back(std::move(poLayer));
}

int GetLayerCount() override
{
return static_cast<int>(m_layers.size());
}

OGRLayer *GetLayer(int idx) override
{
return idx >= 0 && idx < GetLayerCount() ? m_layers[idx].get()
: nullptr;
}
};
DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorClipAlgorithmLayer)

class GDALVectorClipAlgorithmLayer final : public OGRLayer
{
public:
GDALVectorClipAlgorithmLayer(OGRLayer *poSrcLayer,
std::unique_ptr<OGRGeometry> poClipGeom)
Expand All @@ -117,7 +98,7 @@ class GDALVectorClipAlgorithmLayer final : public OGRLayer
m_idxInCurGeomColl = 0;
}

OGRFeature *GetNextFeature() override
OGRFeature *GetNextRawFeature()
{
if (m_poSrcFeature && m_poCurGeomColl)
{
Expand Down Expand Up @@ -447,7 +428,7 @@ bool GDALVectorClipAlgorithm::RunStep(GDALProgressFunc, void *)
return false;
}

auto outDS = std::make_unique<GDALVectorClipAlgorithmDataset>();
auto outDS = std::make_unique<GDALVectorPipelineOutputDataset>();
outDS->SetDescription(poSrcDS->GetDescription());

bool ret = true;
Expand Down
27 changes: 25 additions & 2 deletions apps/gdalalg_vector_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

#include "gdal_priv.h"
#include "ogrsf_frmts.h"
#include "ogr_p.h"

#include <set>

//! @cond Doxygen_Suppress

Expand All @@ -30,6 +33,13 @@ GDALVectorFilterAlgorithm::GDALVectorFilterAlgorithm(bool standaloneStep)
standaloneStep)
{
AddBBOXArg(&m_bbox);
AddArg("where", 0,
_("Attribute query in a restricted form of the queries used in the "
"SQL WHERE statement"),
&m_where)
.SetReadFromFileAtSyntaxAllowed()
.SetMetaVar("<WHERE>|@<filename>")
.SetRemoveSQLCommentsEnabled();
}

/************************************************************************/
Expand All @@ -42,15 +52,16 @@ bool GDALVectorFilterAlgorithm::RunStep(GDALProgressFunc, void *)
CPLAssert(m_outputDataset.GetName().empty());
CPLAssert(!m_outputDataset.GetDatasetRef());

auto poSrcDS = m_inputDataset.GetDatasetRef();
const int nLayerCount = poSrcDS->GetLayerCount();

bool ret = true;
if (m_bbox.size() == 4)
{
const double xmin = m_bbox[0];
const double ymin = m_bbox[1];
const double xmax = m_bbox[2];
const double ymax = m_bbox[3];
auto poSrcDS = m_inputDataset.GetDatasetRef();
const int nLayerCount = poSrcDS->GetLayerCount();
for (int i = 0; i < nLayerCount; ++i)
{
auto poSrcLayer = poSrcDS->GetLayer(i);
Expand All @@ -60,6 +71,18 @@ bool GDALVectorFilterAlgorithm::RunStep(GDALProgressFunc, void *)
}
}

if (ret && !m_where.empty())
{
for (int i = 0; i < nLayerCount; ++i)
{
auto poSrcLayer = poSrcDS->GetLayer(i);
ret = ret && (poSrcLayer != nullptr);
if (ret)
ret = poSrcLayer->SetAttributeFilter(m_where.c_str()) ==
OGRERR_NONE;
}
}

if (ret)
{
m_outputDataset.Set(m_inputDataset.GetDatasetRef());
Expand Down
4 changes: 2 additions & 2 deletions apps/gdalalg_vector_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ class GDALVectorFilterAlgorithm /* non final */
public:
static constexpr const char *NAME = "filter";
static constexpr const char *DESCRIPTION = "Filter a vector dataset.";
static constexpr const char *HELP_URL =
"/programs/gdal_vector_pipeline.html";
static constexpr const char *HELP_URL = "/programs/gdal_vector_filter.html";

static std::vector<std::string> GetAliases()
{
Expand All @@ -41,6 +40,7 @@ class GDALVectorFilterAlgorithm /* non final */
bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) override;

std::vector<double> m_bbox{};
std::string m_where{};
};

/************************************************************************/
Expand Down
20 changes: 15 additions & 5 deletions apps/gdalalg_vector_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "gdalalg_vector_clip.h"
#include "gdalalg_vector_filter.h"
#include "gdalalg_vector_reproject.h"
#include "gdalalg_vector_select.h"
#include "gdalalg_vector_sql.h"
#include "gdalalg_vector_write.h"

Expand Down Expand Up @@ -76,7 +77,7 @@ void GDALVectorPipelineStepAlgorithm::AddInputArgs(bool hiddenForCLI)
void GDALVectorPipelineStepAlgorithm::AddOutputArgs(
bool hiddenForCLI, bool shortNameOutputLayerAllowed)
{
AddOutputFormatArg(&m_format)
AddOutputFormatArg(&m_format, true)
.AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
{GDAL_DCAP_VECTOR, GDAL_DCAP_CREATE})
.SetHiddenForCLI(hiddenForCLI);
Expand Down Expand Up @@ -145,13 +146,21 @@ bool GDALVectorPipelineStepAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
m_outputDataset.Set(nullptr);
if (RunStep(nullptr, nullptr))
{
writeAlg.m_inputDataset.Set(m_outputDataset.GetDatasetRef());
if (writeAlg.Run(pfnProgress, pProgressData))
if (m_format == "stream")
{
m_outputDataset.Set(
writeAlg.m_outputDataset.GetDatasetRef());
ret = true;
}
else
{
writeAlg.m_inputDataset.Set(
m_outputDataset.GetDatasetRef());
if (writeAlg.Run(pfnProgress, pProgressData))
{
m_outputDataset.Set(
writeAlg.m_outputDataset.GetDatasetRef());
ret = true;
}
}
}
}

Expand Down Expand Up @@ -185,6 +194,7 @@ GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm()
m_stepRegistry.Register<GDALVectorClipAlgorithm>();
m_stepRegistry.Register<GDALVectorReprojectAlgorithm>();
m_stepRegistry.Register<GDALVectorFilterAlgorithm>();
m_stepRegistry.Register<GDALVectorSelectAlgorithm>();
m_stepRegistry.Register<GDALVectorSQLAlgorithm>();
}

Expand Down
39 changes: 39 additions & 0 deletions apps/gdalalg_vector_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "gdalalgorithm.h"
#include "gdalalg_abstract_pipeline.h"

#include "ogrsf_frmts.h"

//! @cond Doxygen_Suppress

/************************************************************************/
Expand Down Expand Up @@ -106,6 +108,43 @@ class GDALVectorPipelineAlgorithm final
}
};

/************************************************************************/
/* GDALVectorPipelineOutputDataset */
/************************************************************************/

/** Class used by vector pipeline steps to create an output on-the-fly
* dataset where they can store on-the-fly layers.
*/
class GDALVectorPipelineOutputDataset final : public GDALDataset
{
std::vector<std::unique_ptr<OGRLayer>> m_layersToDestroy{};
std::vector<OGRLayer *> m_layers{};

public:
GDALVectorPipelineOutputDataset() = default;

void AddLayer(std::unique_ptr<OGRLayer> poLayer)
{
m_layersToDestroy.push_back(std::move(poLayer));
m_layers.push_back(m_layersToDestroy.back().get());
}

void AddLayer(OGRLayer *poLayer)
{
m_layers.push_back(poLayer);
}

int GetLayerCount() override
{
return static_cast<int>(m_layers.size());
}

OGRLayer *GetLayer(int idx) override
{
return idx >= 0 && idx < GetLayerCount() ? m_layers[idx] : nullptr;
}
};

//! @endcond

#endif
32 changes: 1 addition & 31 deletions apps/gdalalg_vector_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,6 @@ GDALVectorReadAlgorithm::GDALVectorReadAlgorithm()
AddInputArgs(/* hiddenForCLI = */ false);
}

/************************************************************************/
/* GDALVectorReadAlgorithmDataset */
/************************************************************************/

namespace
{
class GDALVectorReadAlgorithmDataset final : public GDALDataset
{
std::vector<OGRLayer *> m_srcLayers{};

public:
GDALVectorReadAlgorithmDataset() = default;

void AddLayer(OGRLayer *poSrcLayer)
{
m_srcLayers.push_back(poSrcLayer);
}

int GetLayerCount() override
{
return static_cast<int>(m_srcLayers.size());
}

OGRLayer *GetLayer(int idx) override
{
return idx >= 0 && idx < GetLayerCount() ? m_srcLayers[idx] : nullptr;
}
};
} // namespace

/************************************************************************/
/* GDALVectorReadAlgorithm::RunStep() */
/************************************************************************/
Expand All @@ -79,7 +49,7 @@ bool GDALVectorReadAlgorithm::RunStep(GDALProgressFunc, void *)
else
{
auto poSrcDS = m_inputDataset.GetDatasetRef();
auto poOutDS = std::make_unique<GDALVectorReadAlgorithmDataset>();
auto poOutDS = std::make_unique<GDALVectorPipelineOutputDataset>();
poOutDS->SetDescription(poSrcDS->GetDescription());
for (const auto &srcLayerName : m_inputLayerNames)
{
Expand Down
33 changes: 1 addition & 32 deletions apps/gdalalg_vector_reproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,6 @@ GDALVectorReprojectAlgorithm::GDALVectorReprojectAlgorithm(bool standaloneStep)
.AddHiddenAlias("t_srs");
}

/************************************************************************/
/* GDALVectorReprojectAlgorithmDataset */
/************************************************************************/

namespace
{
class GDALVectorReprojectAlgorithmDataset final : public GDALDataset
{
std::vector<std::unique_ptr<OGRLayer>> m_layers{};

public:
GDALVectorReprojectAlgorithmDataset() = default;

void AddLayer(std::unique_ptr<OGRLayer> poLayer)
{
m_layers.push_back(std::move(poLayer));
}

int GetLayerCount() override
{
return static_cast<int>(m_layers.size());
}

OGRLayer *GetLayer(int idx) override
{
return idx >= 0 && idx < GetLayerCount() ? m_layers[idx].get()
: nullptr;
}
};
} // namespace

/************************************************************************/
/* GDALVectorReprojectAlgorithm::RunStep() */
/************************************************************************/
Expand All @@ -96,7 +65,7 @@ bool GDALVectorReprojectAlgorithm::RunStep(GDALProgressFunc, void *)
auto poSrcDS = m_inputDataset.GetDatasetRef();

auto reprojectedDataset =
std::make_unique<GDALVectorReprojectAlgorithmDataset>();
std::make_unique<GDALVectorPipelineOutputDataset>();
reprojectedDataset->SetDescription(poSrcDS->GetDescription());

const int nLayerCount = poSrcDS->GetLayerCount();
Expand Down
Loading

0 comments on commit 51ee293

Please sign in to comment.