Die Erfassung der Transformationen erfolgt in Arbeitsblättern (Sheets). Diese werden in Verzeichnissen organisiert.
Eine einzelne Transformation benötigt Quellen und Ziele und verwendet ein bestimmtes Modul.
Neue Ordner legt man im Explorer unter Transformations über das Kontextmenü an (New Folder). Siehe Der Navigationsbaum.
In Arbeitsblättern werden Transformationen zusammengefasst. Arbeitsblätter sind die kleinste Deploymenteinheit.
Ein Arbeitsblatt kann beliebig viele Elemente enthalten. Es empfiehlt sich, Blätter schlank und themengranular zu halten: gleichzeitiges Bearbeiten durch mehrere Entwickler ist nicht möglich.
Arbeitsblätter erscheinen rechts im Editor als Reiter. Die Beschriftung enthält den Namen der Umgebung, den Namen des Blatts und ein vorangestelltes *, wenn das Blatt im Bearbeitungsmodus ist. Es können mehrere Reiter offen sein, aber nur eines im Bearbeitungsmodus.
Ein Doppelklick auf den Reiter verbirgt den Explorer und maximiert den Arbeitsbereich. Ein erneuter Doppelklick blendet den Explorer wieder ein.

Kontextmenü des Reiters:
Unterhalb des Explorers erscheint die Dokumentation des Arbeitsblatts. Sie lässt sich dort oder in einem größeren Dialog bearbeiten (Schaltfläche in der Documentation-Titelzeile). Dazu muss das Blatt im Bearbeitungsmodus sein. Die Dokumentation wird in Markdown geschrieben; siehe Markdown-Dokumentation.

Im Bearbeitungsmodus platziert man Transformationen und Objekte per Drag & Drop. Der Datenfluss verläuft von oben nach unten.
Verknüpfungen zieht man mit gedrückter linker Maustaste von einem Anschlusspunkt zum nächsten; bei grüner Kennzeichnung rasten sie ein. Quellen führen von der Unterseite des Objekts zur Oberseite der Transformation, Ziele von der Unterseite der Transformation zur Oberseite des Zielobjekts. Remove Connection im Kontextmenü löst eine Verknüpfung.
Einzelne Transformationen startet man über Run im Kontextmenü. Markierte Elemente lassen sich kopieren (Strg+C), einfügen (Strg+V) und löschen (Entf), auch zwischen Arbeitsblättern.
Sheet Validation prüft, ob Modell und verwendete Objekte konsistent sind. Blätter mit Fehlern dürfen nicht deployed werden: für die Ablaufsteuerung müssen alle in der Transformation verwendeten Objekte als Quelle oder Ziel auf dem Blatt stehen.

Export SQL erzeugt ein Skript mit den Metadaten des Blatts. Das File kann in einer anderen Transformationsdatenbank eingespielt oder in der Versionsverwaltung abgelegt werden. Siehe Deployment.
Ein Objekt ist Quelle oder Ziel einer Transformation, zum Beispiel eine Tabelle, ein Webservice, eine Datei oder eine Mailingliste. Die meisten Module erwarten mindestens eine Quelle und ein Ziel.
Ein Objekt definiert sich aus der Objektart und zusätzlichen Eigenschaften wie Connection, Name, Schema oder Pfad.
Auf Objektebene legt man fest, ob die Verbindung zu anderen Sheets als Abhängigkeit gilt. Im Feld Dependency steht Wait für „Auf Transformationen aus anderen Sheets warten“ und Ignore für „Nicht warten“. Innerhalb desselben Blatts gilt diese Einstellung nicht; siehe Abhängigkeiten.
Ein Objekt entsteht per Drag & Drop des Objekticons auf das Raster. Doppelklick öffnet den Edit Object Dialog.
Felder für Table or View:

Refresh Objects liest die für datasqill sichtbaren Objekte aus den konfigurierten Schemata und schreibt sie in den Objektkatalog. Das ist initial nötig und nach jeder transformationsrelevanten Änderung an den Datenbankobjekten.
Show Table Create Script formatiert die erzeugten Skripte in einer Textbox (Kopieren per Strg+C oder Kontextmenü):

