@@ -385,7 +385,8 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
385385 };
386386
387387 const auto SetCurStepAlg =
388- [this , bIsGenericPipeline](Step &curStep, const std::string &algName)
388+ [this , bIsGenericPipeline](Step &curStep, const std::string &algName,
389+ bool firstStep)
389390 {
390391 if (bIsGenericPipeline)
391392 {
@@ -410,6 +411,10 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
410411 algName.c_str ());
411412 return false ;
412413 }
414+ // We don't want to accept '_PIPE_' dataset placeholder for the first
415+ // step of a pipeline.
416+ curStep.alg ->m_inputDatasetCanBeOmitted =
417+ !firstStep || !m_bExpectReadStep;
413418 curStep.alg ->SetCallPath ({algName});
414419 curStep.alg ->SetReferencePathForRelativePaths (
415420 GetReferencePathForRelativePaths ());
@@ -533,7 +538,7 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
533538 else if (arg.find (" +gdal=" ) == 0 )
534539 {
535540 const std::string algName = arg.substr (strlen (" +gdal=" ));
536- if (!SetCurStepAlg (curStep, algName))
541+ if (!SetCurStepAlg (curStep, algName, steps. size () == 1 ))
537542 return false ;
538543 }
539544#endif
@@ -544,7 +549,7 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
544549 if (!algName.empty () && algName[0 ] == ' +' )
545550 algName = algName.substr (1 );
546551#endif
547- if (!SetCurStepAlg (curStep, algName))
552+ if (!SetCurStepAlg (curStep, algName, steps. size () == 1 ))
548553 return false ;
549554 }
550555 else
@@ -562,6 +567,8 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
562567 return false ;
563568 }
564569 curStep.isSubAlgorithm = true ;
570+ subAlg->m_inputDatasetCanBeOmitted =
571+ steps.size () > 1 || !m_bExpectReadStep;
565572 curStep.alg = std::move (subAlg);
566573 continue ;
567574 }
@@ -609,6 +616,7 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
609616 steps.back ().alg = GetStepAlg (
610617 std::string (GDALRasterWriteAlgorithm::NAME)
611618 .append (bIsGenericPipeline ? RASTER_SUFFIX : " " ));
619+ steps.back ().alg ->m_inputDatasetCanBeOmitted = true ;
612620 }
613621
614622 // Remove "--output-format=stream" and "streamed_dataset" if found
@@ -1047,6 +1055,8 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
10471055 (nDatasetType == 0 || nDatasetType == GDAL_OF_VECTOR))
10481056 {
10491057 step.alg = std::move (algVector);
1058+ step.alg ->m_inputDatasetCanBeOmitted =
1059+ !firstStep || !m_bExpectReadStep;
10501060 step.alg ->m_skipValidationInParseCommandLine = true ;
10511061 ret = step.alg ->ParseCommandLineArguments (step.args );
10521062 if (ret)
@@ -1240,6 +1250,8 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
12401250 SetWriteArgFromPipeline ();
12411251 }
12421252
1253+ steps[i].alg ->m_inputDatasetCanBeOmitted =
1254+ i > 0 || !m_bExpectReadStep;
12431255 steps[i].alg ->m_skipValidationInParseCommandLine = true ;
12441256 if (!steps[i].alg ->ParseCommandLineArguments (steps[i].args ))
12451257 return false ;
@@ -1253,21 +1265,68 @@ bool GDALAbstractPipelineAlgorithm::ParseCommandLineArguments(
12531265 else if (i > 0 &&
12541266 steps[i].alg ->GetInputType () != nLastStepOutputType)
12551267 {
1256- ReportError (
1257- CE_Failure, CPLE_AppDefined,
1258- " Step '%s' expects a %s input dataset, but "
1259- " previous step '%s' "
1260- " generates a %s output dataset" ,
1261- steps[i].alg ->GetName ().c_str (),
1262- steps[i].alg ->GetInputType () == GDAL_OF_RASTER ? " raster"
1263- : steps[i].alg ->GetInputType () == GDAL_OF_VECTOR
1264- ? " vector"
1265- : " unknown" ,
1266- steps[i - 1 ].alg ->GetName ().c_str (),
1267- nLastStepOutputType == GDAL_OF_RASTER ? " raster"
1268- : nLastStepOutputType == GDAL_OF_VECTOR ? " vector"
1269- : " unknown" );
1270- return false ;
1268+ bool emitError = true ;
1269+
1270+ // Check if a dataset argument, which has as value the
1271+ // placeholder value, has the same dataset type as the output
1272+ // of the last step
1273+ for (const auto &arg : steps[i].alg ->GetArgs ())
1274+ {
1275+ if (!arg->IsOutput () &&
1276+ (arg->GetType () == GAAT_DATASET ||
1277+ arg->GetType () == GAAT_DATASET_LIST))
1278+ {
1279+ if (arg->GetType () == GAAT_DATASET)
1280+ {
1281+ if (arg->Get <GDALArgDatasetValue>().GetName () ==
1282+ GDAL_DATASET_PIPELINE_PLACEHOLDER_VALUE)
1283+ {
1284+ if ((arg->GetDatasetType () &
1285+ nLastStepOutputType) != 0 )
1286+ {
1287+ emitError = false ;
1288+ break ;
1289+ }
1290+ }
1291+ }
1292+ else
1293+ {
1294+ CPLAssert (arg->GetType () == GAAT_DATASET_LIST);
1295+ auto &val =
1296+ arg->Get <std::vector<GDALArgDatasetValue>>();
1297+ if (val.size () == 1 &&
1298+ val[0 ].GetName () ==
1299+ GDAL_DATASET_PIPELINE_PLACEHOLDER_VALUE)
1300+ {
1301+ if ((arg->GetDatasetType () &
1302+ nLastStepOutputType) != 0 )
1303+ {
1304+ emitError = false ;
1305+ break ;
1306+ }
1307+ }
1308+ }
1309+ }
1310+ }
1311+ if (emitError)
1312+ {
1313+ ReportError (CE_Failure, CPLE_AppDefined,
1314+ " Step '%s' expects a %s input dataset, but "
1315+ " previous step '%s' "
1316+ " generates a %s output dataset" ,
1317+ steps[i].alg ->GetName ().c_str (),
1318+ steps[i].alg ->GetInputType () == GDAL_OF_RASTER
1319+ ? " raster"
1320+ : steps[i].alg ->GetInputType () == GDAL_OF_VECTOR
1321+ ? " vector"
1322+ : " unknown" ,
1323+ steps[i - 1 ].alg ->GetName ().c_str (),
1324+ nLastStepOutputType == GDAL_OF_RASTER ? " raster"
1325+ : nLastStepOutputType == GDAL_OF_VECTOR
1326+ ? " vector"
1327+ : " unknown" );
1328+ return false ;
1329+ }
12711330 }
12721331 nLastStepOutputType = steps[i].alg ->GetOutputType ();
12731332 }
@@ -1953,18 +2012,75 @@ bool GDALAbstractPipelineAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
19532012 auto &step = m_steps[i];
19542013 if (i > 0 || poCurDS)
19552014 {
1956- if (!step->m_inputDataset .empty () &&
1957- step->m_inputDataset [0 ].GetDatasetRef ())
2015+ bool prevStepOutputSetToThisStep = false ;
2016+ for (auto &arg : step->GetArgs ())
2017+ {
2018+ if (!arg->IsOutput () && (arg->GetType () == GAAT_DATASET ||
2019+ arg->GetType () == GAAT_DATASET_LIST))
2020+ {
2021+ if (arg->GetType () == GAAT_DATASET)
2022+ {
2023+ if ((arg->GetName () == GDAL_ARG_NAME_INPUT &&
2024+ !arg->IsExplicitlySet ()) ||
2025+ arg->Get <GDALArgDatasetValue>().GetName () ==
2026+ GDAL_DATASET_PIPELINE_PLACEHOLDER_VALUE)
2027+ {
2028+ auto &val = arg->Get <GDALArgDatasetValue>();
2029+ if (val.GetDatasetRef ())
2030+ {
2031+ // Shouldn't happen
2032+ ReportError (CE_Failure, CPLE_AppDefined,
2033+ " Step nr %d (%s) has already an "
2034+ " input dataset for argument %s" ,
2035+ static_cast <int >(i),
2036+ step->GetName ().c_str (),
2037+ arg->GetName ().c_str ());
2038+ return false ;
2039+ }
2040+ prevStepOutputSetToThisStep = true ;
2041+ val.Set (poCurDS);
2042+ arg->NotifyValueSet ();
2043+ }
2044+ }
2045+ else
2046+ {
2047+ CPLAssert (arg->GetType () == GAAT_DATASET_LIST);
2048+ auto &val =
2049+ arg->Get <std::vector<GDALArgDatasetValue>>();
2050+ if ((arg->GetName () == GDAL_ARG_NAME_INPUT &&
2051+ !arg->IsExplicitlySet ()) ||
2052+ (val.size () == 1 &&
2053+ val[0 ].GetName () ==
2054+ GDAL_DATASET_PIPELINE_PLACEHOLDER_VALUE))
2055+ {
2056+ if (val.size () == 1 && val[0 ].GetDatasetRef ())
2057+ {
2058+ // Shouldn't happen
2059+ ReportError (CE_Failure, CPLE_AppDefined,
2060+ " Step nr %d (%s) has already an "
2061+ " input dataset for argument %s" ,
2062+ static_cast <int >(i),
2063+ step->GetName ().c_str (),
2064+ arg->GetName ().c_str ());
2065+ return false ;
2066+ }
2067+ prevStepOutputSetToThisStep = true ;
2068+ val.clear ();
2069+ val.resize (1 );
2070+ val[0 ].Set (poCurDS);
2071+ arg->NotifyValueSet ();
2072+ }
2073+ }
2074+ }
2075+ }
2076+ if (!prevStepOutputSetToThisStep)
19582077 {
1959- // Shouldn't happen
19602078 ReportError (CE_Failure, CPLE_AppDefined,
1961- " Step nr %d (%s) has already an input dataset" ,
2079+ " Step nr %d (%s) does not use input dataset from "
2080+ " previous step" ,
19622081 static_cast <int >(i), step->GetName ().c_str ());
19632082 return false ;
19642083 }
1965- step->m_inputDataset .clear ();
1966- step->m_inputDataset .resize (1 );
1967- step->m_inputDataset [0 ].Set (poCurDS);
19682084 }
19692085
19702086 if (i + 1 < m_steps.size () && step->m_outputDataset .GetDatasetRef () &&
@@ -2007,6 +2123,7 @@ bool GDALAbstractPipelineAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
20072123 {
20082124 step->m_stdout = true ;
20092125 }
2126+ step->m_inputDatasetCanBeOmitted = false ;
20102127 if (!step->ValidateArguments () || !step->RunStep (stepCtxt))
20112128 {
20122129 ret = false ;
0 commit comments