From 3f3ea13c79d58518e2a85f13db51885b59937fda Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Tue, 24 Feb 2026 16:44:19 +0100 Subject: [PATCH 1/6] HCK-14977: Custom scripts - regular model --- forward_engineering/ddlProvider.js | 14 +- forward_engineering/helpers/general.js | 3 + localization/en.json | 7 +- .../container_level/containerLevelConfig.json | 134 +++++++++++++- .../entity_level/entityLevelConfig.json | 46 +++++ .../model_level/modelLevelConfig.json | 166 +++++++++++++++++- .../view_level/viewLevelConfig.json | 58 +++++- 7 files changed, 409 insertions(+), 19 deletions(-) diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index 073961d..4d31e79 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -20,7 +20,7 @@ module.exports = (baseProvider, options, app) => { const { assignTemplates, compareGroupItems } = app.require('@hackolade/ddl-fe-utils'); const { decorateDefault, decorateType, canBeNational, getSign, createGeneratedColumn, canHaveAutoIncrement } = require('./helpers/columnDefinitionHelper')(wrap); - const { getTableName, getTableOptions, getPartitions, getViewData, getCharacteristics, escapeQuotes } = + const { getTableName, getTableOptions, getPartitions, getViewData, getCharacteristics, escapeQuotes, wrapInTicks } = require('./helpers/general')(_, wrap); const { generateConstraintsString, foreignKeysToString, foreignActiveKeysToString, createKeyConstraint } = require('./helpers/constraintsHelper')({ @@ -36,7 +36,7 @@ module.exports = (baseProvider, options, app) => { const additionalOptions = getAdditionalOptions(options.additionalOptions); return dropStatementProxy({ commentIfDeactivated })(additionalOptions.applyDropStatements, { - createDatabase({ + createSchema({ databaseName, ifNotExist, collation, @@ -798,7 +798,7 @@ module.exports = (baseProvider, options, app) => { }; }, - hydrateDatabase(containerData, data) { + hydrateSchema(containerData, data) { return { databaseName: containerData.name, ifNotExist: containerData.ifNotExist, @@ -911,6 +911,14 @@ module.exports = (baseProvider, options, app) => { return statement; }, + commentStatement(statement) { + return commentIfDeactivated(statement, { isActivated: false }); + }, + + prepareName(name) { + return wrapInTicks(name); + }, + hydrateUdf(udf) { return { name: udf.name, diff --git a/forward_engineering/helpers/general.js b/forward_engineering/helpers/general.js index 057c5f2..aad7603 100644 --- a/forward_engineering/helpers/general.js +++ b/forward_engineering/helpers/general.js @@ -67,6 +67,8 @@ module.exports = (_, wrap) => { NDB: ['KEY_BLOCK_SIZE'], }; + const wrapInTicks = name => `\`${name}\``; + const getTableName = (tableName, schemaName) => { if (schemaName) { return `\`${schemaName}\`.\`${tableName}\``; @@ -328,5 +330,6 @@ module.exports = (_, wrap) => { getViewData, getCharacteristics, escapeQuotes, + wrapInTicks, }; }; diff --git a/localization/en.json b/localization/en.json index 1b61947..15f15e8 100644 --- a/localization/en.json +++ b/localization/en.json @@ -158,5 +158,10 @@ "MODAL_WINDOW___OPTIONS_DISPLAY_ERD_V_ENTITY_BOX_CONTENT": "Display of table box content", "MODAL_WINDOW___OPTIONS_DISPLAY_ERD_V_FIELDS": "Columns", "MODAL_WINDOW___OPTIONS_DISPLAY_REQUIRED_ATTRIBUTES": "Required columns", - "MODAL_WINDOW___OPTIONS_DISPLAY_NULLABLE_ATTRIBUTES": "Nullable columns" + "MODAL_WINDOW___OPTIONS_DISPLAY_NULLABLE_ATTRIBUTES": "Nullable columns", + + "CUSTOM_SCRIPT_CONTAINER_VAR_NAME": "Database name", + "CUSTOM_SCRIPT_CONTAINER_VAR": "databaseName", + "CUSTOM_SCRIPT_ENTITY_VAR_NAME": "Table name", + "CUSTOM_SCRIPT_ENTITY_VAR": "tableName" } diff --git a/properties_pane/container_level/containerLevelConfig.json b/properties_pane/container_level/containerLevelConfig.json index efbbd22..101b835 100644 --- a/properties_pane/container_level/containerLevelConfig.json +++ b/properties_pane/container_level/containerLevelConfig.json @@ -2,9 +2,9 @@ * Copyright © 2016-2017 by IntegrIT S.A. dba Hackolade. All rights reserved. * * The copyright to the computer software herein is the property of IntegrIT S.A. -* The software may be used and/or copied only with the written permission of -* IntegrIT S.A. or in accordance with the terms and conditions stipulated in -* the agreement/contract under which the software has been supplied. +* The software may be used and/or copied only with the written permission of +* IntegrIT S.A. or in accordance with the terms and conditions stipulated in +* the agreement/contract under which the software has been supplied. In order to define custom properties for any object's properties pane, you may copy/paste from the following, @@ -51,8 +51,8 @@ making sure that you maintain a proper JSON format. "propertyType": "checkbox" }, // “groupInput” can have the following states - 0 items, 1 item, and many items. -// “blockInput” has only 2 states - 0 items or 1 item. -// This gives us an easy way to represent it as an object and not as an array internally which is beneficial for processing +// “blockInput” has only 2 states - 0 items or 1 item. +// This gives us an easy way to represent it as an object and not as an array internally which is beneficial for processing // and forward-engineering in particular. { "propertyName": "Block", @@ -80,7 +80,7 @@ making sure that you maintain a proper JSON format. "propertyKeyword": "keyList", "propertyType": "fieldList", "template": "orderedList" - }, + }, { "propertyName": "List with attribute", "propertyKeyword": "keyListOrder", @@ -792,6 +792,128 @@ making sure that you maintain a proper JSON format. "defaultValue": "No", "options": ["No", "Yes"] }, + { + "propertyName": "Custom scripts", + "propertyType": "block", + "propertyKeyword": "customScripts", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Before CREATE DATABASE", + "propertyKeyword": "beforeCreateContainer", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After CREATE DATABASE", + "propertyKeyword": "afterCreateContainer", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "Before each CREATE TABLE", + "propertyKeyword": "beforeCreateEntity", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After each CREATE TABLE", + "propertyKeyword": "afterCreateEntity", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "Before each CREATE VIEW", + "propertyKeyword": "beforeCreateView", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After each CREATE VIEW", + "propertyKeyword": "afterCreateView", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", diff --git a/properties_pane/entity_level/entityLevelConfig.json b/properties_pane/entity_level/entityLevelConfig.json index cfc2d04..55bd5d2 100644 --- a/properties_pane/entity_level/entityLevelConfig.json +++ b/properties_pane/entity_level/entityLevelConfig.json @@ -1494,6 +1494,52 @@ making sure that you maintain a proper JSON format. } } }, + { + "propertyName": "Custom scripts", + "propertyType": "block", + "propertyKeyword": "customScripts", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Before CREATE TABLE", + "propertyKeyword": "beforeCreateEntity", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After CREATE TABLE", + "propertyKeyword": "afterCreateEntity", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", diff --git a/properties_pane/model_level/modelLevelConfig.json b/properties_pane/model_level/modelLevelConfig.json index d5efc6c..12e8599 100644 --- a/properties_pane/model_level/modelLevelConfig.json +++ b/properties_pane/model_level/modelLevelConfig.json @@ -2,9 +2,9 @@ * Copyright © 2016-2017 by IntegrIT S.A. dba Hackolade. All rights reserved. * * The copyright to the computer software herein is the property of IntegrIT S.A. -* The software may be used and/or copied only with the written permission of -* IntegrIT S.A. or in accordance with the terms and conditions stipulated in -* the agreement/contract under which the software has been supplied. +* The software may be used and/or copied only with the written permission of +* IntegrIT S.A. or in accordance with the terms and conditions stipulated in +* the agreement/contract under which the software has been supplied. In order to define custom properties for any object's properties pane, you may copy/paste from the following, making sure that you maintain a proper JSON format. @@ -74,6 +74,166 @@ making sure that you maintain a proper JSON format. "options": ["v5.x", "v8.x", "v9.x"], "disabledOption": false }, + { + "propertyName": "Custom scripts", + "propertyType": "block", + "propertyKeyword": "customScripts", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Header script", + "propertyKeyword": "headerScript", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "Footer script", + "propertyKeyword": "footerScript", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "Before each CREATE DATABASE", + "propertyKeyword": "beforeCreateContainer", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After each CREATE DATABASE", + "propertyKeyword": "afterCreateContainer", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "Before each CREATE TABLE", + "propertyKeyword": "beforeCreateEntity", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After each CREATE TABLE", + "propertyKeyword": "afterCreateEntity", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "Before each CREATE VIEW", + "propertyKeyword": "beforeCreateView", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After each CREATE VIEW", + "propertyKeyword": "afterCreateView", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + } + ] + }, { "propertyName": "Comments", "propertyKeyword": "comments", diff --git a/properties_pane/view_level/viewLevelConfig.json b/properties_pane/view_level/viewLevelConfig.json index 01f486a..81d17e5 100644 --- a/properties_pane/view_level/viewLevelConfig.json +++ b/properties_pane/view_level/viewLevelConfig.json @@ -2,9 +2,9 @@ * Copyright © 2016-2017 by IntegrIT S.A. dba Hackolade. All rights reserved. * * The copyright to the computer software herein is the property of IntegrIT S.A. -* The software may be used and/or copied only with the written permission of -* IntegrIT S.A. or in accordance with the terms and conditions stipulated in -* the agreement/contract under which the software has been supplied. +* The software may be used and/or copied only with the written permission of +* IntegrIT S.A. or in accordance with the terms and conditions stipulated in +* the agreement/contract under which the software has been supplied. In order to define custom properties for any object's properties pane, you may copy/paste from the following, making sure that you maintain a proper JSON format. @@ -69,8 +69,8 @@ making sure that you maintain a proper JSON format. ] }, // “groupInput” can have the following states - 0 items, 1 item, and many items. -// “blockInput” has only 2 states - 0 items or 1 item. -// This gives us an easy way to represent it as an object and not as an array internally which is beneficial for processing +// “blockInput” has only 2 states - 0 items or 1 item. +// This gives us an easy way to represent it as an object and not as an array internally which is beneficial for processing // and forward-engineering in particular. { "propertyName": "Block", @@ -98,7 +98,7 @@ making sure that you maintain a proper JSON format. "propertyKeyword": "keyList", "propertyType": "fieldList", "template": "orderedList" - }, + }, { "propertyName": "List with attribute", "propertyKeyword": "keyListOrder", @@ -174,6 +174,52 @@ making sure that you maintain a proper JSON format. ] } }, + { + "propertyName": "Custom scripts", + "propertyType": "block", + "propertyKeyword": "customScripts", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Before CREATE VIEW", + "propertyKeyword": "beforeCreateView", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + }, + { + "propertyName": "After CREATE VIEW", + "propertyKeyword": "afterCreateView", + "propertyType": "block", + "propertyTooltip": "", + "structure": [ + { + "propertyName": "Script", + "propertyKeyword": "script", + "propertyType": "details", + "markdown": false, + "template": "codeEditor", + "templateOptions": { + "editorDialect": "sql", + "customScriptVariables": true + } + } + ] + } + ] + }, { "propertyName": "Remarks", "propertyKeyword": "comments", From 4b264357a54c264e95111df8f12e435c95ddd5c6 Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Wed, 25 Feb 2026 08:19:22 +0100 Subject: [PATCH 2/6] fix --- forward_engineering/ddlProvider.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index 4d31e79..2a43d0a 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -812,6 +812,11 @@ module.exports = (baseProvider, options, app) => { }; }, + // Keep it because it was used to hydrate `dbData` for the API + hydrateDatabase(containerData, data) { + return this.hydrateSchema(containerData, data).bind(this); + }, + hydrateTableSpace(tableSpace) { return { name: tableSpace.name, From 743eb0ede0aa0dc22a7e6859cc03b32d5e8c49e3 Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Wed, 25 Feb 2026 10:23:00 +0100 Subject: [PATCH 3/6] fix --- forward_engineering/ddlProvider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index 2a43d0a..c439061 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -814,7 +814,7 @@ module.exports = (baseProvider, options, app) => { // Keep it because it was used to hydrate `dbData` for the API hydrateDatabase(containerData, data) { - return this.hydrateSchema(containerData, data).bind(this); + return this.hydrateSchema(containerData, data); }, hydrateTableSpace(tableSpace) { From b5444523cbf6466a1bd5ff863cf441b5a78dc6b3 Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Wed, 25 Feb 2026 11:31:34 +0100 Subject: [PATCH 4/6] fix --- forward_engineering/ddlProvider.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index c439061..a4b6a48 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -71,11 +71,11 @@ module.exports = (baseProvider, options, app) => { ); }, - dropDatabase(dropDbData) { + dropSchema(dropDbData) { return assignTemplates(templates.dropDatabase, dropDbData); }, - alterDatabase(alterDbData) { + alterSchema(alterDbData) { const alterStatements = []; const databaseName = alterDbData.name; @@ -961,13 +961,13 @@ module.exports = (baseProvider, options, app) => { }; }, - hydrateDropDatabase(containerData) { + hydrateDropSchema(containerData) { return { name: containerData[0]?.name || '', }; }, - hydrateAlterDatabase({ containerData, compModeData }) { + hydrateAlterSchema({ containerData, compModeData }) { const data = containerData[0] || {}; const isCharacterSetModified = compModeData.new.characterSet !== compModeData.old.characterSet; const isCollationModified = compModeData.new.collation !== compModeData.old.collation; From b593d3856a81350271d79feb80c9c5aebaf007bc Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Wed, 25 Feb 2026 12:16:55 +0100 Subject: [PATCH 5/6] backward compatibility --- forward_engineering/ddlProvider.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index a4b6a48..670e0ac 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -1013,5 +1013,19 @@ module.exports = (baseProvider, options, app) => { : null, }; }, + + // Keep for backward compatibility + dropDatabase(data) { + return this.dropSchema(data); + }, + alterDatabase(data) { + return this.alterSchema(data); + }, + hydrateDropDatabase(data) { + return this.hydrateDropSchema(data); + }, + hydrateAlterDatabase(data) { + return this.hydrateAlterSchema(data); + }, }); }; From e0cf55dad91e81eaf42551a8718b6650affadb48 Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Wed, 25 Feb 2026 12:19:44 +0100 Subject: [PATCH 6/6] remove --- forward_engineering/ddlProvider.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index 670e0ac..a4b6a48 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -1013,19 +1013,5 @@ module.exports = (baseProvider, options, app) => { : null, }; }, - - // Keep for backward compatibility - dropDatabase(data) { - return this.dropSchema(data); - }, - alterDatabase(data) { - return this.alterSchema(data); - }, - hydrateDropDatabase(data) { - return this.hydrateDropSchema(data); - }, - hydrateAlterDatabase(data) { - return this.hydrateAlterSchema(data); - }, }); };