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 f92fc00f5c Issue #6603 (New DDL transform with docs and IT) (#6737)
f92fc00f5c is described below

commit f92fc00f5c95c22a50947d14c293cdca504d65e6
Author: Matt Casters <[email protected]>
AuthorDate: Mon Mar 9 15:30:11 2026 +0100

    Issue #6603 (New DDL transform with docs and IT) (#6737)
    
    * Issue #6603 (New DDL transform with docs and IT)
    
    * Issue #6603 (IT)
    
    * add to nav
    
    ---------
    
    Co-authored-by: Hans Van Akelyen <[email protected]>
---
 assemblies/plugins/pom.xml                         |   6 +
 docs/hop-user-manual/modules/ROOT/nav.adoc         |   1 +
 .../ROOT/pages/pipeline/transforms/ddl.adoc        |  89 ++++++++++
 integration-tests/database/0037-ddl.hpl            | 176 +++++++++++++++++++
 integration-tests/database/datasets/golden-ddl.csv |   7 +
 integration-tests/database/main-0037-ddl.hwf       | 136 +++++++++++++++
 .../database/metadata/dataset/golden-ddl.json      |  16 ++
 .../database/metadata/unit-test/0037-ddl UNIT.json |  28 ++++
 plugins/transforms/ddl/pom.xml                     |  31 ++++
 plugins/transforms/ddl/src/assembly/assembly.xml   |  50 ++++++
 .../apache/hop/pipeline/transforms/ddl/Ddl.java    | 167 ++++++++++++++++++
 .../hop/pipeline/transforms/ddl/DdlData.java       |  42 +++++
 .../hop/pipeline/transforms/ddl/DdlDialog.java     |  95 +++++++++++
 .../hop/pipeline/transforms/ddl/DdlMeta.java       | 186 +++++++++++++++++++++
 plugins/transforms/ddl/src/main/resources/ddl.svg  |  28 ++++
 .../ddl/messages/messages_en_US.properties         |  40 +++++
 .../transforms/ddl/src/main/resources/version.xml  |  20 +++
 plugins/transforms/pom.xml                         |   1 +
 .../hop/ui/core/gui/GuiCompositeWidgets.java       |  30 +++-
 19 files changed, 1147 insertions(+), 2 deletions(-)

diff --git a/assemblies/plugins/pom.xml b/assemblies/plugins/pom.xml
index 5571864db8..ba5c2a7248 100644
--- a/assemblies/plugins/pom.xml
+++ b/assemblies/plugins/pom.xml
@@ -955,6 +955,12 @@
             <version>${project.version}</version>
             <type>zip</type>
         </dependency>
+        <dependency>
+            <groupId>org.apache.hop</groupId>
+            <artifactId>hop-transform-ddl</artifactId>
+            <version>${project.version}</version>
+            <type>zip</type>
+        </dependency>
         <dependency>
             <groupId>org.apache.hop</groupId>
             <artifactId>hop-transform-delay</artifactId>
diff --git a/docs/hop-user-manual/modules/ROOT/nav.adoc 
b/docs/hop-user-manual/modules/ROOT/nav.adoc
index 364c561658..66e920aef9 100644
--- a/docs/hop-user-manual/modules/ROOT/nav.adoc
+++ b/docs/hop-user-manual/modules/ROOT/nav.adoc
@@ -117,6 +117,7 @@ under the License.
 *** xref:pipeline/transforms/datagrid.adoc[Data Grid]
 *** xref:pipeline/transforms/datasetinput.adoc[Data Set Input]
 *** xref:pipeline/transforms/dbimpactinput.adoc[Database Impact Input]
+*** xref:pipeline/transforms/ddl.adoc[DDL Generator]
 *** xref:pipeline/transforms/validator.adoc[Data Validator]
 *** xref:pipeline/transforms/delay.adoc[Delay row]
 *** xref:pipeline/transforms/delete.adoc[Delete]