Welcher Code dabei generiert wird erfolgt an Hand eines freemarker Templates. Dieses Template ist in der Tabelle vv_sqts_config_global definiert:
| Typ | config_key1 | config_key2 | config_key3 | config_key4 |
|---|---|---|---|---|
| Export | VARIABLE | Template | TABLE_SCRIPT | EXPORT |
Es gibt jeweils zwei Sets von Variablen. Der erste Set bietet die unten angegebenen Variablen. Ein weiterer Set ist für die Basistabelle, falls es sich um ein Objekt handelt, welches auf genau ein anderes Objekt basiert (Für Views, die genau eine Tabelle als Quelle haben). Bei diesem Set haben alle Variablen den Prefix BASE_. Gibt es exakt ein Objekt auf den das Objekt basiert, dann wird dieser Set mit den Informationen der Basistabelle befüllt. Ansonsten entspricht dieser Set dem ersten Set.
Es werden im Freemarker folgende Variablen zur Verfügung gestellt:
| Variable | Datentyp | Bedeutung |
|---|---|---|
| DATABASE_ID | Number | Die Connection des Objekts |
| SCHEMA_NAME | String | Der Name des Schemas |
| OBJECT_NAME | String | Der Name des Objekts |
| OBJECT_TYPE | String | Der Objekttyp. Dereit entweder TABLE oder VIEW |
| PK_NAME | String | Der Name des Primärschlüssels |
| OBJECT_COMMENT | String | Der Objektkommentar |
| SCHEMA_NAME_LOWER | String | Derzeit nicht unterstützt |
| OBJECT_NAME_LOWER | String | Derzeit nicht unterstützt |
| columns | Liste | Liste der Spalten des Objekts |
Hierbei hat jedes Objekt eine Liste von Namen und deren Werten. Folgende Namen sind verfügbar:
| Name | Datentyp | Bedeutung |
|---|---|---|
| DATABASE_ID | Number | Die Connection des Objekts |
| SCHEMA_NAME | String | Der Name des Schemas |
| OBJECT_NAME | String | Der Name des Objekts |
| COLUMN_NAME | String | Der Name der Spalte |
| COLUMN_POSITION | Number | Position der Spalte innerhalb des Objekts |
| COLUMN_TYPE | Number | Der Datentype |
| COLUMN_PK_POSITION | Number | Wenn nicht null Position im Primary Key |
| COLUMN_COMMENT | String | Der Spaltenkommentar |
| COLUMN_IS_NULLABLE | CHAR | "Y" Nulls sind erlaubt, "N" nicht |
| COLUMN_SOURCE_TYPE | String | Der Datentyp, wie im Quellsystem angegeben |
| SCHEMA_NAME_LOWER | String | Derzeit nicht unterstützt |
| OBJECT_NAME_LOWER | String | Derzeit nicht unterstützt |
| COLUMN_NAME_LOWER | String | Derzeit nicht unterstützt |
Ein Beispiel, um den vollen Namen des Objekts name für die weitere Verwendung bereitzustellen:
[#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]
Analog für das Basisobjekt:
[#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]
Versionierte Tabellen erkennen:
[#-- 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]
Die Spalten erkennen, die nicht zur Historisierung / Versionierung gehören
[#-- 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]
Aus den Primary Key Spalten, die Spalten herausfltern, die nicht Teil der versionierung sind
[#-- 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")]
Eine Funktion, um sich die Spaltentypen für die Zielumgebung aufzubereiten
[#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]
Die Ausgabe der versionierten Tabelle für nicht SQDV-versionierten Tabellen
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]
);
Eine Transformation enthält den SQL-Code und wird zur Laufzeit durch das gewählte Modul ergänzt. Typische Module sind Insert from Select oder Upsert/Merge.
Der Entwickler erfasst zum Beispiel:
SELECT SYSDATE AS zeitpunkt_der_reporterstellung
, TO_CHAR(TRUNC(order_date,'MM'), 'YYYY.MM') AS monat_der_bestellungen
, COUNT(*) AS anzahl_der_bestellungen
, SUM(order_total) AS umsatzsumme_der_bestellungen
, ROUND(AVG(order_total),1) AS average_umsatz_pro_bestellung
FROM oe.orders
GROUP BY TRUNC(order_date,'MM')
ORDER BY monat_der_bestellungen;
Insert from Select erzeugt daraus zur Laufzeit:
INSERT INTO oe.order_report(
zeitpunkt_der_reporterstellung
, monat_der_bestellungen
, anzahl_der_bestellungen
, umsatzsumme_der_bestellungen
, average_umsatz_pro_bestellung)
SELECT SYSDATE AS zeitpunkt_der_reporterstellung
, TO_CHAR(TRUNC(order_date,'MM'), 'YYYY.MM') AS monat_der_bestellungen
, COUNT(*) AS anzahl_der_bestellungen
, SUM(order_total) AS umsatzsumme_der_bestellungen
, ROUND(AVG(order_total),1) AS average_umsatz_pro_bestellung
FROM oe.orders
GROUP BY TRUNC(order_date,'MM')
ORDER BY monat_der_bestellungen
Eine Transformation entsteht per Drag & Drop des Transformationsicons (Zahnrad) auf das Raster. Oft legt man gleich die Kette Quellobjekt–Transformation–Zielobjekt an. Doppelklick öffnet den Edit Action Dialog: Parameter, Basisabfrage und Validierung.
Links oben:

Weitere Parameter kommen vom gewählten Modul und sind über Tooltips beschrieben. Im Bereich Documentation hinterlegt man analog zum Arbeitsblatt eine Beschreibung in Markdown; siehe Markdown-Dokumentation. Doppelklick auf die Reiter Action oder Validate blendet Parameter- und Dokumentationsbereich aus bzw. ein.
Im Reiter Action steht die Basisabfrage. Der Editor bietet Syntaxhervorhebung und Reformat SQL im Kontextmenü. Es gelten die SQL-Konstrukte der Transformationsdatenbank. Verwendete Objekte müssen schemaqualifiziert angegeben werden.
Im Feld Type stehen die in der Umgebung registrierten Module. Die Basisabfrage wird zur Laufzeit um die Modulfunktionalität ergänzt, zum Beispiel um den Insert-Anteil bei Insert from Select.
Damit ein Modul als Type erscheint, muss es implementiert, installiert und in der Transformationsdatenbank registriert sein. Die Parameter im Edit-Action-Dialog und ihre Tooltips stammen aus der Moduldefinition.
Der Reiter Validate übergibt die Basisabfrage an die Validate-Funktion des Moduls:

Resulting Action to be performed zeigt das SQL, das der Lauf später ausführt. Dieses Statement wird nur zur Laufzeit gebaut und nicht persistiert.
Result of Validation vergleicht die in der Query verwendeten Objekte mit den auf dem Blatt modellierten Quellen und Zielen. Alle in der Query verwendeten Objekte sollten im Modell stehen, sonst greift die Ablaufsteuerung nicht.