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