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 d0d9092e88 [#5748] Fix evaluation of isAllowEmptySreamOnExecution
(#5957)
d0d9092e88 is described below
commit d0d9092e887b6f010c193b8483dc7e793959364c
Author: François Papon <[email protected]>
AuthorDate: Sun Nov 9 17:49:19 2025 +0100
[#5748] Fix evaluation of isAllowEmptySreamOnExecution (#5957)
* [#5748] Fix evaluation of isAllowEmptySreamOnExecution
* Allow constants only add tests with allowEmptyStream
---------
Co-authored-by: Hans Van Akelyen <[email protected]>
---
.../0032-injection-with-partial-information.hpl | 461 +++++++++++++++++++++
.../mdi/main-0032-mdi-with-partial-information.hwf | 117 ++++++
.../unit-test/0032-get-data-from-xml UNIT.json | 48 +++
.../pipeline/transforms/metainject/MetaInject.java | 11 +-
4 files changed, 636 insertions(+), 1 deletion(-)
diff --git a/integration-tests/mdi/0032-injection-with-partial-information.hpl
b/integration-tests/mdi/0032-injection-with-partial-information.hpl
new file mode 100644
index 0000000000..a2ff7b5b97
--- /dev/null
+++ b/integration-tests/mdi/0032-injection-with-partial-information.hpl
@@ -0,0 +1,461 @@
+<?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>
+ <name>0032-injection-with-partial-information</name>
+ <name_sync_with_filename>Y</name_sync_with_filename>
+ <description/>
+ <extended_description/>
+ <pipeline_version/>
+ <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>2025/09/02 11:28:05.214</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2025/09/02 11:28:05.214</modified_date>
+ </info>
+ <notepads>
+ </notepads>
+ <order>
+ <hop>
+ <from>metadata</from>
+ <to>ETL metadata injection</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>fields</from>
+ <to>ETL metadata injection</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>ETL metadata injection</from>
+ <to>OUTPUT</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>empty stream</from>
+ <to>Filter rows</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Filter rows</from>
+ <to>ETL metadata injection</to>
+ <enabled>Y</enabled>
+ </hop>
+ </order>
+ <transform>
+ <name>ETL metadata injection</name>
+ <type>MetaInject</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <filename>${PROJECT_HOME}/0031-get-data-from-xml-template.hpl</filename>
+ <run_configuration>local</run_configuration>
+ <source_transform>OUTPUT</source_transform>
+ <source_output_fields>
+ <source_output_field>
+ <source_output_field_name>xmlData</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>name</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>ppu</source_output_field_name>
+ <source_output_field_type>Number</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>batters</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>item_id</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>
+ <target_file/>
+ <create_parent_folder>Y</create_parent_folder>
+ <no_execution>N</no_execution>
+ <allow_empty_stream_on_execution>N</allow_empty_stream_on_execution>
+ <stream_source_transform/>
+ <stream_target_transform/>
+ <mappings>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>element_type</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Element</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>format</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Format</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>type</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Type</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>result_type</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Result Type</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>XmlField</target_attribute_key>
+ <target_detail>N</target_detail>
+ <source_transform>metadata</source_transform>
+ <source_field>XML_Source_Field</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>loopxpath</target_attribute_key>
+ <target_detail>N</target_detail>
+ <source_transform>metadata</source_transform>
+ <source_field>Xpath</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>name</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Name</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>group</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Group</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>decimal</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Decimal</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>xPath</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>fields</source_transform>
+ <source_field>Xpath</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>IsInFields</target_attribute_key>
+ <target_detail>N</target_detail>
+ <source_transform>metadata</source_transform>
+ <source_field>XML_source_in_field</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>Get data from XML</target_transform_name>
+ <target_attribute_key>usetoken</target_attribute_key>
+ <target_detail>N</target_detail>
+ <source_transform>empty stream</source_transform>
+ <source_field>use_token</source_field>
+ </mapping>
+ </mappings>
+ <attributes/>
+ <GUI>
+ <xloc>416</xloc>
+ <yloc>64</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Filter rows</name>
+ <type>FilterRows</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <compare>
+ <condition>
+ <conditions>
+</conditions>
+ <function>=</function>
+ <leftvalue>use_token</leftvalue>
+ <negated>N</negated>
+ <operator>-</operator>
+ <value>
+ <isnull>N</isnull>
+ <length>-1</length>
+ <name>constant</name>
+ <precision>-1</precision>
+ <text>Y</text>
+ <type>Boolean</type>
+ </value>
+ </condition>
+ </compare>
+ <attributes/>
+ <GUI>
+ <xloc>272</xloc>
+ <yloc>160</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>OUTPUT</name>
+ <type>Dummy</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <attributes/>
+ <GUI>
+ <xloc>624</xloc>
+ <yloc>64</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>empty stream</name>
+ <type>DataGrid</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <data>
+ <line>
+ <item/>
+ </line>
+ </data>
+ <fields>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>use_token</name>
+ <type>Boolean</type>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>128</xloc>
+ <yloc>272</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>fields</name>
+ <type>DataGrid</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <data>
+ <line>
+ <item>name</item>
+ <item>name</item>
+ <item>Node</item>
+ <item>valueof</item>
+ <item>String</item>
+ <item/>
+ <item/>
+ <item/>
+ </line>
+ <line>
+ <item>ppu</item>
+ <item>ppu</item>
+ <item>Node</item>
+ <item>valueof</item>
+ <item>Number</item>
+ <item>#,##0.###</item>
+ <item>.</item>
+ <item>,</item>
+ </line>
+ <line>
+ <item>batters</item>
+ <item>batters</item>
+ <item>Node</item>
+ <item>singlenode</item>
+ <item>String</item>
+ <item/>
+ <item/>
+ <item/>
+ </line>
+ <line>
+ <item>item_id</item>
+ <item>id</item>
+ <item>Attribute</item>
+ <item>valueof</item>
+ <item>String</item>
+ <item/>
+ <item/>
+ <item/>
+ </line>
+ </data>
+ <fields>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Name</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Xpath</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Element</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Result Type</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Type</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Format</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Decimal</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Group</name>
+ <type>String</type>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>128</xloc>
+ <yloc>160</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>metadata</name>
+ <type>DataGrid</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <data>
+ <line>
+ <item>Y</item>
+ <item>xmlData</item>
+ <item>/items/item</item>
+ </line>
+ </data>
+ <fields>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>XML_source_in_field</name>
+ <type>Boolean</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>XML_Source_Field</name>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <name>Xpath</name>
+ <type>String</type>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>128</xloc>
+ <yloc>64</yloc>
+ </GUI>
+ </transform>
+ <transform_error_handling>
+ </transform_error_handling>
+ <attributes/>
+</pipeline>
diff --git a/integration-tests/mdi/main-0032-mdi-with-partial-information.hwf
b/integration-tests/mdi/main-0032-mdi-with-partial-information.hwf
new file mode 100644
index 0000000000..40b15fb5f8
--- /dev/null
+++ b/integration-tests/mdi/main-0032-mdi-with-partial-information.hwf
@@ -0,0 +1,117 @@
+<?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.
+
+-->
+<workflow>
+ <name>main-0032-mdi-with-partial-information</name>
+ <name_sync_with_filename>Y</name_sync_with_filename>
+ <description/>
+ <extended_description/>
+ <workflow_version/>
+ <created_user>-</created_user>
+ <created_date>2025/09/02 11:24:45.914</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2025/09/02 11:24:45.914</modified_date>
+ <parameters>
+ </parameters>
+ <actions>
+ <action>
+ <name>Start</name>
+ <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>
+ <weekDay>1</weekDay>
+ <parallel>N</parallel>
+ <xloc>80</xloc>
+ <yloc>64</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>Run Pipeline Unit Tests</name>
+ <description/>
+ <type>RunPipelineTests</type>
+ <attributes/>
+ <test_names>
+ <test_name>
+ <name>0032-get-data-from-xml UNIT</name>
+ </test_name>
+ </test_names>
+ <parallel>N</parallel>
+ <xloc>256</xloc>
+ <yloc>64</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>Success</name>
+ <description/>
+ <type>SUCCESS</type>
+ <attributes/>
+ <parallel>N</parallel>
+ <xloc>448</xloc>
+ <yloc>64</yloc>
+ <attributes_hac/>
+ </action>
+ </actions>
+ <hops>
+ <hop>
+ <from>Start</from>
+ <to>Run Pipeline Unit Tests</to>
+ <enabled>Y</enabled>
+ <evaluation>Y</evaluation>
+ <unconditional>Y</unconditional>
+ </hop>
+ <hop>
+ <from>Run Pipeline Unit Tests</from>
+ <to>Success</to>
+ <enabled>Y</enabled>
+ <evaluation>N</evaluation>
+ <unconditional>N</unconditional>
+ </hop>
+ </hops>
+ <notepads>
+ <notepad>
+ <backgroundcolorblue>251</backgroundcolorblue>
+ <backgroundcolorgreen>232</backgroundcolorgreen>
+ <backgroundcolorred>201</backgroundcolorred>
+ <bordercolorblue>90</bordercolorblue>
+ <bordercolorgreen>58</bordercolorgreen>
+ <bordercolorred>14</bordercolorred>
+ <fontbold>N</fontbold>
+ <fontcolorblue>90</fontcolorblue>
+ <fontcolorgreen>58</fontcolorgreen>
+ <fontcolorred>14</fontcolorred>
+ <fontitalic>N</fontitalic>
+ <fontname>.AppleSystemUIFont</fontname>
+ <fontsize>13</fontsize>
+ <height>26</height>
+ <xloc>64</xloc>
+ <yloc>160</yloc>
+ <note>should fail</note>
+ <width>72</width>
+ </notepad>
+ </notepads>
+ <attributes/>
+</workflow>
diff --git a/integration-tests/mdi/metadata/unit-test/0032-get-data-from-xml
UNIT.json b/integration-tests/mdi/metadata/unit-test/0032-get-data-from-xml
UNIT.json
new file mode 100644
index 0000000000..bb5bea3365
--- /dev/null
+++ b/integration-tests/mdi/metadata/unit-test/0032-get-data-from-xml UNIT.json
@@ -0,0 +1,48 @@
+{
+ "database_replacements": [],
+ "autoOpening": true,
+ "description": "",
+ "persist_filename": "",
+ "test_type": "UNIT_TEST",
+ "variableValues": [],
+ "basePath": "",
+ "golden_data_sets": [
+ {
+ "field_mappings": [
+ {
+ "transform_field": "xmlData",
+ "data_set_field": "xmlData"
+ },
+ {
+ "transform_field": "name",
+ "data_set_field": "name"
+ },
+ {
+ "transform_field": "ppu",
+ "data_set_field": "ppu"
+ },
+ {
+ "transform_field": "batters",
+ "data_set_field": "batters"
+ },
+ {
+ "transform_field": "item_id",
+ "data_set_field": "item_id"
+ }
+ ],
+ "field_order": [
+ "xmlData",
+ "name",
+ "ppu",
+ "batters",
+ "item_id"
+ ],
+ "data_set_name": "golden-get-data-from-xml",
+ "transform_name": "OUTPUT"
+ }
+ ],
+ "input_data_sets": [],
+ "name": "0032-get-data-from-xml UNIT",
+ "trans_test_tweaks": [],
+ "pipeline_filename": "./0032-injection-with-partial-information.hpl"
+}
\ No newline at end of file
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 9244a51e04..7682e7188c 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
@@ -85,6 +85,12 @@ public class MetaInject extends
BaseTransform<MetaInjectMeta, MetaInjectData> {
boolean receivedRows = false;
boolean hasEmptyList = false;
+ // If there are no previous transforms we will set receivedRows to true.
This allows execution
+ // using constants only
+ if (getPipelineMeta().getPrevTransformNames(getTransformMeta()).length ==
0) {
+ receivedRows = true;
+ }
+
for (String prevTransformName :
getPipelineMeta().getPrevTransformNames(getTransformMeta())) {
// Don't read from the streaming source transform
//
@@ -109,7 +115,10 @@ public class MetaInject extends
BaseTransform<MetaInjectMeta, MetaInjectData> {
}
}
}
- if (!receivedRows && (hasEmptyList &&
!meta.isAllowEmptyStreamOnExecution())) {
+
+ // Check if all previous transforms are returning data, unless
isAllowEmptyStreamOnExecution is
+ // true then execute if at least one branch has data
+ if (!receivedRows || (hasEmptyList &&
!meta.isAllowEmptyStreamOnExecution())) {
setOutputDone();
return false;
}