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);
+ }
+ }
}