diff --git 
a/docs/hop-user-manual/modules/ROOT/pages/pipeline/transforms/ddl.adoc 
b/docs/hop-user-manual/modules/ROOT/pages/pipeline/transforms/ddl.adoc
new file mode 100644
index 0000000000..f4effbaab1
--- /dev/null
+++ b/docs/hop-user-manual/modules/ROOT/pages/pipeline/transforms/ddl.adoc
@@ -0,0 +1,89 @@
+////
+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.
+////
+:documentationPath: /pipeline/transforms/
+:language: en_US
+:description: The DDL transform generates SQL Data Definition Language.
+
+= image:transforms/icons/ddl.svg[DDL Icon, role="image-doc-icon"] DDL
+
+[%noheader,cols="3a,1a", role="table-no-borders" ]
+|===
+|
+== Description
+
+This transform generates 
https://en.wikipedia.org/wiki/Data_definition_language[DDL] using column 
metadata taken from input rows.
+
+|
+== Supported Engines
+[%noheader,cols="2,1a",frame=none, role="table-supported-engines"]
+!===
+!Hop Engine! image:check_mark.svg[Supported, 24]
+!Spark! image:check_mark.svg[Supported, 24]
+!Flink! image:check_mark.svg[Supported, 24]
+!Dataflow! image:check_mark.svg[Supported, 24]
+!===
+|===
+
+== Options
+
+[options="header]
+|===
+|Option|Description
+|Transform name|Name of the transform.
+This name has to be unique in a single pipeline.
+|Connection name|The name of the database connection to use for the SQL 
dialect and execution.
+|Table schema|The database schema for the table.
+|Table name|The name of the table to generate the DDL for.
+|Column field name|The name of the input field to contain the table column 
name.
+|Column type name|The name of the input field to contain the Apache Hop type 
for the column name.  It will get translated into the correct type for the 
chosen database.
+|Column length name|The name of the input field to contain the column length.
+|Column precision name|The name of the input field to contain the column 
precision.
+|Execute DDL?|Execute the generated DDL?
+|DDL output field (optional)|Specify the name of the field to contain the 
generated SQL in the output.
+|Load all data from table|Pre-loads the cache with all the data present in the 
lookup table.
+|Drop table before creation?|Check this option if you want to always re-create 
the specified table. The table is NOT dropped if the DDL is not executed.
+
+*IMPORTANT*: USE WITH CAUTION!
+|===
+
+== Example
+
+We have 2 input rows for the DDL transform:
+
+[options="header]
+|===
+|name|hopType|length|precision
+|id|Integer|9|0
+|name|String|100|-1
+|===
+
+For a standard https://en.wikipedia.org/wiki/H2_Database_Engine[H2] database 
we can generate the DDL for table `ddlTest`.  At runtime it will generate
+
+[source,sql]
+----
+CREATE TABLE ddlTest
+(
+  id INT
+, name VARCHAR(100)
+)
+;
+----
+
+== Hop Metadata
+
+If you want to re-use field level metadata you can consider using the 
xref:pipeline/transforms/metadata-input.adoc[Metadata Input] transform.  For 
example, you can get access to the JSON of 
xref:metadata-types/beam-file-definition.adoc[Beam File Definition] or 
xref:metadata-types/static-schema-definition.adoc[Static Schema Definition] 
elements.  You can then use the xref:pipeline/transforms/jsoninput.adoc[JSON 
Input] transform to parse the metadata and extract the 4 fields you need.
+
diff --git a/integration-tests/database/0037-ddl.hpl 
b/integration-tests/database/0037-ddl.hpl
new file mode 100644
index 0000000000..936db3940b
--- /dev/null
+++ b/integration-tests/database/0037-ddl.hpl
@@ -0,0 +1,176 @@
+<?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>0037-ddl</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>2026/03/08 11:07:31.788</created_date>
+    <modified_user>-</modified_user>
+    <modified_date>2026/03/08 11:07:31.788</modified_date>
+  </info>
+  <notepads>
+  </notepads>
+  <order>
+    <hop>
+      <from>columns</from>
+      <to>DDL</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>DDL</from>
+      <to>Check</to>
+      <enabled>Y</enabled>
+    </hop>
+  </order>
+  <transform>
+    <name>columns</name>
+    <type>DataGrid</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <data>
+      <line>
+        <item>id</item>
+        <item>Integer</item>
+        <item>9</item>
+        <item>0</item>
+      </line>
+      <line>
+        <item>name</item>
+        <item>String</item>
+        <item>100</item>
+        <item>-1</item>
+      </line>
+    </data>
+    <fields>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <currency/>
+        <set_empty_string>N</set_empty_string>
+        <name>name</name>
+        <format/>
+        <group/>
+        <decimal/>
+        <type>String</type>
+      </field>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <currency/>
+        <set_empty_string>N</set_empty_string>
+        <name>hopType</name>
+        <format/>
+        <group/>
+        <decimal/>
+        <type>String</type>
+      </field>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <currency/>
+        <set_empty_string>N</set_empty_string>
+        <name>length</name>
+        <format/>
+        <group/>
+        <decimal/>
+        <type>String</type>
+      </field>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <currency/>
+        <set_empty_string>N</set_empty_string>
+        <name>precision</name>
+        <format/>
+        <group/>
+        <decimal/>
+        <type>String</type>
+      </field>
+    </fields>
+    <attributes/>
+    <GUI>
+      <xloc>144</xloc>
+      <yloc>112</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>DDL</name>
+    <type>DDL</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <connection>h2-db</connection>
+    <ddlOutputField>ddl</ddlOutputField>
+    <droppingTable>Y</droppingTable>
+    <executingDdl>Y</executingDdl>
+    <fieldLengthField>length</fieldLengthField>
+    <fieldNameField>name</fieldNameField>
+    <fieldPrecisionField>precision</fieldPrecisionField>
+    <fieldTypeField>hopType</fieldTypeField>
+    <schemaName/>
+    <tableName>ddlTest</tableName>
+    <attributes/>
+    <GUI>
+      <xloc>256</xloc>
+      <yloc>112</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Check</name>
+    <type>Dummy</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>352</xloc>
+      <yloc>112</yloc>
+    </GUI>
+  </transform>
+  <transform_error_handling>
+  </transform_error_handling>
+  <attributes/>
+</pipeline>
diff --git a/integration-tests/database/datasets/golden-ddl.csv 
b/integration-tests/database/datasets/golden-ddl.csv
new file mode 100644
index 0000000000..58db98d8bb
--- /dev/null
+++ b/integration-tests/database/datasets/golden-ddl.csv
@@ -0,0 +1,7 @@
+ddl
+"CREATE TABLE ddlTest
+(
+  id INT
+, name VARCHAR(100)
+)
+;"
diff --git a/integration-tests/database/main-0037-ddl.hwf 
b/integration-tests/database/main-0037-ddl.hwf
new file mode 100644
index 0000000000..48336ecfd9
--- /dev/null
+++ b/integration-tests/database/main-0037-ddl.hwf
@@ -0,0 +1,136 @@
+<?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-0037-ddl</name>
+  <name_sync_with_filename>Y</name_sync_with_filename>
+  <description/>
+  <extended_description/>
+  <workflow_version/>
+  <created_user>-</created_user>
+  <created_date>2026/03/08 11:07:03.139</created_date>
+  <modified_user>-</modified_user>
+  <modified_date>2026/03/08 11:07:03.139</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>0037-ddl UNIT</name>
+        </test_name>
+      </test_names>
+      <parallel>N</parallel>
+      <xloc>208</xloc>
+      <yloc>64</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>ddlTest exists?</name>
+      <description/>
+      <type>TABLE_EXISTS</type>
+      <attributes/>
+      <connection>h2-db</connection>
+      <schemaname/>
+      <tablename>DDLTEST</tablename>
+      <parallel>N</parallel>
+      <xloc>336</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>
+    <action>
+      <name>Abort workflow</name>
+      <description/>
+      <type>ABORT</type>
+      <attributes/>
+      <always_log_rows>Y</always_log_rows>
+      <message>The ddlTest table was not created using the DDL 
transform</message>
+      <parallel>N</parallel>
+      <xloc>336</xloc>
+      <yloc>160</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>ddlTest exists?</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>ddlTest exists?</from>
+      <to>Success</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>ddlTest exists?</from>
+      <to>Abort workflow</to>
+      <enabled>Y</enabled>
+      <evaluation>N</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+  </hops>
+  <notepads>
+  </notepads>
+  <attributes/>
+</workflow>
diff --git a/integration-tests/database/metadata/dataset/golden-ddl.json 
b/integration-tests/database/metadata/dataset/golden-ddl.json
new file mode 100644
index 0000000000..9e569ea493
--- /dev/null
+++ b/integration-tests/database/metadata/dataset/golden-ddl.json
@@ -0,0 +1,16 @@
+{
+  "base_filename": "golden-ddl.csv",
+  "name": "golden-ddl",
+  "description": "",
+  "dataset_fields": [
+    {
+      "field_comment": "",
+      "field_length": 65535,
+      "field_type": 2,
+      "field_precision": -1,
+      "field_name": "ddl",
+      "field_format": ""
+    }
+  ],
+  "folder_name": ""
+}
\ No newline at end of file
diff --git a/integration-tests/database/metadata/unit-test/0037-ddl UNIT.json 
b/integration-tests/database/metadata/unit-test/0037-ddl UNIT.json
new file mode 100644
index 0000000000..3fa626e22b
--- /dev/null
+++ b/integration-tests/database/metadata/unit-test/0037-ddl UNIT.json  
@@ -0,0 +1,28 @@
+{
+  "database_replacements": [],
+  "autoOpening": true,
+  "description": "",
+  "persist_filename": "",
+  "test_type": "UNIT_TEST",
+  "variableValues": [],
+  "basePath": "${HOP_UNIT_TESTS_FOLDER}",
+  "golden_data_sets": [
+    {
+      "field_mappings": [
+        {
+          "transform_field": "ddl",
+          "data_set_field": "ddl"
+        }
+      ],
+      "field_order": [
+        "ddl"
+      ],
+      "data_set_name": "golden-ddl",
+      "transform_name": "Check"
+    }
+  ],
+  "input_data_sets": [],
+  "name": "0037-ddl UNIT",
+  "trans_test_tweaks": [],
+  "pipeline_filename": "./0037-ddl.hpl"
+}
\ No newline at end of file
diff --git a/plugins/transforms/ddl/pom.xml b/plugins/transforms/ddl/pom.xml
new file mode 100644
index 0000000000..91e3167214
--- /dev/null
+++ b/plugins/transforms/ddl/pom.xml
@@ -0,0 +1,31 @@
+<?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.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.hop</groupId>
+        <artifactId>hop-plugins-transforms</artifactId>
+        <version>2.18.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>hop-transform-ddl</artifactId>
+    <packaging>jar</packaging>
+    <name>Hop Plugins Transforms DDL</name>
+
+</project>
diff --git a/plugins/transforms/ddl/src/assembly/assembly.xml 
b/plugins/transforms/ddl/src/assembly/assembly.xml
new file mode 100644
index 0000000000..40d37ebcbe
--- /dev/null
+++ b/plugins/transforms/ddl/src/assembly/assembly.xml
@@ -0,0 +1,50 @@
+<!--
+  ~ 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.
+  ~
+  -->
+
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 
http://maven.apache.org/xsd/assembly-2.2.0.xsd";>
+    <id>hop-transform-ddl</id>
+    <formats>
+        <format>zip</format>
+    </formats>
+    <baseDirectory>.</baseDirectory>
+    <files>
+        <file>
+            <source>${project.basedir}/src/main/resources/version.xml</source>
+            <outputDirectory>plugins/transforms/ddl</outputDirectory>
+            <filtered>true</filtered>
+        </file>
+    </files>
+
+    <fileSets>
+        <fileSet>
+            <directory>${project.basedir}/src/main/samples</directory>
+            <outputDirectory>config/projects/samples/</outputDirectory>
+        </fileSet>
+    </fileSets>
+
+    <dependencySets>
+        <dependencySet>
+            <includes>
+                <include>org.apache.hop:hop-transform-ddl:jar</include>
+            </includes>
+            <outputDirectory>plugins/transforms/ddl</outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
\ No newline at end of file
diff --git 
a/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/Ddl.java
 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/Ddl.java
new file mode 100644
index 0000000000..b9e0b205d8
--- /dev/null
+++ 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/Ddl.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+package org.apache.hop.pipeline.transforms.ddl;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.database.Database;
+import org.apache.hop.core.database.DatabaseMeta;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.RowDataUtil;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransform;
+import org.apache.hop.pipeline.transform.TransformMeta;
+
+/** Transform that will abort after having seen 'x' number of rows on its 
input. */
+public class Ddl extends BaseTransform<DdlMeta, DdlData> {
+  public Ddl(
+      TransformMeta transformMeta,
+      DdlMeta meta,
+      DdlData data,
+      int copyNr,
+      PipelineMeta pipelineMeta,
+      Pipeline pipeline) {
+    super(transformMeta, meta, data, copyNr, pipelineMeta, pipeline);
+  }
+
+  @Override
+  public boolean init() {
+    if (!super.init()) {
+      return false;
+    }
+    // Add init code here.
+    //
+    data.connectionName = resolve(meta.getConnectionName());
+    if (StringUtils.isEmpty(data.connectionName)) {
+      logError("There is no database connection name specified.");
+      setErrors(1L);
+      return false;
+    }
+    try {
+      data.databaseMeta =
+          
metadataProvider.getSerializer(DatabaseMeta.class).load(data.connectionName);
+    } catch (HopException e) {
+      logError("Error loading database connection " + data.connectionName, e);
+      setErrors(1L);
+      return false;
+    }
+    data.schemaName = resolve(meta.getSchemaName());
+    data.tableName = resolve(meta.getTableName());
+    data.nameField = resolve(meta.getFieldNameField());
+    data.typeField = resolve(meta.getFieldTypeField());
+    data.lengthField = resolve(meta.getFieldLengthField());
+    data.precisionField = resolve(meta.getFieldPrecisionField());
+    data.ddlOutputField = resolve(meta.getDdlOutputField());
+    data.ddlRowMeta = new RowMeta();
+    return true;
+  }
+
+  @Override
+  public boolean processRow() throws HopException {
+    // Get row from input rowset & set row busy!
+    Object[] r = getRow();
+
+    // no more input to be expected...
+    if (r == null) {
+      // This is where we have the complete row metadata for the target table.
+      //
+      executeDdl();
+
+      setOutputDone();
+      return false;
+    }
+
+    String name = getInputRowMeta().getString(r, data.nameField, null);
+    if (StringUtils.isEmpty(name)) {
+      throw new HopException(
+          "The field name in '" + data.nameField + "' of the input row is 
empty");
+    }
+
+    String type = getInputRowMeta().getString(r, data.typeField, null);
+    if (StringUtils.isEmpty(type)) {
+      throw new HopException(
+          "The field type in '" + data.typeField + "' of the input row is not 
specified");
+    }
+    int hopType = ValueMetaFactory.getIdForValueMeta(type);
+
+    String lengthString = getInputRowMeta().getString(r, data.lengthField, 
null);
+    int length = Const.toInt(lengthString, -1);
+    String precisionString = getInputRowMeta().getString(r, 
data.precisionField, null);
+    int precision = Const.toInt(precisionString, -1);
+
+    IValueMeta valueMeta = ValueMetaFactory.createValueMeta(name, hopType, 
length, precision);
+    data.ddlRowMeta.addValueMeta(valueMeta);
+
+    return true;
+  }
+
+  private void executeDdl() throws HopException {
+    try {
+      try (Database database = new Database(this, this, data.databaseMeta)) {
+        database.connect();
+
+        String schemaTable =
+            data.databaseMeta.getQuotedSchemaTableCombination(
+                this, data.schemaName, data.tableName);
+
+        // We'll only drop the table if we're executing DDL, just to avoid 
confusion.
+        //
+        if (meta.isExecutingDdl() && meta.isDroppingTable()) {
+          boolean tableExists = database.checkTableExists(data.schemaName, 
data.tableName);
+          if (tableExists) {
+            database.execStatement("DROP TABLE " + schemaTable);
+            logBasic("Table " + schemaTable + " was dropped.");
+          }
+        }
+
+        String ddl = database.getDDL(schemaTable, data.ddlRowMeta);
+        if (StringUtils.isEmpty(ddl)) {
+          // We're done here.  The table looks fine as it is.
+          //
+          logDetailed("There was nothing to execute for table '" + schemaTable 
+ "'.");
+          return;
+        }
+
+        // Do we need to execute the DDL?
+        //
+        if (meta.isExecutingDdl()) {
+          database.execStatements(ddl);
+          incrementLinesOutput();
+        }
+
+        // Output the generated DDL?
+        //
+        if (StringUtils.isNotEmpty(data.ddlOutputField)) {
+          IRowMeta outputRowMeta = getInputRowMeta().clone();
+          meta.getFields(outputRowMeta, getTransformName(), null, null, this, 
metadataProvider);
+          Object[] outputRow = 
RowDataUtil.allocateRowData(outputRowMeta.size());
+          outputRow[0] = ddl;
+          putRow(outputRowMeta, outputRow);
+        }
+      }
+    } catch (Exception e) {
+      throw new HopException(
+          "Error executing DDL for row metadata: " + 
data.ddlRowMeta.toStringMeta(), e);
+    }
+  }
+}
diff --git 
a/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlData.java
 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlData.java
new file mode 100644
index 0000000000..2c921ddf19
--- /dev/null
+++ 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlData.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+package org.apache.hop.pipeline.transforms.ddl;
+
+import org.apache.hop.core.database.DatabaseMeta;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.pipeline.transform.BaseTransformData;
+import org.apache.hop.pipeline.transform.ITransformData;
+
+/** Data class for the Ddl transform. */
+public class DdlData extends BaseTransformData implements ITransformData {
+  public String connectionName;
+  public DatabaseMeta databaseMeta;
+  public String schemaName;
+  public String tableName;
+  public String nameField;
+  public String typeField;
+  public String lengthField;
+  public String precisionField;
+  public IRowMeta ddlRowMeta;
+  public String ddlOutputField;
+
+  /** Default constructor for DdlData. */
+  public DdlData() {
+    // Not used
+  }
+}
diff --git 
a/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlDialog.java
 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlDialog.java
new file mode 100644
index 0000000000..ac25471ae2
--- /dev/null
+++ 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlDialog.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+package org.apache.hop.pipeline.transforms.ddl;
+
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.ui.core.dialog.BaseDialog;
+import org.apache.hop.ui.core.gui.GuiCompositeWidgets;
+import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
+import org.eclipse.swt.widgets.Shell;
+
+public class DdlDialog extends BaseTransformDialog {
+  private static final Class<?> PKG = DdlDialog.class;
+
+  private final DdlMeta input;
+  private GuiCompositeWidgets widgets;
+
+  public DdlDialog(
+      Shell parent, IVariables variables, DdlMeta transformMeta, PipelineMeta 
pipelineMeta) {
+    super(parent, variables, transformMeta, pipelineMeta);
+    input = transformMeta;
+  }
+
+  @Override
+  public String open() {
+    createShell(BaseMessages.getString(PKG, "Ddl.Name"));
+
+    buildButtonBar().ok(e -> ok()).cancel(e -> cancel()).build();
+
+    // Add the widgets from metadata...
+    //
+    widgets = new GuiCompositeWidgets(variables);
+    widgets.createCompositeWidgets(
+        input, null, shell, DdlMeta.GUI_PLUGIN_ELEMENT_PARENT_ID, 
wTransformName);
+    widgets.setWidgetsContents(input, shell, 
DdlMeta.GUI_PLUGIN_ELEMENT_PARENT_ID);
+
+    setFieldNamesOnComboWidgets();
+
+    focusTransformName();
+    BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
+
+    return transformName;
+  }
+
+  /** Cancel the dialog. */
+  private void cancel() {
+    transformName = null;
+    dispose();
+  }
+
+  private void ok() {
+    if (Utils.isEmpty(wTransformName.getText())) {
+      return;
+    }
+
+    widgets.getWidgetsContents(input, DdlMeta.GUI_PLUGIN_ELEMENT_PARENT_ID);
+
+    // return value
+    transformName = wTransformName.getText();
+    dispose();
+  }
+
+  private void setFieldNamesOnComboWidgets() {
+    // The input field names:
+    String[] fieldNames;
+    try {
+      fieldNames = pipelineMeta.getPrevTransformFields(variables, 
transformName).getFieldNames();
+    } catch (Exception e) {
+      fieldNames = new String[] {};
+    }
+
+    // Set the field names on the combo widgets
+    widgets.setComboValues(DdlMeta.WIDGET_COLUMN_NAME_FIELD, fieldNames);
+    widgets.setComboValues(DdlMeta.WIDGET_COLUMN_TYPE_FIELD, fieldNames);
+    widgets.setComboValues(DdlMeta.WIDGET_COLUMN_LENGTH_FIELD, fieldNames);
+    widgets.setComboValues(DdlMeta.WIDGET_COLUMN_PRECISION_FIELD, fieldNames);
+  }
+}
diff --git 
a/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlMeta.java
 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlMeta.java
new file mode 100644
index 0000000000..b7f94c1492
--- /dev/null
+++ 
b/plugins/transforms/ddl/src/main/java/org/apache/hop/pipeline/transforms/ddl/DdlMeta.java
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+package org.apache.hop.pipeline.transforms.ddl;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hop.core.annotations.Transform;
+import org.apache.hop.core.database.DatabaseMeta;
+import org.apache.hop.core.exception.HopTransformException;
+import org.apache.hop.core.gui.plugin.GuiElementType;
+import org.apache.hop.core.gui.plugin.GuiPlugin;
+import org.apache.hop.core.gui.plugin.GuiWidgetElement;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.value.ValueMetaString;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.metadata.api.HopMetadataProperty;
+import org.apache.hop.metadata.api.HopMetadataPropertyType;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.TransformMeta;
+
+/** Meta data for the DDL transform. */
+@Setter
+@Getter
+@Transform(
+    id = "DDL",
+    name = "i18n::Ddl.Name",
+    description = "i18n::Ddl.Description",
+    image = "ddl.svg",
+    categoryDescription = 
"i18n:org.apache.hop.pipeline.transform:BaseTransform.Category.Utility",
+    keywords = "i18n::Ddl.keyword",
+    documentationUrl = "/pipeline/transforms/ddl.html")
+@GuiPlugin
+public class DdlMeta extends BaseTransformMeta<Ddl, DdlData> {
+  private static final Class<?> PKG = DdlMeta.class;
+  public static final String GUI_PLUGIN_ELEMENT_PARENT_ID = 
"DDL_DIALOG_OPTIONS";
+  public static final String WIDGET_COLUMN_NAME_FIELD = "COLUMN_NAME_FIELD";
+  public static final String WIDGET_COLUMN_TYPE_FIELD = 
"WIDGET_COLUMN_TYPE_FIELD";
+  public static final String WIDGET_COLUMN_LENGTH_FIELD = 
"WIDGET_COLUMN_LENGTH_FIELD";
+  public static final String WIDGET_COLUMN_PRECISION_FIELD = 
"WIDGET_COLUMN_PRECISION_FIELD";
+
+  @GuiWidgetElement(
+      order = "0100",
+      type = GuiElementType.METADATA,
+      metadata = DatabaseMeta.class,
+      toolTip = "i18n::DdlMeta.ConnectionName.Tooltip",
+      label = "i18n::DdlMeta.ConnectionName.Label",
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty(
+      key = "connection",
+      hopMetadataPropertyType = HopMetadataPropertyType.RDBMS_CONNECTION,
+      storeWithCode = true)
+  private String connectionName;
+
+  @GuiWidgetElement(
+      order = "0200",
+      type = GuiElementType.TEXT,
+      toolTip = "i18n::DdlMeta.SchemaName.Tooltip",
+      label = "i18n::DdlMeta.SchemaName.Label",
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty(
+      key = "schemaName",
+      hopMetadataPropertyType = HopMetadataPropertyType.RDBMS_SCHEMA)
+  private String schemaName;
+
+  @GuiWidgetElement(
+      order = "0300",
+      type = GuiElementType.TEXT,
+      toolTip = "i18n::DdlMeta.TableName.Tooltip",
+      label = "i18n::DdlMeta.TableName.Label",
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty(
+      key = "tableName",
+      hopMetadataPropertyType = HopMetadataPropertyType.RDBMS_TABLE)
+  private String tableName;
+
+  @GuiWidgetElement(
+      order = "0500",
+      type = GuiElementType.COMBO,
+      toolTip = "i18n::DdlMeta.FieldNameField.Tooltip",
+      label = "i18n::DdlMeta.FieldNameField.Label",
+      id = WIDGET_COLUMN_NAME_FIELD,
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty
+  private String fieldNameField;
+
+  @GuiWidgetElement(
+      order = "0600",
+      type = GuiElementType.COMBO,
+      toolTip = "i18n::DdlMeta.FieldTypeField.Tooltip",
+      label = "i18n::DdlMeta.FieldTypeField.Label",
+      id = WIDGET_COLUMN_TYPE_FIELD,
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty
+  private String fieldTypeField;
+
+  @GuiWidgetElement(
+      order = "0700",
+      type = GuiElementType.COMBO,
+      toolTip = "i18n::DdlMeta.FieldLengthField.Tooltip",
+      label = "i18n::DdlMeta.FieldLengthField.Label",
+      id = WIDGET_COLUMN_LENGTH_FIELD,
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty
+  private String fieldLengthField;
+
+  @GuiWidgetElement(
+      order = "0800",
+      type = GuiElementType.COMBO,
+      toolTip = "i18n::DdlMeta.FieldPrecisionField.Tooltip",
+      label = "i18n::DdlMeta.FieldPrecisionField.Label",
+      id = WIDGET_COLUMN_PRECISION_FIELD,
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty
+  private String fieldPrecisionField;
+
+  @GuiWidgetElement(
+      order = "0900",
+      type = GuiElementType.CHECKBOX,
+      toolTip = "i18n::DdlMeta.ExecutingDdl.Tooltip",
+      label = "i18n::DdlMeta.ExecutingDdl.Label",
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty
+  private boolean executingDdl;
+
+  @GuiWidgetElement(
+      order = "1000",
+      type = GuiElementType.TEXT,
+      toolTip = "i18n::DdlMeta.DdlOutputField.Tooltip",
+      label = "i18n::DdlMeta.DdlOutputField.Label",
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty
+  private String ddlOutputField;
+
+  @GuiWidgetElement(
+      order = "1100",
+      type = GuiElementType.CHECKBOX,
+      toolTip = "i18n::DdlMeta.DropTable.Tooltip",
+      label = "i18n::DdlMeta.DropTable.Label",
+      parentId = GUI_PLUGIN_ELEMENT_PARENT_ID)
+  @HopMetadataProperty
+  private boolean droppingTable;
+
+  public DdlMeta() {
+    fieldNameField = "FieldName";
+    fieldTypeField = "Type";
+    fieldLengthField = "Length";
+    fieldPrecisionField = "Precision";
+    executingDdl = true;
+    ddlOutputField = "ddl";
+  }
+
+  @Override
+  public void getFields(
+      IRowMeta inputRowMeta,
+      String name,
+      IRowMeta[] info,
+      TransformMeta nextTransform,
+      IVariables variables,
+      IHopMetadataProvider metadataProvider)
+      throws HopTransformException {
+    inputRowMeta.clear();
+    String outputFieldName = variables.resolve(ddlOutputField);
+    if (StringUtils.isNotEmpty(outputFieldName)) {
+      // Just one String containing the DDL in the output.
+      //
+      inputRowMeta.addValueMeta(new ValueMetaString(outputFieldName, 65535, 
-1));
+    }
+  }
+}
diff --git a/plugins/transforms/ddl/src/main/resources/ddl.svg 
b/plugins/transforms/ddl/src/main/resources/ddl.svg
new file mode 100644
index 0000000000..b192494193
--- /dev/null
+++ b/plugins/transforms/ddl/src/main/resources/ddl.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+        xmlns="http://www.w3.org/2000/svg";
+        version="1.1"
+        width="32"
+        height="32"
+        viewBox="0 0 32 32"
+>
+    <path
+            d="m 21.015401,26.793888 c 0.760542,0 1.744293,-0.578071 
1.740641,-1.291139 l 0.05194,-20.5721725 -12.107336,1e-7 c -1.275179,0 
-2.5150225,1.260161 -2.519691,2.496225 L 8.1153759,24.790051 6.503817,24.273095 
6.5693927,7.4268016 C 6.5777163,5.2875867 8.4190162,3.5533844 
10.700643,3.5533844 h 15.147913 c 2.281627,0 3.335614,1.523969 
3.321776,2.9492814 l -0.02151,2.2152751 c -1.559454,0.01197 -3.094514,0.038985 
-4.653491,0.00728 l -0.02381,16.7775271 c 0,2.139228 -1.849623,3.873 [...]
+            style="fill:#0e3a5a;fill-opacity:1;stroke-width:1.33341"/>
+    <path
+            d="m 20.644862,26.741992 c -0.631451,-0.07101 -1.244097,-0.30257 
-1.833462,-0.692986 -0.666885,-0.441767 -1.107458,-1.046378 -1.184236,-1.625159 
l -0.03315,-0.249913 H 12.865781 8.1375505 l 0.020407,-7.535715 c 
0.025345,-9.3594308 0.026691,-9.4417677 0.1608458,-9.84 0.256036,-0.7600325 
0.8905379,-1.4151027 1.6614613,-1.7153203 l 0.3164934,-0.1232506 
6.246184,-0.012928 6.246183,-0.012928 -0.02203,10.2272139 c -0.01211,5.624967 
-0.03272,10.315502 -0.04579,10.42341 -0.0511,0.421 [...]
+            
style="fill:#c9e8fb;fill-opacity:1;stroke:none;stroke-width:0.571991;stroke-linecap:round;stroke-linejoin:round"/>
+    <path
+            fill="#0e3a5a"
+            d="M 11.070253,13.437255 C 10.515488,13.291573 10.290082,13.21927 
10.18407,13.10704 c -0.04425,-0.04748 -0.06999,-0.106831 -0.08543,-0.208272 
-0.01646,-0.113311 -0.01545,-0.256834 -0.01545,-0.445684 0,-0.567626 
0.08749,-0.7241 0.934559,-0.7241 0.43846,0 0.942794,0.05935 1.364785,0.159712 l 
0.127627,0.03022 0.07822,-0.861152 -0.09365,-0.02481 c -0.442578,-0.123019 
-1.012782,-0.192085 -1.493442,-0.192085 -1.391544,0 -1.847501,0.516905 
-1.847501,1.587409 0,1.238848 0.195556,1.54 [...]
+            style="fill:#0e3a5a;fill-opacity:1;stroke-width:1.0539"/>
+    <path
+            fill="#0e3a5a"
+            d="m 15.613361,10.840855 c -1.455359,0 -2.074967,0.82338 
-2.074967,1.843164 v 2.405395 c 0,0.953957 0.542414,1.734173 1.811478,1.829135 
l 0.579467,1.383452 0.836781,-0.3982 -0.444636,-1.054316 c 0.95823,-0.221223 
1.366844,-0.936691 1.366844,-1.761151 v -2.405393 c 0,-1.019785 
-0.618579,-1.842086 -2.074967,-1.842086 z m 1.145554,4.230214 c 0,0.615107 
-0.336564,0.971221 -1.145554,0.971221 -0.80899,0 -1.145554,-0.356114 
-1.145554,-0.971221 v -2.370862 c 0,-0.615109 0.336564,-0.9 [...]
+            style="fill:#0e3a5a;fill-opacity:1;stroke-width:1.0539"/>
+    <polygon
+            style="fill:#0e3a5a;fill-opacity:1"
+            fill="#0e3a5a"
+            points="27.637,22.275 27.637,21.444 25.353,21.444 25.353,16.789 
24.45,16.789 24.45,22.275 "
+            transform="matrix(1.0292495,0,0,1.0791364,-6.445517,-7.1915146)"/>
+</svg>
diff --git 
a/plugins/transforms/ddl/src/main/resources/org/apache/hop/pipeline/transforms/ddl/messages/messages_en_US.properties
 
b/plugins/transforms/ddl/src/main/resources/org/apache/hop/pipeline/transforms/ddl/messages/messages_en_US.properties
new file mode 100644
index 0000000000..c24f8451b7
--- /dev/null
+++ 
b/plugins/transforms/ddl/src/main/resources/org/apache/hop/pipeline/transforms/ddl/messages/messages_en_US.properties
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+Ddl.Name=DDL
+Ddl.Description=Generate and execution DDL
+Ddl.keyword=DDL, DML, SQL, generate
+DdlMeta.ConnectionName.Label=Connection name
+DdlMeta.ConnectionName.Tooltip=The relational database connection used to 
generate and execute the DDL
+DdlMeta.SchemaName.Label=Schema name
+DdlMeta.SchemaName.Tooltip=The name of the schema for the target table
+DdlMeta.TableName.Label=Table name
+DdlMeta.TableName.Tooltip=The name of the table to create or alter
+DdlMeta.FieldNameField.Label=Column name field
+DdlMeta.FieldNameField.Tooltip=The name of the field in the input rows 
containing the name of the column
+DdlMeta.FieldTypeField.Label=Column type field
+DdlMeta.FieldTypeField.Tooltip=The name of the field in the input rows 
containing the Hop type for the column in the target table.
+DdlMeta.FieldLengthField.Label=Column length field
+DdlMeta.FieldLengthField.Tooltip=The name of the field in the input rows 
containing the length for the column in the target table.
+DdlMeta.FieldPrecisionField.Label=Column precision field
+DdlMeta.FieldPrecisionField.Tooltip=The name of the field in the input rows 
containing the precision for the column in the target table.
+DdlMeta.ExecutingDdl.Label=Execute DDL?
+DdlMeta.ExecutingDdl.Tooltip=Execute the generated DDL?
+DdlMeta.DdlOutputField.Label=DDL output field (optional)
+DdlMeta.DdlOutputField.Tooltip=Specify the name of the field to contain the 
generated SQL in the output.
+DdlMeta.DropTable.Label = Drop table before creation?
+DdlMeta.DropTable.Tooltip = Check this option if you want to always re-create 
the specified table. \
+  \The table is NOT dropped if the DDL is not executed. \!\!\! USE WITH 
CAUTION \!\!\!
diff --git a/plugins/transforms/ddl/src/main/resources/version.xml 
b/plugins/transforms/ddl/src/main/resources/version.xml
new file mode 100644
index 0000000000..6be576acae
--- /dev/null
+++ b/plugins/transforms/ddl/src/main/resources/version.xml
@@ -0,0 +1,20 @@
+<?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.
+  ~
+  -->
+
+<version>${project.version}</version>
\ No newline at end of file
diff --git a/plugins/transforms/pom.xml b/plugins/transforms/pom.xml
index 2d604730b8..68684d2591 100644
--- a/plugins/transforms/pom.xml
+++ b/plugins/transforms/pom.xml
@@ -55,6 +55,7 @@
         <module>datagrid</module>
         <module>dbimpact</module>
         <module>dbproc</module>
+        <module>ddl</module>
         <module>delay</module>
         <module>delete</module>
         <module>denormaliser</module>
diff --git 
a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java 
b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java
index 5eb69fb899..04ba0e5564 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java
@@ -506,7 +506,7 @@ public class GuiCompositeWidgets {
     } else {
       // Old layout: checkbox next to label
       layoutControlBetweenLabelAndRightControl(
-          props, lastControl, label, control, null, useNewLayout);
+          props, lastControl, label, control, null, useNewLayout, true);
     }
 
     return control;
@@ -666,6 +666,18 @@ public class GuiCompositeWidgets {
       Control control,
       Control rightControl,
       boolean useNewLayout) {
+    layoutControlBetweenLabelAndRightControl(
+        props, lastControl, label, control, rightControl, useNewLayout, false);
+  }
+
+  private void layoutControlBetweenLabelAndRightControl(
+      PropsUi props,
+      Control lastControl,
+      Label label,
+      Control control,
+      Control rightControl,
+      boolean useNewLayout,
+      boolean checkBox) {
     FormData fdControl = new FormData();
     if (label != null) {
       if (useNewLayout) {
@@ -687,7 +699,12 @@ public class GuiCompositeWidgets {
         }
         // Attach to lastControl to create proper vertical spacing between 
widgets
         if (lastControl != null) {
-          fdControl.top = new FormAttachment(lastControl, PropsUi.getMargin());
+          if (checkBox) {
+            // Center on the label
+            fdControl.top = new FormAttachment(label, 0, SWT.CENTER);
+          } else {
+            fdControl.top = new FormAttachment(lastControl, 
PropsUi.getMargin());
+          }
         } else {
           fdControl.top = new FormAttachment(0, PropsUi.getMargin());
         }
@@ -1088,4 +1105,13 @@ public class GuiCompositeWidgets {
       }
     }
   }
+
+  public void setComboValues(String widgetId, String[] fieldNames) {
+    Control control = widgetsMap.get(widgetId);
+    if (control instanceof Combo combo) {
+      combo.setItems(fieldNames);
+    } else if (control instanceof ComboVar comboVar) {
+      comboVar.setItems(fieldNames);
+    }
+  }
 }

Reply via email to