Transformations are captured in worksheets (Sheets). These are organized in directories.
A single transformation requires sources and targets and uses a specific module.
Transformations are grouped in worksheets.
Worksheets are the smallest deployment unit.
An object is defined by the object type and additional properties such as Connection, name, schema, path, etc.
Furthermore, at the object level, you can determine whether the connection to other sheets should be considered as a dependency or not.
This is configured in the GUI in the Dependency field. In this field, you set Wait = "Wait for transformations from other sheets" or Ignore = "Do not wait".
Additionally, you can refresh the metadata from the specified connection in the object editor.
Furthermore, for database objects, you can have an (export) script generated that describes the object. This script can be used to generate the DDL for creating the object. You can execute excerpts from the script directly on the target database, or use them for artifact definitions.
The code generated is based on a Freemarker template. This template is defined in the table vv_sqts_config_global:
| Type | config_key1 | config_key2 | config_key3 | config_key4 |
|---|---|---|---|---|
| Export | VARIABLE | Template | TABLE_SCRIPT | EXPORT |
There are two sets of variables. The first set provides the variables listed below. Another set is for the base table if it is an object that is based on exactly one other object (for views that have exactly one table as source). In this set, all variables have the prefix BASE_. If there is exactly one object that the object is based on, this set is filled with the information of the base table. Otherwise, this set corresponds to the first set.
The following variables are made available in Freemarker:
| Variable | Data Type | Meaning |
|---|---|---|
| DATABASE_ID | Number | The connection of the object |
| SCHEMA_NAME | String | The schema name |
| OBJECT_NAME | String | The object name |
| OBJECT_TYPE | String | The object type. Currently either TABLE or VIEW |
| PK_NAME | String | The primary key name |
| OBJECT_COMMENT | String | The object comment |
| SCHEMA_NAME_LOWER | String | Currently not supported |
| OBJECT_NAME_LOWER | String | Currently not supported |
| columns | List | List of columns of the object |
Each object has a list of names and their values. The following names are available:
| Name | Data Type | Meaning |
|---|---|---|
| DATABASE_ID | Number | The connection of the object |
| SCHEMA_NAME | String | The schema name |
| OBJECT_NAME | String | The object name |
| COLUMN_NAME | String | The column name |
| COLUMN_POSITION | Number | Position of the column within the object |
| COLUMN_TYPE | Number | The data type |
| COLUMN_PK_POSITION | Number | If not null, position in primary key |
| COLUMN_COMMENT | String | The column comment |
| COLUMN_IS_NULLABLE | CHAR | "Y" nulls allowed, "N" not |
| COLUMN_SOURCE_TYPE | String | The data type as specified in the source system |
| SCHEMA_NAME_LOWER | String | Currently not supported |
| OBJECT_NAME_LOWER | String | Currently not supported |
| COLUMN_NAME_LOWER | String | Currently not supported |
An example to provide the full name of the object name for further use:
[#if SCHEMA_NAME?has_content]
[#assign schema=SCHEMA_NAME?lower_case + "."]
[#else]
[#assign schema=""]
[/#if]
[#assign object=OBJECT_NAME?lower_case]
[#assign name=schema+object]
Analogous for the base object:
[#if BASE_SCHEMA_NAME?has_content]
[#assign base_schema=BASE_SCHEMA_NAME?lower_case + "."]
[#else]
[#assign base_schema=""]
[/#if]
[#assign base_object=BASE_OBJECT_NAME?lower_case]
[#assign base_name=base_schema + base_object]
Recognize versioned tables:
[#-- base_tv and base_nv are placeholder for the versioned / non versioned table name with schema --]
[#assign base_tv=base_schema +base_object]
[#assign base_nv=base_schema +base_object]
[#if base_name?starts_with("tv_")]
[#assign base_nv=base_schema + base_object[3..]]
[#else]
[#assign base_tv=base_schema + "tv_" + base_object]
[/#if]
Recognize columns that do not belong to historization / versioning
[#-- list of historize columns --]
[#assign hist_cols = ["upd_by", "ins_by", "is_latest_period","last_changed_dt", "valid_from_dt", "invalid_from_dt", "is_current_and_active", "is_deleted"]]
[#-- generate the list data_cols with all columns which are not sqdv columns --]
[#assign data_cols = []]
[#list baseColumns as col]
[#if !(col["COLUMN_NAME"]?lower_case?starts_with("sqdv_")) && !hist_cols?seq_contains(col["COLUMN_NAME"]?lower_case)]
[#assign data_cols += [col] ]
[/#if]
[/#list]
Filter out columns from primary key columns that are not part of versioning
[#-- generate the list pkCols with all primary key columns which are not sqdv columns --]
[#assign pkCols = []]
[#list baseColumns as col]
[#if col["COLUMN_PK_POSITION"]?? && !(col["COLUMN_NAME"]?lower_case?starts_with("sqdv_")) && !hist_cols?seq_contains(col["COLUMN_NAME"]?lower_case)]
[#assign pkCols += [col] ]
[/#if]
[/#list]
[#assign pkCols = pkCols?sort_by("COLUMN_PK_POSITION")]
A function to prepare column types for the target environment
[#function toTargetType columType]
[#local colType = columType?upper_case]
[#local pos = colType?index_of("(")]
[#if pos != -1]
[#local colTypeFirst = colType?substring(0, pos)?trim]
[#local colTypeLast = colType?substring(pos)?trim]
[#local colTypeLast = colTypeLast?replace(" CHAR", "")?replace(" BYTE", "")]
[#else]
[#local colTypeFirst = colType?trim]
[#local colTypeLast = ""]
[/#if]
[#if ["BIGINT", "INTEGER", "SMALLINT", "TINYINT"]?seq_contains(colTypeFirst)]
[#local colTypeFirst = "INT"]
[#elseif ["TIMESTAMP", "TIMESTAMP WITHOUT TIME ZONE"]?seq_contains(colTypeFirst)]
[#local colTypeFirst = "DATETIME"]
[#elseif ["VARCHAR2", "CHARACTER VARYING"]?seq_contains(colTypeFirst)]
[#local colTypeFirst = "VARCHAR"]
[#elseif ["CHARACTER"]?seq_contains(colTypeFirst)]
[#local colTypeFirst = "CHAR"]
[#elseif ["NUMBER", "NUMERIC"]?seq_contains(colTypeFirst) && colTypeLast=""]
[#local colTypeFirst = "DECIMAL(15,2)"]
[#elseif ["NUMBER", "NUMERIC"]?seq_contains(colTypeFirst)]
[#local colTypeFirst = "DECIMAL"]
[#elseif ["CLOB", "TEXT"]?seq_contains(colTypeFirst)]
[#local colTypeFirst = "VARCHAR(MAX)"]
[#local colTypeLast = ""]
[/#if]
[#return colTypeFirst + colTypeLast]
[/#function]
Output of the versioned table for non-SQDV versioned tables
DROP TABLE IF EXISTS ${base_tv};
-- Versioned table with data types of target database
CREATE TABLE ${base_tv} (
[#list data_cols as col]${col["COLUMN_NAME"]?lower_case} ${toTargetType(col["COLUMN_TYPE"])}[#if col["COLUMN_IS_NULLABLE"] == 'N'] NOT NULL[/#if][#sep]
, [/#list]
, is_latest_period CHAR(1) NOT NULL
, is_current_and_active CHAR(1) NOT NULL
, is_deleted CHAR(1) NOT NULL
, last_changed_dt DATETIME NOT NULL
, valid_from_dt DATETIME NOT NULL
, invalid_from_dt DATETIME NOT NULL [#if pkCols?size > 0]
, PRIMARY KEY([#list pkCols as pk]${pk["COLUMN_NAME"]?lower_case}, [/#list]invalid_from_dt)[/#if]
);