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