This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 7f44475fcd Improve the wording of the rules and samples (#8191)
7f44475fcd is described below

commit 7f44475fcd1b68107aa0fa2b168a097105fb6ea5
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Mon Aug 31 17:29:45 2026 +0200

    Improve the wording of the rules and samples (#8191)
---
 .../ROOT/pages/variables/parameter-passing.adoc    | 109 +++++++++++++++++----
 1 file changed, 91 insertions(+), 18 deletions(-)

diff --git 
a/docs/hop-user-manual/modules/ROOT/pages/variables/parameter-passing.adoc 
b/docs/hop-user-manual/modules/ROOT/pages/variables/parameter-passing.adoc
index 466f4d7dec..2bb370adfa 100644
--- a/docs/hop-user-manual/modules/ROOT/pages/variables/parameter-passing.adoc
+++ b/docs/hop-user-manual/modules/ROOT/pages/variables/parameter-passing.adoc
@@ -40,48 +40,107 @@ Throughout this page, *caller* is the pipeline or workflow 
that starts another o
 
 Each of those actions and transforms gives you two things, and they answer 
different questions.
 
-The *Parameters* tab is a grid. Each row names a parameter and says where its 
value comes from: a fixed value, a variable expression, or a field from the 
incoming row. **A row that supplies a value always wins.**
+The *Parameters* tab is a grid. Each row names a parameter and says where its 
value comes from: a fixed value, a variable expression, or a stream field from 
the incoming row. **A row that supplies a value always wins.**
 
-The checkbox *Pass parent values to matching parameters* answers a different 
question: what to do about the parameters you did *not* list. With the option 
on, the caller's own value of that name is passed down. With it off, the child 
keeps its own default.
+The columns are labelled differently per executor. This page says *value* and 
*stream field*; in the dialogs those are:
+
+[cols="1,1,1", options="header"]
+|===
+|Executor |"value" is the column |"stream field" is the column
+
+|Pipeline and Workflow action
+|*Value*
+|*Stream Column Name*
+
+|Pipeline and Workflow Executor
+|*Static input value*
+|*Field to use*
+
+|Simple and Multi Mapping
+|*String value (can include variable expressions)*
+|-- (no stream field column)
+|===
+
+The checkbox *Pass parent values to matching parameters* answers a different 
question: what to do about the parameters you did *not supply a value for*. 
That covers a name you left out of the grid altogether **and** a name you typed 
into the grid without giving it a value. With the option on, the caller's own 
value of that name is passed down. With it off, the child keeps its own default.
+
+The moment a row does supply a value, the checkbox is out of the picture for 
that parameter - even if the value turns out to be empty. See <<supplies>>.
 
 [IMPORTANT]
 ====
 Neither control has anything to do with variable inheritance.
 A child **always** inherits the caller's variables. The option only decides 
whether a parameter *declared by the child* is filled in from the caller or 
keeps its own default.
 
-This is a common misreading, because the option used to be labelled "Inherit 
all variables from pipeline".
+This is a common misreading, and the old labels did not help. On the executor 
transforms the option
+was called "Inherit all variables from pipeline", which describes something it 
never did. On the
+Pipeline and Workflow actions it was "Pass parameter values to sub pipeline", 
which is closer, but
+still reads as if it governed every parameter rather than only the ones you 
leave unset.
 ====
 
 == The rules
 
 For each parameter the child declares, in this order:
 
-. **A row on the caller's Parameters tab that supplies a value.** This wins 
over everything, including the checkbox. It is how you override a child's 
default for one execution.
-. **Otherwise, if _Pass parent values to matching parameters_ is on:** the 
caller's value of a parameter or variable with that same name.
+. **A value supplied on the caller's Parameters tab.** This wins over 
everything, including the checkbox. It is how you override a child's default 
for one execution.
+. **Otherwise, if _Pass parent values to matching parameters_ is on: the 
caller's own value of that same name.** That can be a parameter the caller 
declared or any variable in its scope - once the caller is running, the two are 
the same thing.
 . **Otherwise: the child's own default**, as declared in the child's pipeline 
or workflow properties.
 . If the child declares no default either, the parameter is an empty string.
 
+"Otherwise" means the row supplied nothing, which includes a name you typed in 
and left blank. What
+counts as supplying a value is not always obvious - see <<supplies>>.
+
 A row that names a parameter the child does *not* declare is not ignored: that 
parameter is declared on the child and set, so the child can use 
`{openvar}NAME{closevar}` as if it had declared it itself.
 
+[[supplies]]
 == What counts as "supplies a value"
 
-Rule 1 only applies to a row that actually configures something. Three cases 
look similar and behave differently on purpose:
+Rule 1 only applies to a row that actually configures something. Several cases 
look alike in the dialog and behave differently on purpose:
 
 [cols="2,3", options="header"]
 |===
 |The row |What happens
 
-|A value or variable expression is filled in
+|A value is filled in
 |That value is used. Rule 1.
 
-|A field is mapped, and the field is empty on this row
-|You did configure a source, it just produced nothing this time. The child 
falls back to its own default. It does **not** reuse the value from a previous 
row.
+|A value that is a variable expression resolving to empty, such as 
`{openvar}OTHER_VARIABLE{closevar}` when `OTHER_VARIABLE` is set but empty
+|You configured a value; it just came out empty. The child falls back to its 
own default. **The checkbox makes no difference here** - the row already 
claimed the parameter, so the caller's own value of that name is not considered.
 
-|No value and no field - only the name
-|Nothing is configured, so the row is treated as if it were not there. The 
option and the child's default decide, as in rules 2 and 3.
+|A stream field is mapped, and it is empty on this row
+|You configured a source, it just produced nothing this time. The child falls 
back to its own default. It does **not** reuse the value from a previous row.
+
+|No value and no stream field - only the name
+|Nothing is configured, so the row behaves as if it were not there. The 
checkbox and the child's default decide, as in rules 2 and 3.
+
+|Both a stream field and a value are filled in
+|The stream field wins. The value acts as neither a fallback nor an override; 
if the stream field is empty on this row you get the child's default, not the 
value.
 |===
 
-The last case matters more than it looks. Pressing *Get Parameters* fills the 
grid with the names the child declares and leaves the values empty. Those rows 
do not pass anything by themselves; whether the caller's values reach the child 
is still decided by the checkbox.
+The "only the name" case matters more than it looks. Pressing *Get Parameters* 
fills the grid with the names the child declares and leaves the values empty. 
Those rows pass nothing by themselves; whether the caller's values reach the 
child is still decided by the checkbox.
+
+The contrast to keep in mind is between an empty cell and an expression that 
evaluates to empty. Both look like nothing, and both pass nothing, but they 
land on opposite sides of the checkbox:
+
+[cols="2,1,1", options="header"]
+|===
+|Value column |Checkbox off |Checkbox on
+
+|left blank
+|`child-default`
+|`parent-value`
+
+|`{openvar}EMPTY_VAR{closevar}`, where `EMPTY_VAR` is set but empty
+|`child-default`
+|`child-default`
+|===
+
+There is therefore no way to say "use my expression, and fall back to the 
caller's value when it is empty". If you need that, compute the fallback in the 
caller and pass the result.
+
+[WARNING]
+====
+If the variable in such an expression does not exist at all, Hop cannot 
resolve it and passes the
+text through unchanged: the child receives the literal string 
`{openvar}OTHER_VARIABLE{closevar}`,
+not an empty value. An undefined variable and a variable set to empty behave 
very differently, and
+unticking the checkbox does not protect you from this one.
+====
 
 == The full picture
 
@@ -95,15 +154,23 @@ A child that declares `MY_PARAM` with default 
`child-default`, a caller whose sc
 |`from-tab`
 |`from-tab`
 
-|`MY_PARAM` mapped to a field holding `abc`
+|`MY_PARAM` mapped to a stream field holding `abc`
 |`abc`
 |`abc`
 
-|`MY_PARAM` mapped to a field that is empty on this row
+|`MY_PARAM` mapped to a stream field that is empty on this row
+|`child-default`
+|`child-default`
+
+|`MY_PARAM` = `{openvar}EMPTY_VAR{closevar}`, where `EMPTY_VAR` is set but 
empty
 |`child-default`
 |`child-default`
 
-|`MY_PARAM` listed, no value, no field
+|`MY_PARAM` = `{openvar}NO_SUCH_VAR{closevar}`, where the variable does not 
exist
+|`{openvar}NO_SUCH_VAR{closevar}`
+|`{openvar}NO_SUCH_VAR{closevar}`
+
+|`MY_PARAM` listed, no value, no stream field
 |`child-default`
 |`parent-value`
 
@@ -114,11 +181,15 @@ A child that declares `MY_PARAM` with default 
`child-default`, a caller whose sc
 
 The two bottom rows are the reason a parameter is worth declaring: a child 
that declares a parameter is shielded from an unrelated value of the same name 
that happens to exist in the caller, unless you deliberately allow it.
 
+It follows that if every parameter the child declares is listed on the 
caller's tab **with a value**, the checkbox changes nothing at all - there is 
nothing left for it to act on. The checkbox only ever decides the fate of a 
parameter that the child declares and the caller supplies no value for.
+
 == Things that surprise people
 
 === You cannot blank out a parameter by leaving the value empty
 
-An empty parameter value means "nothing was passed", so the child's default 
applies. There is no way to force a parameter that has a non-empty default to 
become an empty string from the caller.
+An empty parameter value means "nothing was passed", so the child's default 
applies. There is no way to force a parameter that has a non-empty default to 
become an empty string from the caller. This holds however the emptiness 
arrives: a blank cell, a mapped stream field that is empty on this row, or a 
variable expression that resolves to empty all end at the child's default.
+
+Passing an empty value does work when no non-empty default is in the way. A 
parameter the child declares with an empty default, and a name the child does 
not declare at all, both end up empty. What you cannot do is override a 
non-empty default with emptiness.
 
 If the child must be able to run with an empty value, declare it in the child 
with an *empty* default. It is then empty unless something passes a value.
 
@@ -143,13 +214,15 @@ It reads the pipeline or workflow the action or transform 
points at, not the who
 |Executor |Notes
 
 |Pipeline / Workflow action
-|The Parameters tab also has a *Copy results to parameters* option, which 
pre-fills the values from the incoming result rows before the rules above are 
applied.
+a|*Stream Column Name* reads from the incoming result row, so it only produces 
a value when *Execute for every input row* is ticked. Without it there is no 
row to read and the child falls back to its default, whatever *Copy results to 
parameters* is set to.
+
+Naming a column that is not present in the incoming row does not yield an 
empty value: it raises an error and stops the workflow.
 
 |Pipeline / Workflow Executor
 |Parameters are set once per executor iteration, from the first row of the 
group. A child started for the next row starts over from these rules; nothing 
carries over.
 
 |Mapping / Multi Mapping
-|Same rules. The grid has no field column, so only the "value filled in" and 
"nothing configured" cases occur.
+|Same rules. The grid has no stream field column, so only the "value filled 
in" and "nothing configured" cases occur.
 
 |Metadata Injection
 |Same rules, applied to the template pipeline. Files saved before the 
Parameters tab existed behave as if the option is on, which is what they always 
did.

Reply via email to