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