This is an automated email from the ASF dual-hosted git repository. hansva pushed a commit to branch 2.18.1-patch in repository https://gitbox.apache.org/repos/asf/hop.git
commit 76cb8195d1999cece39f097adf60a281800d3812 Author: Hans Van Akelyen <[email protected]> AuthorDate: Thu Jun 11 12:41:17 2026 +0200 add variable injection support back, fixes #7265 (#7269) --- ...ate.hpl => 0054-load-file-content-template.hpl} | 2 +- ...ate.hpl => 0054-load-file-content-validate.hpl} | 2 +- ...file-content.hpl => 0054-load-file-content.hpl} | 12 +- ...child.hpl => 0055-set-constant-value-child.hpl} | 2 +- ...rent.hpl => 0055-set-constant-value-parent.hpl} | 10 +- ...te.hpl => 0056-mdi-multi-datagrid-template.hpl} | 2 +- ...ti-datagrid.hpl => 0056-mdi-multi-datagrid.hpl} | 6 +- ...late.hpl => 0057-mdi-shared-field-template.hpl} | 2 +- ...-shared-field.hpl => 0057-mdi-shared-field.hpl} | 6 +- ...mplate.hpl => 0058-mdi-edge-cases-template.hpl} | 2 +- ...-mdi-edge-cases.hpl => 0058-mdi-edge-cases.hpl} | 6 +- ...ld.hpl => 0059-mdi-constant-variable-child.hpl} | 93 +++++----- .../mdi/0059-mdi-constant-variable-parent.hpl | 198 +++++++++++++++++++++ ...content.hwf => main-0054-load-file-content.hwf} | 16 +- ...-value.hwf => main-0055-set-constant-value.hwf} | 4 +- ...tagrid.hwf => main-0056-mdi-multi-datagrid.hwf} | 14 +- ...ed-field.hwf => main-0057-mdi-shared-field.hwf} | 14 +- ...edge-cases.hwf => main-0058-mdi-edge-cases.hwf} | 14 +- ...ent.hwf => main-0059-mdi-constant-variable.hwf} | 57 ++---- ...n => 0054-load-file-content-validate UNIT.json} | 4 +- ...on => 0055-set-constant-value-parent UNIT.json} | 4 +- ... => 0056-mdi-multi-datagrid-template UNIT.json} | 4 +- ...on => 0057-mdi-shared-field-template UNIT.json} | 4 +- ...json => 0058-mdi-edge-cases-template UNIT.json} | 4 +- .../pipeline/transforms/metainject/MetaInject.java | 25 ++- .../transforms/metainject/MetaInjectTest.java | 45 +++++ 26 files changed, 387 insertions(+), 165 deletions(-) diff --git a/integration-tests/mdi/0087-load-file-content-template.hpl b/integration-tests/mdi/0054-load-file-content-template.hpl similarity index 97% rename from integration-tests/mdi/0087-load-file-content-template.hpl rename to integration-tests/mdi/0054-load-file-content-template.hpl index 60f93fac1c..dba68f1903 100644 --- a/integration-tests/mdi/0087-load-file-content-template.hpl +++ b/integration-tests/mdi/0054-load-file-content-template.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0087-load-file-content-template</name> + <name>0054-load-file-content-template</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> diff --git a/integration-tests/mdi/0087-load-file-content-validate.hpl b/integration-tests/mdi/0054-load-file-content-validate.hpl similarity index 99% rename from integration-tests/mdi/0087-load-file-content-validate.hpl rename to integration-tests/mdi/0054-load-file-content-validate.hpl index f3191b0c4b..026a240a0f 100644 --- a/integration-tests/mdi/0087-load-file-content-validate.hpl +++ b/integration-tests/mdi/0054-load-file-content-validate.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0087-load-file-content-validate</name> + <name>0054-load-file-content-validate</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> diff --git a/integration-tests/mdi/0087-load-file-content.hpl b/integration-tests/mdi/0054-load-file-content.hpl similarity index 97% rename from integration-tests/mdi/0087-load-file-content.hpl rename to integration-tests/mdi/0054-load-file-content.hpl index 978e4ce8ad..1198ec2573 100644 --- a/integration-tests/mdi/0087-load-file-content.hpl +++ b/integration-tests/mdi/0054-load-file-content.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0087-load-file-content</name> + <name>0054-load-file-content</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> @@ -40,22 +40,22 @@ limitations under the License. <order> <hop> <from>golden-load-file-content</from> - <to>0087-load-file-content-template.hpl</to> + <to>0054-load-file-content-template.hpl</to> <enabled>Y</enabled> </hop> <hop> <from>golden-load-file-content-files</from> - <to>0087-load-file-content-template.hpl</to> + <to>0054-load-file-content-template.hpl</to> <enabled>Y</enabled> </hop> <hop> <from>golden-load-file-content-fields</from> - <to>0087-load-file-content-template.hpl</to> + <to>0054-load-file-content-template.hpl</to> <enabled>Y</enabled> </hop> </order> <transform> - <name>0087-load-file-content-template.hpl</name> + <name>0054-load-file-content-template.hpl</name> <type>MetaInject</type> <description/> <distribute>Y</distribute> @@ -65,7 +65,7 @@ limitations under the License. <method>none</method> <schema_name/> </partitioning> - <filename>${PROJECT_HOME}/0087-load-file-content-template.hpl</filename> + <filename>${PROJECT_HOME}/0054-load-file-content-template.hpl</filename> <run_configuration>local</run_configuration> <source_transform/> <source_output_fields> </source_output_fields> diff --git a/integration-tests/mdi/0088-set-constant-value-child.hpl b/integration-tests/mdi/0055-set-constant-value-child.hpl similarity index 98% copy from integration-tests/mdi/0088-set-constant-value-child.hpl copy to integration-tests/mdi/0055-set-constant-value-child.hpl index 298f23220e..89f76b6bb4 100644 --- a/integration-tests/mdi/0088-set-constant-value-child.hpl +++ b/integration-tests/mdi/0055-set-constant-value-child.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0088-set-constant-value-child</name> + <name>0055-set-constant-value-child</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> diff --git a/integration-tests/mdi/0088-set-constant-value-parent.hpl b/integration-tests/mdi/0055-set-constant-value-parent.hpl similarity index 94% rename from integration-tests/mdi/0088-set-constant-value-parent.hpl rename to integration-tests/mdi/0055-set-constant-value-parent.hpl index fa619b3fbb..031d60c6bb 100644 --- a/integration-tests/mdi/0088-set-constant-value-parent.hpl +++ b/integration-tests/mdi/0055-set-constant-value-parent.hpl @@ -26,7 +26,7 @@ limitations under the License. <pipeline_type>Normal</pipeline_type> <pipeline_status>0</pipeline_status> <parameters/> - <name>0088-set-constant-value-parent</name> + <name>0055-set-constant-value-parent</name> <name_sync_with_filename>Y</name_sync_with_filename> <description>Regression test for issue #7246: a constant value (a mapping without a source transform) must be injected into the template, even when another key in the same injection group is fed from a source transform.</description> <extended_description/> @@ -37,8 +37,8 @@ limitations under the License. </info> <transform> <type>MetaInject</type> - <name>0088-set-constant-value-child.hpl</name> - <filename>${PROJECT_HOME}/0088-set-constant-value-child.hpl</filename> + <name>0055-set-constant-value-child.hpl</name> + <filename>${PROJECT_HOME}/0055-set-constant-value-child.hpl</filename> <source_transform>Output</source_transform> <source_output_fields> <source_output_field> @@ -136,11 +136,11 @@ limitations under the License. <order> <hop> <from>fields</from> - <to>0088-set-constant-value-child.hpl</to> + <to>0055-set-constant-value-child.hpl</to> <enabled>Y</enabled> </hop> <hop> - <from>0088-set-constant-value-child.hpl</from> + <from>0055-set-constant-value-child.hpl</from> <to>Verify</to> <enabled>Y</enabled> </hop> diff --git a/integration-tests/mdi/0089-mdi-multi-datagrid-template.hpl b/integration-tests/mdi/0056-mdi-multi-datagrid-template.hpl similarity index 98% rename from integration-tests/mdi/0089-mdi-multi-datagrid-template.hpl rename to integration-tests/mdi/0056-mdi-multi-datagrid-template.hpl index d10eafb72c..1d269179da 100644 --- a/integration-tests/mdi/0089-mdi-multi-datagrid-template.hpl +++ b/integration-tests/mdi/0056-mdi-multi-datagrid-template.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0089-mdi-multi-datagrid-template</name> + <name>0056-mdi-multi-datagrid-template</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> diff --git a/integration-tests/mdi/0089-mdi-multi-datagrid.hpl b/integration-tests/mdi/0056-mdi-multi-datagrid.hpl similarity index 96% rename from integration-tests/mdi/0089-mdi-multi-datagrid.hpl rename to integration-tests/mdi/0056-mdi-multi-datagrid.hpl index ee0153cd62..01c0d250ff 100644 --- a/integration-tests/mdi/0089-mdi-multi-datagrid.hpl +++ b/integration-tests/mdi/0056-mdi-multi-datagrid.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0089-mdi-multi-datagrid</name> + <name>0056-mdi-multi-datagrid</name> <name_sync_with_filename>Y</name_sync_with_filename> <description>Injects a single Select Values "fields" group from two separate data grids. Reproduces the regression where the second grid's source field can not be found because the group row layout is cached from the first grid only.</description> <extended_description/> @@ -60,11 +60,11 @@ limitations under the License. <method>none</method> <schema_name/> </partitioning> - <filename>${PROJECT_HOME}/0089-mdi-multi-datagrid-template.hpl</filename> + <filename>${PROJECT_HOME}/0056-mdi-multi-datagrid-template.hpl</filename> <run_configuration>local</run_configuration> <source_transform/> <source_output_fields> </source_output_fields> - <target_file>${PROJECT_HOME}/0089-mdi-multi-datagrid-template-injected.hpl</target_file> + <target_file>${PROJECT_HOME}/0056-mdi-multi-datagrid-template-injected.hpl</target_file> <create_parent_folder>Y</create_parent_folder> <no_execution>N</no_execution> <stream_source_transform/> diff --git a/integration-tests/mdi/0090-mdi-shared-field-template.hpl b/integration-tests/mdi/0057-mdi-shared-field-template.hpl similarity index 98% rename from integration-tests/mdi/0090-mdi-shared-field-template.hpl rename to integration-tests/mdi/0057-mdi-shared-field-template.hpl index 5894c4795e..3ae0e32101 100644 --- a/integration-tests/mdi/0090-mdi-shared-field-template.hpl +++ b/integration-tests/mdi/0057-mdi-shared-field-template.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0090-mdi-shared-field-template</name> + <name>0057-mdi-shared-field-template</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> diff --git a/integration-tests/mdi/0090-mdi-shared-field.hpl b/integration-tests/mdi/0057-mdi-shared-field.hpl similarity index 96% rename from integration-tests/mdi/0090-mdi-shared-field.hpl rename to integration-tests/mdi/0057-mdi-shared-field.hpl index e92f7531ed..50f69b2c5d 100644 --- a/integration-tests/mdi/0090-mdi-shared-field.hpl +++ b/integration-tests/mdi/0057-mdi-shared-field.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0090-mdi-shared-field</name> + <name>0057-mdi-shared-field</name> <name_sync_with_filename>Y</name_sync_with_filename> <description>Injects one and the same source field into several injection targets: two keys (FIELD_NAME and FIELD_RENAME) of one Select Values group and the FIELD_NAME key of a second Select Values transform. Verifies that reusing a single input column for multiple injection transforms/groups works.</description> <extended_description/> @@ -55,11 +55,11 @@ limitations under the License. <method>none</method> <schema_name/> </partitioning> - <filename>${PROJECT_HOME}/0090-mdi-shared-field-template.hpl</filename> + <filename>${PROJECT_HOME}/0057-mdi-shared-field-template.hpl</filename> <run_configuration>local</run_configuration> <source_transform/> <source_output_fields> </source_output_fields> - <target_file>${PROJECT_HOME}/0090-mdi-shared-field-template-injected.hpl</target_file> + <target_file>${PROJECT_HOME}/0057-mdi-shared-field-template-injected.hpl</target_file> <create_parent_folder>Y</create_parent_folder> <no_execution>N</no_execution> <stream_source_transform/> diff --git a/integration-tests/mdi/0091-mdi-edge-cases-template.hpl b/integration-tests/mdi/0058-mdi-edge-cases-template.hpl similarity index 98% rename from integration-tests/mdi/0091-mdi-edge-cases-template.hpl rename to integration-tests/mdi/0058-mdi-edge-cases-template.hpl index a4e0679ac6..cdef004713 100644 --- a/integration-tests/mdi/0091-mdi-edge-cases-template.hpl +++ b/integration-tests/mdi/0058-mdi-edge-cases-template.hpl @@ -19,7 +19,7 @@ limitations under the License. --> <pipeline> <info> - <name>0091-mdi-edge-cases-template</name> + <name>0058-mdi-edge-cases-template</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> diff --git a/integration-tests/mdi/0091-mdi-edge-cases.hpl b/integration-tests/mdi/0058-mdi-edge-cases.hpl similarity index 97% rename from integration-tests/mdi/0091-mdi-edge-cases.hpl rename to integration-tests/mdi/0058-mdi-edge-cases.hpl index 53cb679e1f..7cae61197d 100644 --- a/integration-tests/mdi/0091-mdi-edge-cases.hpl +++ b/integration-tests/mdi/0058-mdi-edge-cases.hpl @@ -26,7 +26,7 @@ limitations under the License. <pipeline_type>Normal</pipeline_type> <pipeline_status>0</pipeline_status> <parameters/> - <name>0091-mdi-edge-cases</name> + <name>0058-mdi-edge-cases</name> <name_sync_with_filename>Y</name_sync_with_filename> <description>Stress test for metadata injection group handling. The Select Values METAS group is fed from two source transforms with a different number of rows (select fields = 4 rows, renames = 2 rows), mixed with a constant (META_TYPE), while the 'select fields' grid is reused across two different groups (FIELDS via FIELD_NAME and METAS via META_NAME).</description> <extended_description/> @@ -38,7 +38,7 @@ limitations under the License. <transform> <type>MetaInject</type> <name>ETL metadata injection</name> - <filename>${PROJECT_HOME}/0091-mdi-edge-cases-template.hpl</filename> + <filename>${PROJECT_HOME}/0058-mdi-edge-cases-template.hpl</filename> <source_transform/> <source_output_fields/> <mappings> @@ -70,7 +70,7 @@ limitations under the License. <target_detail>Y</target_detail> </mapping> </mappings> - <target_file>${PROJECT_HOME}/0091-mdi-edge-cases-template-injected.hpl</target_file> + <target_file>${PROJECT_HOME}/0058-mdi-edge-cases-template-injected.hpl</target_file> <no_execution>N</no_execution> <allow_empty_stream_on_execution>N</allow_empty_stream_on_execution> <stream_source_transform/> diff --git a/integration-tests/mdi/0088-set-constant-value-child.hpl b/integration-tests/mdi/0059-mdi-constant-variable-child.hpl similarity index 66% rename from integration-tests/mdi/0088-set-constant-value-child.hpl rename to integration-tests/mdi/0059-mdi-constant-variable-child.hpl index 298f23220e..03313e2ce3 100644 --- a/integration-tests/mdi/0088-set-constant-value-child.hpl +++ b/integration-tests/mdi/0059-mdi-constant-variable-child.hpl @@ -19,39 +19,28 @@ limitations under the License. --> <pipeline> <info> - <name>0088-set-constant-value-child</name> + <name>0059-mdi-constant-variable-child</name> <name_sync_with_filename>Y</name_sync_with_filename> - <description/> - <extended_description/> - <pipeline_version/> + <description>Template: the "Add constant" value is injected by the parent as a constant containing a variable</description> <pipeline_type>Normal</pipeline_type> <parameters> </parameters> - <capture_transform_performance>N</capture_transform_performance> - <transform_performance_capturing_delay>1000</transform_performance_capturing_delay> - <transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit> - <created_user>-</created_user> - <created_date>2026/06/09 10:00:00.000</created_date> - <modified_user>-</modified_user> - <modified_date>2026/06/09 10:00:00.000</modified_date> </info> - <notepads> - </notepads> <order> <hop> - <from>Sample data</from> - <to>Set field value to a constant</to> + <from>seed</from> + <to>Add constant</to> <enabled>Y</enabled> </hop> <hop> - <from>Set field value to a constant</from> - <to>Output</to> + <from>Add constant</from> + <to>out</to> <enabled>Y</enabled> </hop> </order> <transform> - <name>Output</name> - <type>Dummy</type> + <name>seed</name> + <type>DataGrid</type> <description/> <distribute>Y</distribute> <custom_distribution/> @@ -60,15 +49,29 @@ limitations under the License. <method>none</method> <schema_name/> </partitioning> + <data> + <line> + <item>x</item> + </line> + </data> + <fields> + <field> + <length>-1</length> + <precision>-1</precision> + <set_empty_string>N</set_empty_string> + <name>seed</name> + <type>String</type> + </field> + </fields> <attributes/> <GUI> - <xloc>480</xloc> - <yloc>112</yloc> + <xloc>144</xloc> + <yloc>96</yloc> </GUI> </transform> <transform> - <name>Set field value to a constant</name> - <type>SetValueConstant</type> + <name>Add constant</name> + <type>Constant</type> <description/> <distribute>Y</distribute> <custom_distribution/> @@ -78,17 +81,28 @@ limitations under the License. <schema_name/> </partitioning> <fields> -</fields> - <usevar>N</usevar> + <field> + <name>injected</name> + <type>String</type> + <format/> + <currency/> + <decimal/> + <group/> + <nullif>PLACEHOLDER</nullif> + <length>-1</length> + <precision>-1</precision> + <set_empty_string>N</set_empty_string> + </field> + </fields> <attributes/> <GUI> - <xloc>320</xloc> - <yloc>112</yloc> + <xloc>336</xloc> + <yloc>96</yloc> </GUI> </transform> <transform> - <name>Sample data</name> - <type>DataGrid</type> + <name>out</name> + <type>Dummy</type> <description/> <distribute>Y</distribute> <custom_distribution/> @@ -97,27 +111,10 @@ limitations under the License. <method>none</method> <schema_name/> </partitioning> - <data> - <line> - <item>original</item> - </line> - <line> - <item>untouched</item> - </line> - </data> - <fields> - <field> - <length>-1</length> - <precision>-1</precision> - <set_empty_string>N</set_empty_string> - <name>x</name> - <type>String</type> - </field> - </fields> <attributes/> <GUI> - <xloc>160</xloc> - <yloc>112</yloc> + <xloc>528</xloc> + <yloc>96</yloc> </GUI> </transform> <transform_error_handling> diff --git a/integration-tests/mdi/0059-mdi-constant-variable-parent.hpl b/integration-tests/mdi/0059-mdi-constant-variable-parent.hpl new file mode 100644 index 0000000000..820dfdfc0e --- /dev/null +++ b/integration-tests/mdi/0059-mdi-constant-variable-parent.hpl @@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +--> +<pipeline> + <info> + <pipeline_version/> + <capture_transform_performance>N</capture_transform_performance> + <transform_performance_capturing_delay>1000</transform_performance_capturing_delay> + <transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit> + <pipeline_type>Normal</pipeline_type> + <pipeline_status>0</pipeline_status> + <parameters> + <parameter> + <name>SAMPLE</name> + <description/> + <default_value>sampleValue</default_value> + </parameter> + </parameters> + <name>0059-mdi-constant-variable-parent</name> + <name_sync_with_filename>Y</name_sync_with_filename> + <description>Injects a constant value containing the ${SAMPLE} variable into a @HopMetadataProperty template (Add constant) and verifies the variable is resolved</description> + <extended_description/> + <created_user>-</created_user> + <modified_user>-</modified_user> + <created_date>2026/06/11 11:20:36.014</created_date> + <modified_date>2026/06/11 11:20:36.014</modified_date> + </info> + <transform> + <type>MetaInject</type> + <name>ETL metadata injection</name> + <filename>${PROJECT_HOME}/0059-mdi-constant-variable-child.hpl</filename> + <source_transform>out</source_transform> + <source_output_fields> + <source_output_field> + <source_output_field_name>seed</source_output_field_name> + <source_output_field_type>String</source_output_field_type> + <source_output_field_length>-1</source_output_field_length> + <source_output_field_precision>-1</source_output_field_precision> + </source_output_field> + <source_output_field> + <source_output_field_name>injected</source_output_field_name> + <source_output_field_type>String</source_output_field_type> + <source_output_field_length>-1</source_output_field_length> + <source_output_field_precision>-1</source_output_field_precision> + </source_output_field> + </source_output_fields> + <mappings> + <mapping> + <source_transform/> + <source_field>injected</source_field> + <target_transform_name>Add constant</target_transform_name> + <target_attribute_key>name</target_attribute_key> + <target_detail>Y</target_detail> + </mapping> + <mapping> + <source_transform/> + <source_field>String</source_field> + <target_transform_name>Add constant</target_transform_name> + <target_attribute_key>type</target_attribute_key> + <target_detail>Y</target_detail> + </mapping> + <mapping> + <source_field>${SAMPLE}</source_field> + <target_transform_name>Add constant</target_transform_name> + <target_attribute_key>nullif</target_attribute_key> + <target_detail>Y</target_detail> + </mapping> + </mappings> + <target_file/> + <no_execution>N</no_execution> + <allow_empty_stream_on_execution>N</allow_empty_stream_on_execution> + <stream_source_transform/> + <stream_target_transform/> + <run_configuration>local</run_configuration> + <create_parent_folder>Y</create_parent_folder> + <distribute>Y</distribute> + <copies>1</copies> + <GUI> + <xloc>144</xloc> + <yloc>112</yloc> + </GUI> + <description/> + <partitioning> + <method>none</method> + <schema_name/> + </partitioning> + <attributes/> + </transform> + <transform> + <type>FilterRows</type> + <name>Check resolved</name> + <compare> + <condition> + <negated>N</negated> + <operator>-</operator> + <leftvalue>injected</leftvalue> + <function>=</function> + <rightvalue/> + <value> + <name>constant</name> + <type>String</type> + <text>sampleValue</text> + <length>-1</length> + <precision>-1</precision> + <isnull>N</isnull> + <mask/> + </value> + <conditions/> + </condition> + </compare> + <send_true_to>Resolved OK</send_true_to> + <send_false_to>Variable not resolved - Abort</send_false_to> + <distribute>Y</distribute> + <copies>1</copies> + <GUI> + <xloc>352</xloc> + <yloc>112</yloc> + </GUI> + <description/> + <partitioning> + <method>none</method> + <schema_name/> + </partitioning> + <attributes/> + </transform> + <transform> + <type>Abort</type> + <name>Variable not resolved - Abort</name> + <row_threshold>0</row_threshold> + <message>The ${SAMPLE} variable in the injected constant was not resolved</message> + <always_log_rows>Y</always_log_rows> + <abort_option>ABORT_WITH_ERROR</abort_option> + <distribute>Y</distribute> + <copies>1</copies> + <GUI> + <xloc>352</xloc> + <yloc>256</yloc> + </GUI> + <description/> + <partitioning> + <method>none</method> + <schema_name/> + </partitioning> + <attributes/> + </transform> + <transform> + <type>Dummy</type> + <name>Resolved OK</name> + <distribute>Y</distribute> + <copies>1</copies> + <GUI> + <xloc>560</xloc> + <yloc>112</yloc> + </GUI> + <description/> + <partitioning> + <method>none</method> + <schema_name/> + </partitioning> + <attributes/> + </transform> + <order> + <hop> + <from>ETL metadata injection</from> + <to>Check resolved</to> + <enabled>Y</enabled> + </hop> + <hop> + <from>Check resolved</from> + <to>Resolved OK</to> + <enabled>Y</enabled> + </hop> + <hop> + <from>Check resolved</from> + <to>Variable not resolved - Abort</to> + <enabled>Y</enabled> + </hop> + </order> + <notepads/> + <attributes/> + <transform_error_handling/> +</pipeline> diff --git a/integration-tests/mdi/main-0087-load-file-content.hwf b/integration-tests/mdi/main-0054-load-file-content.hwf similarity index 88% copy from integration-tests/mdi/main-0087-load-file-content.hwf copy to integration-tests/mdi/main-0054-load-file-content.hwf index ee4726a41f..3139aa0349 100644 --- a/integration-tests/mdi/main-0087-load-file-content.hwf +++ b/integration-tests/mdi/main-0054-load-file-content.hwf @@ -18,7 +18,7 @@ limitations under the License. --> <workflow> - <name>main-0087-load-file-content</name> + <name>main-0054-load-file-content</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> @@ -50,7 +50,7 @@ limitations under the License. <attributes_hac/> </action> <action> - <name>0087-load-file-content.hpl</name> + <name>0054-load-file-content.hpl</name> <description/> <type>PIPELINE</type> <attributes/> @@ -60,7 +60,7 @@ limitations under the License. <clear_rows>N</clear_rows> <create_parent_folder>N</create_parent_folder> <exec_per_row>N</exec_per_row> - <filename>${PROJECT_HOME}/0087-load-file-content.hpl</filename> + <filename>${PROJECT_HOME}/0054-load-file-content.hpl</filename> <logext/> <logfile/> <loglevel>Basic</loglevel> @@ -78,13 +78,13 @@ limitations under the License. <attributes_hac/> </action> <action> - <name>0087-load-file-content-validate UNIT</name> + <name>0054-load-file-content-validate UNIT</name> <description/> <type>RunPipelineTests</type> <attributes/> <test_names> <test_name> - <name>0087-load-file-content-validate UNIT</name> + <name>0054-load-file-content-validate UNIT</name> </test_name> </test_names> <parallel>N</parallel> @@ -96,14 +96,14 @@ limitations under the License. <hops> <hop> <from>Start</from> - <to>0087-load-file-content.hpl</to> + <to>0054-load-file-content.hpl</to> <enabled>Y</enabled> <evaluation>Y</evaluation> <unconditional>Y</unconditional> </hop> <hop> - <from>0087-load-file-content.hpl</from> - <to>0087-load-file-content-validate UNIT</to> + <from>0054-load-file-content.hpl</from> + <to>0054-load-file-content-validate UNIT</to> <enabled>Y</enabled> <evaluation>Y</evaluation> <unconditional>N</unconditional> diff --git a/integration-tests/mdi/main-0088-set-constant-value.hwf b/integration-tests/mdi/main-0055-set-constant-value.hwf similarity index 95% rename from integration-tests/mdi/main-0088-set-constant-value.hwf rename to integration-tests/mdi/main-0055-set-constant-value.hwf index 602ca5c15e..ad56f99a83 100644 --- a/integration-tests/mdi/main-0088-set-constant-value.hwf +++ b/integration-tests/mdi/main-0055-set-constant-value.hwf @@ -18,7 +18,7 @@ limitations under the License. --> <workflow> - <name>main-0088-set-constant-value</name> + <name>main-0055-set-constant-value</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> @@ -55,7 +55,7 @@ limitations under the License. <attributes/> <test_names> <test_name> - <name>0088-set-constant-value-parent UNIT</name> + <name>0055-set-constant-value-parent UNIT</name> </test_name> </test_names> <parallel>N</parallel> diff --git a/integration-tests/mdi/main-0089-mdi-multi-datagrid.hwf b/integration-tests/mdi/main-0056-mdi-multi-datagrid.hwf similarity index 90% rename from integration-tests/mdi/main-0089-mdi-multi-datagrid.hwf rename to integration-tests/mdi/main-0056-mdi-multi-datagrid.hwf index d040b6dd49..0f26366bf0 100644 --- a/integration-tests/mdi/main-0089-mdi-multi-datagrid.hwf +++ b/integration-tests/mdi/main-0056-mdi-multi-datagrid.hwf @@ -18,7 +18,7 @@ limitations under the License. --> <workflow> - <name>main-0089-mdi-multi-datagrid</name> + <name>main-0056-mdi-multi-datagrid</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> @@ -49,7 +49,7 @@ limitations under the License. <attributes_hac/> </action> <action> - <name>0089-mdi-multi-datagrid.hpl</name> + <name>0056-mdi-multi-datagrid.hpl</name> <description/> <type>PIPELINE</type> <attributes/> @@ -59,7 +59,7 @@ limitations under the License. <clear_rows>N</clear_rows> <create_parent_folder>N</create_parent_folder> <exec_per_row>N</exec_per_row> - <filename>${PROJECT_HOME}/0089-mdi-multi-datagrid.hpl</filename> + <filename>${PROJECT_HOME}/0056-mdi-multi-datagrid.hpl</filename> <loglevel>Basic</loglevel> <parameters> <pass_all_parameters>Y</pass_all_parameters> @@ -81,7 +81,7 @@ limitations under the License. <attributes/> <test_names> <test_name> - <name>0089-mdi-multi-datagrid-template UNIT</name> + <name>0056-mdi-multi-datagrid-template UNIT</name> </test_name> </test_names> <parallel>N</parallel> @@ -95,7 +95,7 @@ limitations under the License. <type>DELETE_FILE</type> <attributes/> <fail_if_file_not_exists>N</fail_if_file_not_exists> - <filename>${PROJECT_HOME}/0089-mdi-multi-datagrid-template-injected.hpl</filename> + <filename>${PROJECT_HOME}/0056-mdi-multi-datagrid-template-injected.hpl</filename> <parallel>N</parallel> <xloc>464</xloc> <yloc>272</yloc> @@ -105,13 +105,13 @@ limitations under the License. <hops> <hop> <from>Start</from> - <to>0089-mdi-multi-datagrid.hpl</to> + <to>0056-mdi-multi-datagrid.hpl</to> <enabled>Y</enabled> <evaluation>Y</evaluation> <unconditional>Y</unconditional> </hop> <hop> - <from>0089-mdi-multi-datagrid.hpl</from> + <from>0056-mdi-multi-datagrid.hpl</from> <to>Run Pipeline Unit Tests</to> <enabled>Y</enabled> <evaluation>Y</evaluation> diff --git a/integration-tests/mdi/main-0090-mdi-shared-field.hwf b/integration-tests/mdi/main-0057-mdi-shared-field.hwf similarity index 91% rename from integration-tests/mdi/main-0090-mdi-shared-field.hwf rename to integration-tests/mdi/main-0057-mdi-shared-field.hwf index 0de808ab38..5fb9b43b20 100644 --- a/integration-tests/mdi/main-0090-mdi-shared-field.hwf +++ b/integration-tests/mdi/main-0057-mdi-shared-field.hwf @@ -18,7 +18,7 @@ limitations under the License. --> <workflow> - <name>main-0090-mdi-shared-field</name> + <name>main-0057-mdi-shared-field</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> @@ -49,7 +49,7 @@ limitations under the License. <attributes_hac/> </action> <action> - <name>0090-mdi-shared-field.hpl</name> + <name>0057-mdi-shared-field.hpl</name> <description/> <type>PIPELINE</type> <attributes/> @@ -59,7 +59,7 @@ limitations under the License. <clear_rows>N</clear_rows> <create_parent_folder>N</create_parent_folder> <exec_per_row>N</exec_per_row> - <filename>${PROJECT_HOME}/0090-mdi-shared-field.hpl</filename> + <filename>${PROJECT_HOME}/0057-mdi-shared-field.hpl</filename> <loglevel>Basic</loglevel> <parameters> <pass_all_parameters>Y</pass_all_parameters> @@ -81,7 +81,7 @@ limitations under the License. <attributes/> <test_names> <test_name> - <name>0090-mdi-shared-field-template UNIT</name> + <name>0057-mdi-shared-field-template UNIT</name> </test_name> </test_names> <parallel>N</parallel> @@ -95,7 +95,7 @@ limitations under the License. <type>DELETE_FILE</type> <attributes/> <fail_if_file_not_exists>N</fail_if_file_not_exists> - <filename>${PROJECT_HOME}/0090-mdi-shared-field-template-injected.hpl</filename> + <filename>${PROJECT_HOME}/0057-mdi-shared-field-template-injected.hpl</filename> <parallel>N</parallel> <xloc>464</xloc> <yloc>272</yloc> @@ -105,13 +105,13 @@ limitations under the License. <hops> <hop> <from>Start</from> - <to>0090-mdi-shared-field.hpl</to> + <to>0057-mdi-shared-field.hpl</to> <enabled>Y</enabled> <evaluation>Y</evaluation> <unconditional>Y</unconditional> </hop> <hop> - <from>0090-mdi-shared-field.hpl</from> + <from>0057-mdi-shared-field.hpl</from> <to>Run Pipeline Unit Tests</to> <enabled>Y</enabled> <evaluation>Y</evaluation> diff --git a/integration-tests/mdi/main-0091-mdi-edge-cases.hwf b/integration-tests/mdi/main-0058-mdi-edge-cases.hwf similarity index 91% rename from integration-tests/mdi/main-0091-mdi-edge-cases.hwf rename to integration-tests/mdi/main-0058-mdi-edge-cases.hwf index 84f3cf408d..1232111bf6 100644 --- a/integration-tests/mdi/main-0091-mdi-edge-cases.hwf +++ b/integration-tests/mdi/main-0058-mdi-edge-cases.hwf @@ -18,7 +18,7 @@ limitations under the License. --> <workflow> - <name>main-0091-mdi-edge-cases</name> + <name>main-0058-mdi-edge-cases</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> <extended_description/> @@ -49,7 +49,7 @@ limitations under the License. <attributes_hac/> </action> <action> - <name>0091-mdi-edge-cases.hpl</name> + <name>0058-mdi-edge-cases.hpl</name> <description/> <type>PIPELINE</type> <attributes/> @@ -59,7 +59,7 @@ limitations under the License. <clear_rows>N</clear_rows> <create_parent_folder>N</create_parent_folder> <exec_per_row>N</exec_per_row> - <filename>${PROJECT_HOME}/0091-mdi-edge-cases.hpl</filename> + <filename>${PROJECT_HOME}/0058-mdi-edge-cases.hpl</filename> <loglevel>Basic</loglevel> <parameters> <pass_all_parameters>Y</pass_all_parameters> @@ -81,7 +81,7 @@ limitations under the License. <attributes/> <test_names> <test_name> - <name>0091-mdi-edge-cases-template UNIT</name> + <name>0058-mdi-edge-cases-template UNIT</name> </test_name> </test_names> <parallel>N</parallel> @@ -95,7 +95,7 @@ limitations under the License. <type>DELETE_FILE</type> <attributes/> <fail_if_file_not_exists>N</fail_if_file_not_exists> - <filename>${PROJECT_HOME}/0091-mdi-edge-cases-template-injected.hpl</filename> + <filename>${PROJECT_HOME}/0058-mdi-edge-cases-template-injected.hpl</filename> <parallel>N</parallel> <xloc>464</xloc> <yloc>272</yloc> @@ -105,13 +105,13 @@ limitations under the License. <hops> <hop> <from>Start</from> - <to>0091-mdi-edge-cases.hpl</to> + <to>0058-mdi-edge-cases.hpl</to> <enabled>Y</enabled> <evaluation>Y</evaluation> <unconditional>Y</unconditional> </hop> <hop> - <from>0091-mdi-edge-cases.hpl</from> + <from>0058-mdi-edge-cases.hpl</from> <to>Run Pipeline Unit Tests</to> <enabled>Y</enabled> <evaluation>Y</evaluation> diff --git a/integration-tests/mdi/main-0087-load-file-content.hwf b/integration-tests/mdi/main-0059-mdi-constant-variable.hwf similarity index 67% rename from integration-tests/mdi/main-0087-load-file-content.hwf rename to integration-tests/mdi/main-0059-mdi-constant-variable.hwf index ee4726a41f..910ae44e55 100644 --- a/integration-tests/mdi/main-0087-load-file-content.hwf +++ b/integration-tests/mdi/main-0059-mdi-constant-variable.hwf @@ -18,15 +18,13 @@ limitations under the License. --> <workflow> - <name>main-0087-load-file-content</name> + <name>main-0059-mdi-constant-variable</name> <name_sync_with_filename>Y</name_sync_with_filename> <description/> - <extended_description/> - <workflow_version/> <created_user>-</created_user> - <created_date>2026/03/19 09:54:45.798</created_date> + <created_date>2026/06/11 12:00:00.000</created_date> <modified_user>-</modified_user> - <modified_date>2026/03/19 09:54:45.798</modified_date> + <modified_date>2026/06/11 12:00:00.000</modified_date> <parameters> </parameters> <actions> @@ -35,22 +33,21 @@ limitations under the License. <description/> <type>SPECIAL</type> <attributes/> - <DayOfMonth>1</DayOfMonth> - <doNotWaitOnFirstExecution>N</doNotWaitOnFirstExecution> - <hour>12</hour> - <intervalMinutes>60</intervalMinutes> - <intervalSeconds>0</intervalSeconds> - <minutes>0</minutes> <repeat>N</repeat> <schedulerType>0</schedulerType> + <intervalSeconds>0</intervalSeconds> + <intervalMinutes>60</intervalMinutes> + <hour>12</hour> + <minutes>0</minutes> <weekDay>1</weekDay> + <DayOfMonth>1</DayOfMonth> <parallel>N</parallel> - <xloc>96</xloc> - <yloc>64</yloc> + <xloc>128</xloc> + <yloc>112</yloc> <attributes_hac/> </action> <action> - <name>0087-load-file-content.hpl</name> + <name>0059-mdi-constant-variable-parent.hpl</name> <description/> <type>PIPELINE</type> <attributes/> @@ -60,9 +57,7 @@ limitations under the License. <clear_rows>N</clear_rows> <create_parent_folder>N</create_parent_folder> <exec_per_row>N</exec_per_row> - <filename>${PROJECT_HOME}/0087-load-file-content.hpl</filename> - <logext/> - <logfile/> + <filename>${PROJECT_HOME}/0059-mdi-constant-variable-parent.hpl</filename> <loglevel>Basic</loglevel> <parameters> <pass_all_parameters>Y</pass_all_parameters> @@ -73,41 +68,19 @@ limitations under the License. <set_logfile>N</set_logfile> <wait_until_finished>Y</wait_until_finished> <parallel>N</parallel> - <xloc>256</xloc> - <yloc>64</yloc> - <attributes_hac/> - </action> - <action> - <name>0087-load-file-content-validate UNIT</name> - <description/> - <type>RunPipelineTests</type> - <attributes/> - <test_names> - <test_name> - <name>0087-load-file-content-validate UNIT</name> - </test_name> - </test_names> - <parallel>N</parallel> - <xloc>480</xloc> - <yloc>64</yloc> + <xloc>320</xloc> + <yloc>112</yloc> <attributes_hac/> </action> </actions> <hops> <hop> <from>Start</from> - <to>0087-load-file-content.hpl</to> + <to>0059-mdi-constant-variable-parent.hpl</to> <enabled>Y</enabled> <evaluation>Y</evaluation> <unconditional>Y</unconditional> </hop> - <hop> - <from>0087-load-file-content.hpl</from> - <to>0087-load-file-content-validate UNIT</to> - <enabled>Y</enabled> - <evaluation>Y</evaluation> - <unconditional>N</unconditional> - </hop> </hops> <notepads> </notepads> diff --git a/integration-tests/mdi/metadata/unit-test/0087-load-file-content-validate UNIT.json b/integration-tests/mdi/metadata/unit-test/0054-load-file-content-validate UNIT.json similarity index 97% rename from integration-tests/mdi/metadata/unit-test/0087-load-file-content-validate UNIT.json rename to integration-tests/mdi/metadata/unit-test/0054-load-file-content-validate UNIT.json index 12f8de0fe8..edeb465c5b 100644 --- a/integration-tests/mdi/metadata/unit-test/0087-load-file-content-validate UNIT.json +++ b/integration-tests/mdi/metadata/unit-test/0054-load-file-content-validate UNIT.json @@ -152,7 +152,7 @@ } ], "input_data_sets": [], - "name": "0087-load-file-content-validate UNIT", + "name": "0054-load-file-content-validate UNIT", "trans_test_tweaks": [], - "pipeline_filename": "./0087-load-file-content-validate.hpl" + "pipeline_filename": "./0054-load-file-content-validate.hpl" } \ No newline at end of file diff --git a/integration-tests/mdi/metadata/unit-test/0088-set-constant-value-parent UNIT.json b/integration-tests/mdi/metadata/unit-test/0055-set-constant-value-parent UNIT.json similarity index 82% rename from integration-tests/mdi/metadata/unit-test/0088-set-constant-value-parent UNIT.json rename to integration-tests/mdi/metadata/unit-test/0055-set-constant-value-parent UNIT.json index 1ce759f19c..f8d7ea2fe3 100644 --- a/integration-tests/mdi/metadata/unit-test/0088-set-constant-value-parent UNIT.json +++ b/integration-tests/mdi/metadata/unit-test/0055-set-constant-value-parent UNIT.json @@ -19,10 +19,10 @@ } ], "input_data_sets": [], - "name": "0088-set-constant-value-parent UNIT", + "name": "0055-set-constant-value-parent UNIT", "description": "", "trans_test_tweaks": [], "persist_filename": "", - "pipeline_filename": "./0088-set-constant-value-parent.hpl", + "pipeline_filename": "./0055-set-constant-value-parent.hpl", "test_type": "UNIT_TEST" } diff --git a/integration-tests/mdi/metadata/unit-test/0089-mdi-multi-datagrid-template UNIT.json b/integration-tests/mdi/metadata/unit-test/0056-mdi-multi-datagrid-template UNIT.json similarity index 85% rename from integration-tests/mdi/metadata/unit-test/0089-mdi-multi-datagrid-template UNIT.json rename to integration-tests/mdi/metadata/unit-test/0056-mdi-multi-datagrid-template UNIT.json index c97178eeca..197c4a187e 100644 --- a/integration-tests/mdi/metadata/unit-test/0089-mdi-multi-datagrid-template UNIT.json +++ b/integration-tests/mdi/metadata/unit-test/0056-mdi-multi-datagrid-template UNIT.json @@ -27,7 +27,7 @@ } ], "input_data_sets": [], - "name": "0089-mdi-multi-datagrid-template UNIT", + "name": "0056-mdi-multi-datagrid-template UNIT", "trans_test_tweaks": [], - "pipeline_filename": "./0089-mdi-multi-datagrid-template-injected.hpl" + "pipeline_filename": "./0056-mdi-multi-datagrid-template-injected.hpl" } diff --git a/integration-tests/mdi/metadata/unit-test/0090-mdi-shared-field-template UNIT.json b/integration-tests/mdi/metadata/unit-test/0057-mdi-shared-field-template UNIT.json similarity index 85% rename from integration-tests/mdi/metadata/unit-test/0090-mdi-shared-field-template UNIT.json rename to integration-tests/mdi/metadata/unit-test/0057-mdi-shared-field-template UNIT.json index d8807be526..45f1048eea 100644 --- a/integration-tests/mdi/metadata/unit-test/0090-mdi-shared-field-template UNIT.json +++ b/integration-tests/mdi/metadata/unit-test/0057-mdi-shared-field-template UNIT.json @@ -27,7 +27,7 @@ } ], "input_data_sets": [], - "name": "0090-mdi-shared-field-template UNIT", + "name": "0057-mdi-shared-field-template UNIT", "trans_test_tweaks": [], - "pipeline_filename": "./0090-mdi-shared-field-template-injected.hpl" + "pipeline_filename": "./0057-mdi-shared-field-template-injected.hpl" } diff --git a/integration-tests/mdi/metadata/unit-test/0091-mdi-edge-cases-template UNIT.json b/integration-tests/mdi/metadata/unit-test/0058-mdi-edge-cases-template UNIT.json similarity index 88% rename from integration-tests/mdi/metadata/unit-test/0091-mdi-edge-cases-template UNIT.json rename to integration-tests/mdi/metadata/unit-test/0058-mdi-edge-cases-template UNIT.json index b0e6adf20c..bb70d21dc3 100644 --- a/integration-tests/mdi/metadata/unit-test/0091-mdi-edge-cases-template UNIT.json +++ b/integration-tests/mdi/metadata/unit-test/0058-mdi-edge-cases-template UNIT.json @@ -37,7 +37,7 @@ } ], "input_data_sets": [], - "name": "0091-mdi-edge-cases-template UNIT", + "name": "0058-mdi-edge-cases-template UNIT", "trans_test_tweaks": [], - "pipeline_filename": "./0091-mdi-edge-cases-template-injected.hpl" + "pipeline_filename": "./0058-mdi-edge-cases-template-injected.hpl" } diff --git a/plugins/transforms/metainject/src/main/java/org/apache/hop/pipeline/transforms/metainject/MetaInject.java b/plugins/transforms/metainject/src/main/java/org/apache/hop/pipeline/transforms/metainject/MetaInject.java index db6d8e417a..58abda44b1 100644 --- a/plugins/transforms/metainject/src/main/java/org/apache/hop/pipeline/transforms/metainject/MetaInject.java +++ b/plugins/transforms/metainject/src/main/java/org/apache/hop/pipeline/transforms/metainject/MetaInject.java @@ -396,7 +396,7 @@ public class MetaInject extends BaseTransform<MetaInjectMeta, MetaInjectData> { // See if this is a constant without a source // if (StringUtils.isEmpty(mapping.getSourceTransformName())) { - addConstantToGroupData(mapping, injectionGroupData, groupKey); + addConstantToGroupData(this, mapping, injectionGroupData, groupKey); } } } else if (mapping.isTargetDetail()) { @@ -405,7 +405,7 @@ public class MetaInject extends BaseTransform<MetaInjectMeta, MetaInjectData> { // if (HopMetadataInjector.isTopLevelInjectionKey( targetMetaClass, mapping.getTargetAttributeKey())) { - collectInjectionKeyValue(mapping, sourceRows, injectionKeyData); + collectInjectionKeyValue(this, mapping, sourceRows, injectionKeyData); } else { throw new HopTransformException( "The injection group key for target key '" @@ -417,7 +417,7 @@ public class MetaInject extends BaseTransform<MetaInjectMeta, MetaInjectData> { // This also captures the "Constant" mappings where we don't have source rows to feed the // injection. // - collectInjectionKeyValue(mapping, sourceRows, injectionKeyData); + collectInjectionKeyValue(this, mapping, sourceRows, injectionKeyData); } } @@ -488,8 +488,12 @@ public class MetaInject extends BaseTransform<MetaInjectMeta, MetaInjectData> { */ record GroupColumn(String targetKey, String sourceTransformName, int columnIndex) {} - private static void addConstantToGroupData( - MetaInjectMapping mapping, Map<String, RowBuffer> injectionGroupData, String groupKey) { + // Package-private for unit testing of the constant-injection path (see MetaInjectTest). + static void addConstantToGroupData( + IVariables variables, + MetaInjectMapping mapping, + Map<String, RowBuffer> injectionGroupData, + String groupKey) { // We need to add or extend a single row in a row buffer for the given group. // RowBuffer rowBuffer = injectionGroupData.computeIfAbsent(groupKey, f -> new RowBuffer()); @@ -508,7 +512,8 @@ public class MetaInject extends BaseTransform<MetaInjectMeta, MetaInjectData> { row = rows.getFirst(); } row = RowDataUtil.createResizedCopy(row, rowMeta.size()); - row[rowMeta.size() - 1] = mapping.getSourceField(); + // Resolve variables in the constant value, just like the legacy newInjectionConstants() path. + row[rowMeta.size() - 1] = variables.resolve(mapping.getSourceField()); // Let's not forget to update the row after re-sizing it. rows.set(0, row); } @@ -562,7 +567,9 @@ public class MetaInject extends BaseTransform<MetaInjectMeta, MetaInjectData> { return null; } - private static void collectInjectionKeyValue( + // Package-private for unit testing of the constant-injection path (see MetaInjectTest). + static void collectInjectionKeyValue( + IVariables variables, MetaInjectMapping mapping, List<RowMetaAndData> sourceRows, Map<String, Object> injectionKeyData) @@ -571,8 +578,10 @@ public class MetaInject extends BaseTransform<MetaInjectMeta, MetaInjectData> { if (StringUtils.isEmpty(mapping.getSourceTransformName())) { // This is a constant String value to set. // The value is set in the source field. + // Resolve variables in the constant, just like the legacy newInjectionConstants() path. // - injectionKeyData.put(mapping.getTargetAttributeKey(), mapping.getSourceField()); + injectionKeyData.put( + mapping.getTargetAttributeKey(), variables.resolve(mapping.getSourceField())); } return; } diff --git a/plugins/transforms/metainject/src/test/java/org/apache/hop/pipeline/transforms/metainject/MetaInjectTest.java b/plugins/transforms/metainject/src/test/java/org/apache/hop/pipeline/transforms/metainject/MetaInjectTest.java index e364b40c9a..09d69dc333 100644 --- a/plugins/transforms/metainject/src/test/java/org/apache/hop/pipeline/transforms/metainject/MetaInjectTest.java +++ b/plugins/transforms/metainject/src/test/java/org/apache/hop/pipeline/transforms/metainject/MetaInjectTest.java @@ -42,6 +42,7 @@ import org.apache.hop.core.row.IRowMeta; import org.apache.hop.core.row.RowBuffer; import org.apache.hop.core.row.RowMeta; import org.apache.hop.core.row.value.ValueMetaString; +import org.apache.hop.core.variables.Variables; import org.apache.hop.metadata.api.IHopMetadataProvider; import org.apache.hop.pipeline.Pipeline; import org.apache.hop.pipeline.PipelineMeta; @@ -189,6 +190,50 @@ class MetaInjectTest { assertNull(targetMeta.there); } + /** + * Regression test: a constant value containing variables must be resolved before it is injected + * into a {@code @HopMetadataProperty} template transform. The legacy {@code @InjectionSupported} + * path ({@link MetaInject#newInjectionConstants}) always resolved them; the rewritten + * scalar-constant path did not, so variables leaked through unresolved (worked in 2.17). + */ + @Test + void collectInjectionKeyValue_resolvesVariablesInConstant() throws Exception { + Variables variables = new Variables(); + variables.setVariable("MY_VAR", "resolved-value"); + + // A "constant" mapping: no source transform, the literal value sits in the source field. + MetaInjectMapping mapping = new MetaInjectMapping(); + mapping.setTargetAttributeKey("SOME_KEY"); + mapping.setSourceTransformName(null); + mapping.setSourceField("${MY_VAR}"); + + Map<String, Object> injectionKeyData = new HashMap<>(); + MetaInject.collectInjectionKeyValue(variables, mapping, null, injectionKeyData); + + assertEquals("resolved-value", injectionKeyData.get("SOME_KEY")); + } + + /** + * Same regression as {@link #collectInjectionKeyValue_resolvesVariablesInConstant()} but for a + * constant that belongs to an injection group (list) key. + */ + @Test + void addConstantToGroupData_resolvesVariablesInConstant() { + Variables variables = new Variables(); + variables.setVariable("MY_VAR", "resolved-value"); + + MetaInjectMapping mapping = new MetaInjectMapping(); + mapping.setTargetAttributeKey("SOME_KEY"); + mapping.setSourceField("${MY_VAR}"); + + Map<String, RowBuffer> injectionGroupData = new HashMap<>(); + MetaInject.addConstantToGroupData(variables, mapping, injectionGroupData, "GROUP"); + + RowBuffer buffer = injectionGroupData.get("GROUP"); + assertNotNull(buffer); + assertEquals("resolved-value", buffer.getBuffer().getFirst()[0]); + } + /** * Regression test for <a href="https://github.com/apache/hop/issues/7246">#7246</a>: when an * injection group mixes a streamed key and a constant key, the constant value must be merged into
