Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: gdal "vector info" subcommand
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_info.h"
14 :
15 : #include "cpl_conv.h"
16 : #include "gdal_priv.h"
17 : #include "gdal_utils.h"
18 :
19 : //! @cond Doxygen_Suppress
20 :
21 : #ifndef _
22 : #define _(x) (x)
23 : #endif
24 :
25 : /************************************************************************/
26 : /* GDALVectorInfoAlgorithm::GDALVectorInfoAlgorithm() */
27 : /************************************************************************/
28 :
29 215 : GDALVectorInfoAlgorithm::GDALVectorInfoAlgorithm(bool standaloneStep)
30 : : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
31 0 : ConstructorOptions()
32 215 : .SetStandaloneStep(standaloneStep)
33 215 : .SetInputDatasetMaxCount(1)
34 430 : .SetAddDefaultArguments(false))
35 : {
36 215 : AddOutputFormatArg(&m_format).SetChoices("json", "text");
37 215 : AddOpenOptionsArg(&m_openOptions).SetHiddenForCLI(!standaloneStep);
38 215 : AddInputFormatsArg(&m_inputFormats)
39 645 : .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_VECTOR})
40 215 : .SetHiddenForCLI(!standaloneStep);
41 :
42 : auto &datasetArg =
43 215 : AddInputDatasetArg(&m_inputDataset, GDAL_OF_VECTOR).AddAlias("dataset");
44 215 : if (!standaloneStep)
45 70 : datasetArg.SetHidden();
46 215 : auto &layerArg = AddLayerNameArg(&m_layerNames)
47 430 : .SetMutualExclusionGroup("layer-sql")
48 215 : .AddAlias("layer");
49 215 : SetAutoCompleteFunctionForLayerName(layerArg, datasetArg);
50 : auto &argFeature =
51 : AddArg(
52 : "features", 0,
53 : _("List all features (beware of RAM consumption on large layers)"),
54 430 : &m_listFeatures)
55 215 : .SetMutualExclusionGroup("summary-features");
56 : AddArg("summary", 0, _("List the layer names and the geometry type"),
57 430 : &m_summaryOnly)
58 215 : .SetMutualExclusionGroup("summary-features");
59 : AddArg("limit", 0,
60 : _("Limit the number of features per layer (implies --features)"),
61 430 : &m_limit)
62 215 : .SetMinValueIncluded(0)
63 430 : .SetMetaVar("FEATURE-COUNT")
64 217 : .AddAction([&argFeature]() { argFeature.Set(true); });
65 : AddArg("sql", 0,
66 : _("Execute the indicated SQL statement and return the result"),
67 430 : &m_sql)
68 215 : .SetReadFromFileAtSyntaxAllowed()
69 430 : .SetMetaVar("<statement>|@<filename>")
70 215 : .SetRemoveSQLCommentsEnabled()
71 215 : .SetMutualExclusionGroup("layer-sql");
72 : AddArg("where", 0,
73 : _("Attribute query in a restricted form of the queries used in the "
74 : "SQL WHERE statement"),
75 430 : &m_where)
76 215 : .SetReadFromFileAtSyntaxAllowed()
77 430 : .SetMetaVar("<WHERE>|@<filename>")
78 215 : .SetRemoveSQLCommentsEnabled();
79 430 : AddArg("fid", 0, _("Feature identifier"), &m_fid)
80 430 : .SetMetaVar("FID")
81 215 : .SetMutualExclusionGroup("layer-sql");
82 215 : AddArg("dialect", 0, _("SQL dialect"), &m_dialect);
83 215 : AddOutputStringArg(&m_output);
84 215 : AddStdoutArg(&m_stdout);
85 : AddArg("crs-format", 0, _("Which format to use to report CRS"),
86 430 : &m_crsFormat)
87 215 : .SetChoices("AUTO", "WKT2", "PROJJSON")
88 215 : .SetDefault(m_crsFormat)
89 215 : .SetCategory(GAAC_ESOTERIC);
90 :
91 215 : AddValidationAction(
92 149 : [this]()
93 : {
94 72 : if (!m_sql.empty() && !m_where.empty())
95 : {
96 1 : ReportError(CE_Failure, CPLE_NotSupported,
97 : "Option 'sql' and 'where' are mutually exclusive");
98 1 : return false;
99 : }
100 :
101 71 : if (m_crsFormat != "AUTO" && m_format == "json")
102 : {
103 0 : ReportError(CE_Failure, CPLE_AppDefined,
104 : "'crs-format' cannot be set when 'format' is set "
105 : "to 'json'");
106 0 : return false;
107 : }
108 :
109 71 : return true;
110 : });
111 215 : }
112 :
113 : /************************************************************************/
114 : /* GDALVectorInfoAlgorithm::RunStep() */
115 : /************************************************************************/
116 :
117 32 : bool GDALVectorInfoAlgorithm::RunStep(GDALPipelineStepRunContext &)
118 : {
119 32 : CPLAssert(m_inputDataset.size() == 1);
120 32 : auto poSrcDS = m_inputDataset[0].GetDatasetRef();
121 32 : CPLAssert(poSrcDS);
122 :
123 32 : if (m_format.empty())
124 19 : m_format = IsCalledFromCommandLine() ? "text" : "json";
125 :
126 64 : CPLStringList aosOptions;
127 :
128 32 : aosOptions.AddString("--cli");
129 32 : aosOptions.AddString("--crs-format=" + m_crsFormat);
130 :
131 32 : if (m_format == "json")
132 : {
133 18 : aosOptions.AddString("-json");
134 : }
135 :
136 32 : if (m_summaryOnly)
137 : {
138 4 : aosOptions.AddString("-summary");
139 : }
140 28 : else if (m_listFeatures)
141 : {
142 5 : aosOptions.AddString("-features");
143 : }
144 :
145 32 : if (!m_sql.empty())
146 : {
147 2 : aosOptions.AddString("-sql");
148 2 : aosOptions.AddString(m_sql.c_str());
149 : }
150 32 : if (!m_where.empty())
151 : {
152 2 : aosOptions.AddString("-where");
153 2 : aosOptions.AddString(m_where.c_str());
154 : }
155 32 : if (m_fid >= 0)
156 : {
157 1 : aosOptions.AddString("-fid");
158 1 : aosOptions.AddString(CPLSPrintf("%d", m_fid));
159 : }
160 32 : if (!m_dialect.empty())
161 : {
162 2 : aosOptions.AddString("-dialect");
163 2 : aosOptions.AddString(m_dialect.c_str());
164 : }
165 32 : if (m_stdout)
166 : {
167 6 : aosOptions.AddString("-stdout");
168 : }
169 32 : if (m_limit > 0)
170 : {
171 1 : aosOptions.AddString("-limit");
172 1 : aosOptions.AddString(std::to_string(m_limit));
173 : }
174 :
175 : // Must be last, as positional
176 32 : aosOptions.AddString("dummy");
177 33 : for (const std::string &name : m_layerNames)
178 1 : aosOptions.AddString(name.c_str());
179 :
180 32 : if (m_layerNames.empty())
181 : {
182 31 : aosOptions.AddString("-al");
183 : }
184 :
185 : GDALVectorInfoOptions *psInfo =
186 32 : GDALVectorInfoOptionsNew(aosOptions.List(), nullptr);
187 :
188 32 : char *ret = GDALVectorInfo(GDALDataset::ToHandle(poSrcDS), psInfo);
189 32 : GDALVectorInfoOptionsFree(psInfo);
190 32 : if (!ret)
191 0 : return false;
192 :
193 32 : m_output = ret;
194 32 : CPLFree(ret);
195 :
196 32 : return true;
197 : }
198 :
199 : GDALVectorInfoAlgorithmStandalone::~GDALVectorInfoAlgorithmStandalone() =
200 : default;
201 :
202 : //! @endcond
|