From 381327ad1374b3558b1846d1a772ae1ce7222a79 Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Tue, 6 Jan 2026 17:20:11 +0100 Subject: [PATCH 01/11] chore: base code script generation options --- api/fe.js | 5 + .../alterScript/alterScriptBuilder.js | 50 +++ .../alterScript/alterScriptFromDeltaHelper.js | 99 +++++ .../alterScriptHelpers/alterEntityHelper.js | 41 ++ .../alterScriptHelpers/alterViewHelper.js | 13 + forward_engineering/api.js | 6 +- .../api/generateContainerScript.js | 16 + forward_engineering/config.json | 396 ++++++++++++++++++ 8 files changed, 623 insertions(+), 3 deletions(-) create mode 100644 api/fe.js create mode 100644 forward_engineering/alterScript/alterScriptBuilder.js create mode 100644 forward_engineering/alterScript/alterScriptFromDeltaHelper.js create mode 100644 forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js create mode 100644 forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js create mode 100644 forward_engineering/api/generateContainerScript.js diff --git a/api/fe.js b/api/fe.js new file mode 100644 index 0000000..9529b66 --- /dev/null +++ b/api/fe.js @@ -0,0 +1,5 @@ +const { generateContainerScript } = require('../forward_engineering/api/generateContainerScript'); + +module.exports = { + generateContainerScript, +}; diff --git a/forward_engineering/alterScript/alterScriptBuilder.js b/forward_engineering/alterScript/alterScriptBuilder.js new file mode 100644 index 0000000..61e9bc5 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptBuilder.js @@ -0,0 +1,50 @@ +const { commentIfDeactivated } = require('../utils/general'); +const { getAlterScriptDtos } = require('./alterScriptFromDeltaHelper'); + +const joinAlterScriptDtosIntoScript = (dtos, shouldApplyDropStatements) => { + return dtos + .flatMap(dto => { + if (dto.isActivated === false) { + return dto.scripts.map(scriptDto => + commentIfDeactivated(scriptDto.script, { + isActivated: false, + isPartOfLine: false, + }), + ); + } + if (!shouldApplyDropStatements) { + return dto.scripts.map(scriptDto => + commentIfDeactivated(scriptDto.script, { + isActivated: !scriptDto.isDropScript, + isPartOfLine: false, + }), + ); + } + return dto.scripts.map(scriptDto => scriptDto.script); + }) + .map(scriptLine => scriptLine?.trim()) + .filter(Boolean) + .join('\n\n'); +}; + +const mapCoreDataForContainerLevelScripts = data => { + return { + ...data, + jsonSchema: data.collections[0], + internalDefinitions: Object.values(data.internalDefinitions)[0], + }; +}; + +const buildContainerLevelAlterScript = (data, app) => { + const preparedData = mapCoreDataForContainerLevelScripts(data); + const alterScriptDtos = []; + const shouldApplyDropStatements = preparedData.options?.additionalOptions?.some( + option => option.id === 'applyDropStatements' && option.value, + ); + + return joinAlterScriptDtosIntoScript(alterScriptDtos, shouldApplyDropStatements); +}; + +module.exports = { + buildContainerLevelAlterScript, +}; diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js new file mode 100644 index 0000000..21a6af1 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -0,0 +1,99 @@ +const { + getModifyCollectionScriptDtos, + getModifyCollectionKeysScriptDtos, + getModifyColumnScriptDtos, +} = require('./alterScriptHelpers/alterEntityHelper'); +const { getModifyViewScriptDtos } = require('./alterScriptHelpers/alterViewHelper'); + +const getItems = data => data?.items || []; + +const getAlterCollectionScriptDtos = ({ + collection, + app, + dbVersion, + modelDefinitions, + internalDefinitions, + externalDefinitions, +}) => { + const modifyScriptsData = getItems(collection.properties?.entities?.properties?.modified) + .filter(Boolean) + .map(item => Object.values(item.properties)[0]); + + const modifyCollectionScriptDtos = modifyScriptsData.flatMap(getModifyCollectionScriptDtos({ dbVersion })); + const modifyCollectionKeysScriptDtos = modifyScriptsData.flatMap(getModifyCollectionKeysScriptDtos({ dbVersion })); + + const modifyColumnScriptDtos = modifyScriptsData.flatMap( + getModifyColumnScriptDtos({ app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions }), + ); + + return [...modifyCollectionScriptDtos, ...modifyColumnScriptDtos, ...modifyCollectionKeysScriptDtos].filter( + Boolean, + ); +}; + +const getAlterViewScriptDtos = (collection, app) => { + const modifyViewScriptDtos = getItems(collection.properties?.views?.properties?.modified) + .filter(Boolean) + .map(viewWrapper => Object.values(viewWrapper.properties)[0]) + .map(view => ({ ...view, ...(view.role || {}) })) + .flatMap(view => getModifyViewScriptDtos(view)); + + return [...modifyViewScriptDtos].filter(Boolean); +}; + +const prettifyAlterScriptDto = dto => { + if (!dto) { + return undefined; + } + /** + * @type {Array} + * */ + const nonEmptyScriptModificationDtos = dto.scripts + .map(scriptDto => ({ + ...scriptDto, + script: (scriptDto.script || '').trim(), + })) + .filter(scriptDto => Boolean(scriptDto.script)); + if (!nonEmptyScriptModificationDtos.length) { + return undefined; + } + return { + ...dto, + scripts: nonEmptyScriptModificationDtos, + }; +}; + +const getAlterScriptDtos = (data, app) => { + const collection = JSON.parse(data.jsonSchema); + + if (!collection) { + throw new Error( + '"comparisonModelCollection" is not found. Alter script can be generated only from Delta model', + ); + } + + const modelDefinitions = JSON.parse(data.modelDefinitions); + const internalDefinitions = JSON.parse(data.internalDefinitions); + const externalDefinitions = JSON.parse(data.externalDefinitions); + const dbVersion = data.modelData[0]?.dbVersion; + + const collectionsScriptDtos = getAlterCollectionScriptDtos({ + collection, + app, + dbVersion, + modelDefinitions, + internalDefinitions, + externalDefinitions, + }); + + const viewScriptDtos = getAlterViewScriptDtos({ collection, app }); + + return [...collectionsScriptDtos, ...viewScriptDtos] + .filter(Boolean) + .map(dto => dto && prettifyAlterScriptDto(dto)) + .filter(Boolean); +}; + +module.exports = { + getAlterScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js new file mode 100644 index 0000000..1f638d6 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -0,0 +1,41 @@ +const getModifyCollectionScriptDtos = + ({}) => + collection => { + // const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(...); + // const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(...); + return [ + // ...modifyCheckConstraintScriptDtos, + // ...modifyCommentScriptDtos, + ].filter(Boolean); + }; + +const getModifyCollectionKeysScriptDtos = + ({}) => + collection => { + // const modifyPkConstraintDtos = getModifyPkConstraintScriptDtos(...); + // const modifyUkConstraintDtos = getModifyUkConstraintsScriptDtos(...); + return [ + // ...modifyPkConstraintDtos, + // ...modifyUniqueKeyConstraintDtos, + ].filter(Boolean); + }; + +const getModifyColumnScriptDtos = + ({}) => + collection => { + // const modifyNotNullScriptDtos = getModifyNonNullColumnScriptDtos(...); + // const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(...); + // const modifyDefaultColumnValueScriptDtos = getModifiedDefaultColumnValueScriptDtos(...); + + return [ + // ...modifyNotNullScriptDtos, + // ...modifyDefaultColumnValueScriptDtos, + // ...modifyCommentScriptDtos, + ].filter(Boolean); + }; + +module.exports = { + getModifyCollectionScriptDtos, + getModifyColumnScriptDtos, + getModifyCollectionKeysScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js new file mode 100644 index 0000000..11e5c6c --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js @@ -0,0 +1,13 @@ +// const { getModifyViewCommentsScriptDtos } = require('./viewHelpers/commentsHelper'); + +const getModifyViewScriptDtos = view => { + // const modifyCommentsScriptDtos = getModifyViewCommentsScriptDtos(...); + + return [ + // ...modifyCommentsScriptDtos, + ].filter(Boolean); +}; + +module.exports = { + getModifyViewScriptDtos, +}; diff --git a/forward_engineering/api.js b/forward_engineering/api.js index f69e0a9..a9f97d1 100644 --- a/forward_engineering/api.js +++ b/forward_engineering/api.js @@ -1,3 +1,5 @@ +const { generateContainerScript } = require('./api/generateContainerScript'); + module.exports = { generateScript(data, logger, callback, app) { throw new Error('Not implemented'); @@ -7,9 +9,7 @@ module.exports = { throw new Error('Not implemented'); }, - generateContainerScript(data, logger, callback, app) { - throw new Error('Not implemented'); - }, + generateContainerScript, getDatabases(connectionInfo, logger, callback, app) { throw new Error('Not implemented'); diff --git a/forward_engineering/api/generateContainerScript.js b/forward_engineering/api/generateContainerScript.js new file mode 100644 index 0000000..b57df78 --- /dev/null +++ b/forward_engineering/api/generateContainerScript.js @@ -0,0 +1,16 @@ +const { buildContainerLevelAlterScript } = require('../alterScript/alterScriptBuilder'); + +function generateContainerScript(data, logger, callback, app) { + try { + const script = buildContainerLevelAlterScript(data, app); + callback(null, script); + } catch (error) { + logger.log('error', { message: error.message, stack: error.stack }, 'Db2 Forward-Engineering Error'); + + callback({ message: error.message, stack: error.stack }); + } +} + +module.exports = { + generateContainerScript, +}; diff --git a/forward_engineering/config.json b/forward_engineering/config.json index 12eb15e..e213887 100644 --- a/forward_engineering/config.json +++ b/forward_engineering/config.json @@ -33,5 +33,401 @@ "name": "Apply Drop Statements", "isDropInStatements": true } + ], + "scriptGenerationOptions": [ + { + "keyword": "primaryKeys", + "label": "FE_SCRIPT_GENERATION_OPTIONS___PRIMARY_KEYS", + "disabled": false, + "value": { + "inline": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "separate": { + "default": false, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "key": "primaryKey", + "valueType": "array" + }, + "defaultValue": { + "primaryKey": [] + } + }, + { + "dependency": { + "key": "primaryKey", + "valueType": "object" + }, + + "defaultValue": { + "primaryKey": {} + } + }, + { + "dependency": { + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "compositePrimaryKey", + "value": true + } + ] + }, + "defaultValue": { + "primaryKey": false, + "compositePrimaryKey": false + } + } + ] + }, + { + "keyword": "foreignKeys", + "label": "FE_SCRIPT_GENERATION_OPTIONS___FOREIGN_KEYS", + "disabled": false, + "value": { + "inline": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "separate": { + "default": false, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + } + }, + { + "keyword": "uniqueConstraints", + "label": "FE_SCRIPT_GENERATION_OPTIONS___UNIQUE_KEYS", + "disabled": false, + "value": { + "inline": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "separate": { + "default": false, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "key": "uniqueKey", + "valueType": "array" + }, + "defaultValue": { + "uniqueKey": [] + } + }, + { + "dependency": { + "key": "uniqueKey", + "valueType": "object" + }, + "defaultValue": { + "uniqueKey": {} + } + }, + { + "dependency": { + "type": "or", + "values": [ + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + }, + { + "key": "compMode", + "exist": true + } + ] + }, + "defaultValue": { + "unique": false, + "compositeUniqueKey": false + } + } + ] + }, + { + "keyword": "columnNotNullConstraints", + "label": "FE_SCRIPT_GENERATION_OPTIONS___COLUMN_NOT_NULL", + "disabled": false, + "value": { + "inline": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "separate": { + "default": false, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "key": "required", + "value": true + }, + "defaultValue": { + "required": false + } + } + ] + }, + { + "keyword": "checkConstraints", + "label": "FE_SCRIPT_GENERATION_OPTIONS___CHECK_CONSTRAINTS", + "disabled": false, + "value": { + "inline": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "separate": { + "default": false, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "type": "or", + "values": [ + { + "key": "chkConstr", + "valueType": "array" + }, + { + "key": "checkConstraint", + "valueType": "array" + } + ] + }, + "defaultValue": { + "chkConstr": [], + "checkConstraint": [] + } + } + ] + }, + { + "keyword": "columnDefaultValues", + "label": "FE_SCRIPT_GENERATION_OPTIONS___COLUMN_DEFAULT_VALUES", + "disabled": false, + "value": { + "inline": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "separate": { + "default": false, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "key": "default", + "exist": true + }, + "defaultValue": { + "default": "" + } + } + ] + }, + { + "keyword": "tableComments", + "label": "FE_SCRIPT_GENERATION_OPTIONS___TABLE_COMMENTS", + "disabled": false, + "value": { + "inline": { + "default": false, + "disabled": true, + "disabledLabel": "" + }, + "separate": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "type": "and", + "values": [ + { + "key": "collectionName", + "exist": true + }, + { + "key": "description", + "exist": true + } + ] + }, + "defaultValue": { + "description": "" + } + } + ] + }, + { + "keyword": "viewComments", + "label": "FE_SCRIPT_GENERATION_OPTIONS___VIEW_COMMENTS", + "disabled": false, + "value": { + "inline": { + "default": false, + "disabled": true, + "disabledLabel": "" + }, + "separate": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "key": "viewOn", + "exist": true + }, + "defaultValue": { + "description": "" + } + } + ] + }, + { + "keyword": "columnComments", + "label": "FE_SCRIPT_GENERATION_OPTIONS___COLUMN_COMMENTS", + "disabled": false, + "value": { + "inline": { + "default": false, + "disabled": true, + "disabledLabel": "" + }, + "separate": { + "default": true, + "disabled": false, + "disabledLabel": "" + }, + "ignore": { + "default": false, + "disabled": false, + "disabledLabel": "" + } + }, + "adapters": [ + { + "dependency": { + "type": "and", + "values": [ + { + "type": "not", + "values": [ + { + "key": "type", + "value": "bucket" + }, + { + "level": "parent", + "key": "type", + "value": "definitions", + "inDepthParentSearch": true + } + ] + }, + { + "key": "collectionName", + "exist": false + }, + { + "key": "viewOn", + "exist": false + }, + { + "key": "description", + "exist": true + } + ] + }, + "defaultValue": { + "description": "" + } + } + ] + } ] } From ef64d2ef46a8d306cb957c1a1097e0654538ed5f Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Tue, 6 Jan 2026 17:31:44 +0100 Subject: [PATCH 02/11] add isDropInStatements --- api/fe.js | 2 ++ esbuild.package.js | 1 + .../alterScript/alterScriptBuilder.js | 21 ++++++++++++++++++ forward_engineering/api.js | 6 ++--- forward_engineering/api/isDropInStatements.js | 22 +++++++++++++++++++ 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 forward_engineering/api/isDropInStatements.js diff --git a/api/fe.js b/api/fe.js index 9529b66..64f1b6f 100644 --- a/api/fe.js +++ b/api/fe.js @@ -1,5 +1,7 @@ const { generateContainerScript } = require('../forward_engineering/api/generateContainerScript'); +const { isDropInStatements } = require('../forward_engineering/api/isDropInStatements'); module.exports = { generateContainerScript, + isDropInStatements, }; diff --git a/esbuild.package.js b/esbuild.package.js index 816fcd1..2ecd825 100644 --- a/esbuild.package.js +++ b/esbuild.package.js @@ -31,6 +31,7 @@ esbuild .build({ entryPoints: [ path.resolve(__dirname, 'forward_engineering', 'api.js'), + path.resolve(__dirname, 'api', 'fe.js'), path.resolve(__dirname, 'forward_engineering', 'ddlProvider.js'), path.resolve(__dirname, 'reverse_engineering', 'api.js'), ], diff --git a/forward_engineering/alterScript/alterScriptBuilder.js b/forward_engineering/alterScript/alterScriptBuilder.js index 61e9bc5..b5c2ad9 100644 --- a/forward_engineering/alterScript/alterScriptBuilder.js +++ b/forward_engineering/alterScript/alterScriptBuilder.js @@ -27,6 +27,15 @@ const joinAlterScriptDtosIntoScript = (dtos, shouldApplyDropStatements) => { .join('\n\n'); }; +const doesEntityLevelAlterScriptContainDropStatements = (data, app) => { + const alterScriptDtos = getAlterScriptDtos(data, app); + return alterScriptDtos.some( + alterScriptDto => + alterScriptDto.isActivated && + alterScriptDto.scripts.some(scriptModificationDto => scriptModificationDto.isDropScript), + ); +}; + const mapCoreDataForContainerLevelScripts = data => { return { ...data, @@ -45,6 +54,18 @@ const buildContainerLevelAlterScript = (data, app) => { return joinAlterScriptDtosIntoScript(alterScriptDtos, shouldApplyDropStatements); }; +const doesContainerLevelAlterScriptContainDropStatements = (data, app) => { + const preparedData = mapCoreDataForContainerLevelScripts(data); + const alterScriptDtos = getAlterScriptDtos(preparedData, app); + return alterScriptDtos.some( + alterScriptDto => + alterScriptDto.isActivated && + alterScriptDto.scripts.some(scriptModificationDto => scriptModificationDto.isDropScript), + ); +}; + module.exports = { + doesEntityLevelAlterScriptContainDropStatements, buildContainerLevelAlterScript, + doesContainerLevelAlterScriptContainDropStatements, }; diff --git a/forward_engineering/api.js b/forward_engineering/api.js index a9f97d1..f69e0a9 100644 --- a/forward_engineering/api.js +++ b/forward_engineering/api.js @@ -1,5 +1,3 @@ -const { generateContainerScript } = require('./api/generateContainerScript'); - module.exports = { generateScript(data, logger, callback, app) { throw new Error('Not implemented'); @@ -9,7 +7,9 @@ module.exports = { throw new Error('Not implemented'); }, - generateContainerScript, + generateContainerScript(data, logger, callback, app) { + throw new Error('Not implemented'); + }, getDatabases(connectionInfo, logger, callback, app) { throw new Error('Not implemented'); diff --git a/forward_engineering/api/isDropInStatements.js b/forward_engineering/api/isDropInStatements.js new file mode 100644 index 0000000..1d7fd53 --- /dev/null +++ b/forward_engineering/api/isDropInStatements.js @@ -0,0 +1,22 @@ +const { + doesContainerLevelAlterScriptContainDropStatements, + doesEntityLevelAlterScriptContainDropStatements, +} = require('../alterScript/alterScriptBuilder'); + +function isDropInStatements(data, logger, callback, app) { + try { + if (data.level === 'container') { + const containsDropStatements = doesContainerLevelAlterScriptContainDropStatements(data, app); + callback(null, containsDropStatements); + } else { + const containsDropStatements = doesEntityLevelAlterScriptContainDropStatements(data, app); + callback(null, containsDropStatements); + } + } catch (e) { + callback({ message: e.message, stack: e.stack }); + } +} + +module.exports = { + isDropInStatements, +}; From b188d923c24a88239680d1318c82fca5b1b56de5 Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Tue, 6 Jan 2026 17:32:59 +0100 Subject: [PATCH 03/11] fix --- forward_engineering/api.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/forward_engineering/api.js b/forward_engineering/api.js index f69e0a9..178d5d7 100644 --- a/forward_engineering/api.js +++ b/forward_engineering/api.js @@ -1,3 +1,6 @@ +const { generateContainerScript } = require('./api/generateContainerScript'); +const { isDropInStatements } = require('./api/isDropInStatements'); + module.exports = { generateScript(data, logger, callback, app) { throw new Error('Not implemented'); @@ -7,9 +10,7 @@ module.exports = { throw new Error('Not implemented'); }, - generateContainerScript(data, logger, callback, app) { - throw new Error('Not implemented'); - }, + generateContainerScript, getDatabases(connectionInfo, logger, callback, app) { throw new Error('Not implemented'); @@ -23,7 +24,5 @@ module.exports = { throw new Error('Not implemented'); }, - isDropInStatements(data, logger, callback, app) { - throw new Error('Not implemented'); - }, + isDropInStatements, }; From 4ae6a01099a7f011e52191bda5e10674aa23374c Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Tue, 6 Jan 2026 17:41:40 +0100 Subject: [PATCH 04/11] fix --- .../alterScript/alterScriptFromDeltaHelper.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index 21a6af1..da8336e 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -5,7 +5,7 @@ const { } = require('./alterScriptHelpers/alterEntityHelper'); const { getModifyViewScriptDtos } = require('./alterScriptHelpers/alterViewHelper'); -const getItems = data => data?.items || []; +const getItems = data => [data?.items].flat().filter(Boolean); const getAlterCollectionScriptDtos = ({ collection, @@ -15,9 +15,9 @@ const getAlterCollectionScriptDtos = ({ internalDefinitions, externalDefinitions, }) => { - const modifyScriptsData = getItems(collection.properties?.entities?.properties?.modified) - .filter(Boolean) - .map(item => Object.values(item.properties)[0]); + const modifyScriptsData = getItems(collection.properties?.entities?.properties?.modified).map( + item => Object.values(item.properties)[0], + ); const modifyCollectionScriptDtos = modifyScriptsData.flatMap(getModifyCollectionScriptDtos({ dbVersion })); const modifyCollectionKeysScriptDtos = modifyScriptsData.flatMap(getModifyCollectionKeysScriptDtos({ dbVersion })); @@ -33,7 +33,6 @@ const getAlterCollectionScriptDtos = ({ const getAlterViewScriptDtos = (collection, app) => { const modifyViewScriptDtos = getItems(collection.properties?.views?.properties?.modified) - .filter(Boolean) .map(viewWrapper => Object.values(viewWrapper.properties)[0]) .map(view => ({ ...view, ...(view.role || {}) })) .flatMap(view => getModifyViewScriptDtos(view)); From 5b178ffbc9be03971cbb39e689c59be482d72638 Mon Sep 17 00:00:00 2001 From: Alik Date: Wed, 7 Jan 2026 13:17:28 +0100 Subject: [PATCH 05/11] HCK-14211: script generation option for PK (#64)
Sub-taskHCK-14211 [DB2] Enable script generation options for PK

## Technical details Script generation option for PK. Keep the "drop" logic for the future ALTER script. --- .../alterScript/alterScriptBuilder.js | 2 +- .../alterScript/alterScriptFromDeltaHelper.js | 4 +- .../alterScriptHelpers/alterEntityHelper.js | 20 +- .../entityHelpers/primaryKeyHelper.js | 461 ++++++++++++++++++ .../alterScript/types/AlterKeyDto.js | 101 ++++ .../alterScript/types/AlterScriptDto.js | 97 ++++ .../ddlHelpers/key/constraintsHelper.js | 46 ++ .../ddlProvider/ddlHelpers/key/keyHelper.js | 1 + forward_engineering/ddlProvider/templates.js | 4 + forward_engineering/utils/general.js | 31 +- 10 files changed, 753 insertions(+), 14 deletions(-) create mode 100644 forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js create mode 100644 forward_engineering/alterScript/types/AlterKeyDto.js create mode 100644 forward_engineering/alterScript/types/AlterScriptDto.js create mode 100644 forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js diff --git a/forward_engineering/alterScript/alterScriptBuilder.js b/forward_engineering/alterScript/alterScriptBuilder.js index b5c2ad9..a5e0923 100644 --- a/forward_engineering/alterScript/alterScriptBuilder.js +++ b/forward_engineering/alterScript/alterScriptBuilder.js @@ -46,7 +46,7 @@ const mapCoreDataForContainerLevelScripts = data => { const buildContainerLevelAlterScript = (data, app) => { const preparedData = mapCoreDataForContainerLevelScripts(data); - const alterScriptDtos = []; + const alterScriptDtos = getAlterScriptDtos(preparedData, app); const shouldApplyDropStatements = preparedData.options?.additionalOptions?.some( option => option.id === 'applyDropStatements' && option.value, ); diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index da8336e..ff137d2 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -20,7 +20,7 @@ const getAlterCollectionScriptDtos = ({ ); const modifyCollectionScriptDtos = modifyScriptsData.flatMap(getModifyCollectionScriptDtos({ dbVersion })); - const modifyCollectionKeysScriptDtos = modifyScriptsData.flatMap(getModifyCollectionKeysScriptDtos({ dbVersion })); + const modifyCollectionKeysScriptDtos = modifyScriptsData.flatMap(getModifyCollectionKeysScriptDtos); const modifyColumnScriptDtos = modifyScriptsData.flatMap( getModifyColumnScriptDtos({ app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions }), @@ -34,7 +34,7 @@ const getAlterCollectionScriptDtos = ({ const getAlterViewScriptDtos = (collection, app) => { const modifyViewScriptDtos = getItems(collection.properties?.views?.properties?.modified) .map(viewWrapper => Object.values(viewWrapper.properties)[0]) - .map(view => ({ ...view, ...(view.role || {}) })) + .map(view => ({ ...view, ...view.role })) .flatMap(view => getModifyViewScriptDtos(view)); return [...modifyViewScriptDtos].filter(Boolean); diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js index 1f638d6..b6eaacf 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -1,3 +1,5 @@ +const { getModifyPkConstraintsScriptDtos } = require('./entityHelpers/primaryKeyHelper'); + const getModifyCollectionScriptDtos = ({}) => collection => { @@ -9,16 +11,14 @@ const getModifyCollectionScriptDtos = ].filter(Boolean); }; -const getModifyCollectionKeysScriptDtos = - ({}) => - collection => { - // const modifyPkConstraintDtos = getModifyPkConstraintScriptDtos(...); - // const modifyUkConstraintDtos = getModifyUkConstraintsScriptDtos(...); - return [ - // ...modifyPkConstraintDtos, - // ...modifyUniqueKeyConstraintDtos, - ].filter(Boolean); - }; +const getModifyCollectionKeysScriptDtos = collection => { + const modifyPkConstraintDtos = getModifyPkConstraintsScriptDtos(collection); + // const modifyUkConstraintDtos = getModifyUkConstraintsScriptDtos(...); + return [ + ...modifyPkConstraintDtos, + // ...modifyUniqueKeyConstraintDtos, + ].filter(Boolean); +}; const getModifyColumnScriptDtos = ({}) => diff --git a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js new file mode 100644 index 0000000..f45bda9 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js @@ -0,0 +1,461 @@ +const _ = require('lodash'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { PrimaryKeyTransitionDto, KeyScriptModificationDto } = require('../../types/AlterKeyDto'); +const { + getFullCollectionName, + getSchemaOfAlterCollection, + getEntityName, + wrapInQuotes, + isParentContainerActivated, + isObjectInDeltaModelActivated, +} = require('../../../utils/general'); +const { alterPkConstraint, dropPK } = require('../../../ddlProvider/ddlHelpers/key/constraintsHelper'); +const { KEY_TYPE } = require('../../../ddlProvider/ddlHelpers/key/keyHelper'); + +const amountOfColumnsInRegularPk = 1; + +const getDefaultConstraintName = entityName => { + return `${entityName}_pkey`; +}; + +const extractOptionsForComparisonWithRegularPkOptions = (optionHolder = {}) => { + return { + constraintName: optionHolder.constraintName, + deferClause: optionHolder.deferClause, + exceptionClause: optionHolder.exceptionClause, + id: optionHolder.id, + indexClause: optionHolder.indexClause, + rely: optionHolder.rely, + validate: optionHolder.validate, + }; +}; + +const getCustomPropertiesOfRegularPkForComparisonWithRegularPkOptions = columnJsonSchema => { + return extractOptionsForComparisonWithRegularPkOptions(columnJsonSchema.primaryKeyOptions); +}; + +const getCustomPropertiesOfCompositePkForComparisonWithRegularPkOptions = compositePk => { + const optionsForComparison = extractOptionsForComparisonWithRegularPkOptions(compositePk); + return [optionsForComparison].filter(o => Object.values(o).some(Boolean)); +}; + +const wasCompositePkChangedInTransitionFromCompositeToRegular = collection => { + const pkDto = collection?.role?.compMod?.primaryKey || {}; + const oldPrimaryKeys = pkDto.old || []; + const idsOfColumns = oldPrimaryKeys.flatMap(pk => pk.compositePrimaryKey?.map(dto => dto.keyId) || []); + if (idsOfColumns.length !== amountOfColumnsInRegularPk) { + // We return false, because it wouldn't count as transition between regular PK and composite PK + // if composite PK did not constraint exactly 1 column + return PrimaryKeyTransitionDto.noTransition(); + } + const idOfPkColumn = idsOfColumns[0]; + const newColumnJsonSchema = Object.values(collection.properties).find( + columnJsonSchema => columnJsonSchema.GUID === idOfPkColumn, + ); + if (!newColumnJsonSchema) { + return PrimaryKeyTransitionDto.noTransition(); + } + const isNewColumnARegularPrimaryKey = newColumnJsonSchema?.primaryKey && !newColumnJsonSchema?.compositePrimaryKey; + if (!isNewColumnARegularPrimaryKey) { + return PrimaryKeyTransitionDto.noTransition(); + } + const constraintOptions = getCustomPropertiesOfRegularPkForComparisonWithRegularPkOptions(newColumnJsonSchema); + const areOptionsEqual = oldPrimaryKeys.some(compositePk => { + if (compositePk.compositePrimaryKey?.length !== amountOfColumnsInRegularPk) { + return false; + } + const oldCompositePkAsRegularPkOptions = + getCustomPropertiesOfCompositePkForComparisonWithRegularPkOptions(compositePk); + + return _.isEqual(oldCompositePkAsRegularPkOptions, constraintOptions); + }); + + return PrimaryKeyTransitionDto.transition(!areOptionsEqual); +}; + +const wasCompositePkChangedInTransitionFromRegularToComposite = collection => { + /** + * @type {AlterCollectionRoleCompModPrimaryKey} + * */ + const pkDto = collection?.role?.compMod?.primaryKey || {}; + /** + * @type {AlterCollectionRoleCompModPKDto[]} + * */ + const newPrimaryKeys = pkDto.new || []; + const idsOfColumns = newPrimaryKeys.flatMap(pk => pk.compositePrimaryKey?.map(dto => dto.keyId) || []); + if (idsOfColumns.length !== amountOfColumnsInRegularPk) { + // We return false, because it wouldn't count as transition between regular PK and composite PK + // if composite PK does not constraint exactly 1 column + return PrimaryKeyTransitionDto.noTransition(); + } + const idOfPkColumn = idsOfColumns[0]; + const oldColumnJsonSchema = Object.values(collection.role.properties).find( + columnJsonSchema => columnJsonSchema.GUID === idOfPkColumn, + ); + if (!oldColumnJsonSchema) { + return PrimaryKeyTransitionDto.noTransition(); + } + const isOldColumnARegularPrimaryKey = oldColumnJsonSchema?.primaryKey && !oldColumnJsonSchema?.compositePrimaryKey; + if (!isOldColumnARegularPrimaryKey) { + return PrimaryKeyTransitionDto.noTransition(); + } + const constraintOptions = getCustomPropertiesOfRegularPkForComparisonWithRegularPkOptions(oldColumnJsonSchema); + const areOptionsEqual = newPrimaryKeys.some(compositePk => { + if (compositePk.compositePrimaryKey?.length !== amountOfColumnsInRegularPk) { + return false; + } + const oldCompositePkAsRegularPkOptions = + getCustomPropertiesOfCompositePkForComparisonWithRegularPkOptions(compositePk); + + return _.isEqual(oldCompositePkAsRegularPkOptions, constraintOptions); + }); + + return PrimaryKeyTransitionDto.transition(!areOptionsEqual); +}; + +const getConstraintNameForCompositePk = (primaryKey, entityName) => { + if (primaryKey.constraintName) { + return primaryKey.constraintName; + } + return getDefaultConstraintName(entityName); +}; + +const getCreateCompositePKDDLProviderConfig = (primaryKey, entityName, entity) => { + const constraintName = getConstraintNameForCompositePk(primaryKey, entityName); + const pkColumns = _.toPairs(entity.role.properties) + .filter(([name, jsonSchema]) => + Boolean(primaryKey.compositePrimaryKey?.find(keyDto => keyDto.keyId === jsonSchema.GUID)), + ) + .map(([name, jsonSchema]) => ({ + name, + isActivated: jsonSchema.isActivated, + })); + + return { + keyType: KEY_TYPE.primaryKey, + name: constraintName, + columns: pkColumns, + }; +}; + +const getAddCompositePkScriptDtos = collection => { + /** + * @type {AlterCollectionRoleCompModPrimaryKey} + * */ + const pkDto = collection?.role?.compMod?.primaryKey || {}; + const newPrimaryKeys = pkDto.new || []; + const oldPrimaryKeys = pkDto.old || []; + if (newPrimaryKeys.length === 0 && oldPrimaryKeys.length === 0) { + return []; + } + const transitionToCompositeDto = wasCompositePkChangedInTransitionFromRegularToComposite(collection); + if (transitionToCompositeDto.didTransitionHappen && !transitionToCompositeDto.wasPkChangedInTransition) { + return []; + } + if (newPrimaryKeys.length === oldPrimaryKeys.length) { + const areKeyArraysEqual = _(oldPrimaryKeys).differenceWith(newPrimaryKeys, _.isEqual).isEmpty(); + if (areKeyArraysEqual) { + return []; + } + } + + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + const entityName = getEntityName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return newPrimaryKeys + .map(newPk => { + const ddlConfig = getCreateCompositePKDDLProviderConfig(newPk, entityName, collection); + if (_.isEmpty(ddlConfig.columns)) { + return null; + } + const statementDto = alterPkConstraint(fullTableName, isCollectionActivated, ddlConfig); + return new KeyScriptModificationDto(statementDto.statement, fullTableName, false, statementDto.isActivated); + }) + .filter(scriptDto => Boolean(scriptDto?.script)); +}; + +const getDropCompositePkScriptDtos = collection => { + const pkDto = collection?.role?.compMod?.primaryKey || {}; + const newPrimaryKeys = pkDto.new || []; + const oldPrimaryKeys = pkDto.old || []; + if (newPrimaryKeys.length === 0 && oldPrimaryKeys.length === 0) { + return []; + } + const transitionToCompositeDto = wasCompositePkChangedInTransitionFromCompositeToRegular(collection); + if (transitionToCompositeDto.didTransitionHappen && !transitionToCompositeDto.wasPkChangedInTransition) { + return []; + } + if (newPrimaryKeys.length === oldPrimaryKeys.length) { + const areKeyArraysEqual = _(oldPrimaryKeys).differenceWith(newPrimaryKeys, _.isEqual).isEmpty(); + if (areKeyArraysEqual) { + return []; + } + } + + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return oldPrimaryKeys + .map(oldPk => { + const script = dropPK(fullTableName); + return new KeyScriptModificationDto(script, fullTableName, true, isCollectionActivated); + }) + .filter(scriptDto => Boolean(scriptDto.script)); +}; + +const getModifyCompositePkScriptDtos = collection => { + const dropCompositePkScriptDtos = getDropCompositePkScriptDtos(collection); + const addCompositePkScriptDtos = getAddCompositePkScriptDtos(collection); + + return [...dropCompositePkScriptDtos, ...addCompositePkScriptDtos].filter(Boolean); +}; + +const getConstraintNameForRegularPk = (columnJsonSchema, entityName) => { + const constraintOptions = columnJsonSchema.primaryKeyOptions; + if (constraintOptions?.constraintName?.trim()) { + return constraintOptions.constraintName; + } + return getDefaultConstraintName(entityName); +}; + +const getCreateRegularPKDDLProviderConfig = (columnName, columnJsonSchema, entityName, entity) => { + const constraintName = getConstraintNameForRegularPk(columnJsonSchema, entityName); + const pkColumns = [ + { + name: columnName, + isActivated: columnJsonSchema.isActivated, + }, + ]; + + return { + keyType: KEY_TYPE.primaryKey, + name: constraintName, + columns: pkColumns, + options: columnJsonSchema.primaryKeyOptions, + }; +}; + +const wasFieldChangedToBeARegularPk = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldColumnJsonSchema = collection.role.properties[oldName]; + + const isRegularPrimaryKey = columnJsonSchema.primaryKey && !columnJsonSchema.compositePrimaryKey; + const wasTheFieldAnyPrimaryKey = Boolean(oldColumnJsonSchema?.primaryKey); + + return isRegularPrimaryKey && !wasTheFieldAnyPrimaryKey; +}; + +const wasRegularPkChangedInTransitionFromCompositeToRegular = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldColumnJsonSchema = collection.role.properties[oldName]; + + const isRegularPrimaryKey = columnJsonSchema.primaryKey && !columnJsonSchema.compositePrimaryKey; + const wasTheFieldAnyPrimaryKey = Boolean(oldColumnJsonSchema?.primaryKey); + + if (!(isRegularPrimaryKey && wasTheFieldAnyPrimaryKey)) { + return PrimaryKeyTransitionDto.noTransition(); + } + + const pkDto = collection?.role?.compMod?.primaryKey || {}; + const newPrimaryKeys = pkDto.new || []; + const oldPrimaryKeys = pkDto.old || []; + const wasTheFieldACompositePrimaryKey = oldPrimaryKeys.some(compPk => + compPk.compositePrimaryKey?.some(pk => pk.keyId === oldColumnJsonSchema.GUID), + ); + const isTheFieldACompositePrimaryKey = newPrimaryKeys.some(compPk => + compPk.compositePrimaryKey?.some(pk => pk.keyId === columnJsonSchema.GUID), + ); + + const wasCompositePkRemoved = wasTheFieldACompositePrimaryKey && !isTheFieldACompositePrimaryKey; + + if (isRegularPrimaryKey && wasCompositePkRemoved) { + // return compare custom properties and amount of columns. + // If there was a transition and amount of composite PK columns is not equal + // to amount of regular pk columns, we must recreate PK + const constraintOptions = getCustomPropertiesOfRegularPkForComparisonWithRegularPkOptions(columnJsonSchema); + const areOptionsEqual = oldPrimaryKeys.some(oldCompositePk => { + if (oldCompositePk.compositePrimaryKey?.length !== amountOfColumnsInRegularPk) { + return false; + } + const oldCompositePkAsRegularPkOptions = + getCustomPropertiesOfCompositePkForComparisonWithRegularPkOptions(oldCompositePk); + + return _.isEqual(oldCompositePkAsRegularPkOptions, constraintOptions); + }); + return PrimaryKeyTransitionDto.transition(!areOptionsEqual); + } + + return PrimaryKeyTransitionDto.noTransition(); +}; + +const wasRegularPkChangedInTransitionFromRegularToComposite = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldColumnJsonSchema = collection.role.properties[oldName]; + + const wasRegularPrimaryKey = oldColumnJsonSchema.primaryKey && !oldColumnJsonSchema.compositePrimaryKey; + const isTheFieldAnyPrimaryKey = Boolean(columnJsonSchema?.primaryKey); + + if (!(wasRegularPrimaryKey && isTheFieldAnyPrimaryKey)) { + return PrimaryKeyTransitionDto.noTransition(); + } + + const pkDto = collection?.role?.compMod?.primaryKey || {}; + const newPrimaryKeys = pkDto.new || []; + const oldPrimaryKeys = pkDto.old || []; + const wasTheFieldACompositePrimaryKey = oldPrimaryKeys.some(compPk => + compPk.compositePrimaryKey?.some(pk => pk.keyId === oldColumnJsonSchema.GUID), + ); + const isTheFieldACompositePrimaryKey = newPrimaryKeys.some(compPk => + compPk.compositePrimaryKey?.some(pk => pk.keyId === columnJsonSchema.GUID), + ); + + const wasCompositePkAdded = isTheFieldACompositePrimaryKey && !wasTheFieldACompositePrimaryKey; + + if (wasRegularPrimaryKey && wasCompositePkAdded) { + // return compare custom properties and amount of columns. + // If there was a transition and amount of composite PK columns is not equal + // to amount of regular pk columns, we must recreate PK + const constraintOptions = getCustomPropertiesOfRegularPkForComparisonWithRegularPkOptions(oldColumnJsonSchema); + const areOptionsEqual = newPrimaryKeys.some(oldCompositePk => { + if (oldCompositePk.compositePrimaryKey?.length !== amountOfColumnsInRegularPk) { + return false; + } + const oldCompositePkAsRegularPkOptions = + getCustomPropertiesOfCompositePkForComparisonWithRegularPkOptions(oldCompositePk); + + return _.isEqual(oldCompositePkAsRegularPkOptions, constraintOptions); + }); + return PrimaryKeyTransitionDto.transition(!areOptionsEqual); + } + + return PrimaryKeyTransitionDto.noTransition(); +}; + +const isFieldNoLongerARegularPk = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + + const oldJsonSchema = collection.role.properties[oldName]; + const wasTheFieldARegularPrimaryKey = oldJsonSchema?.primaryKey && !oldJsonSchema?.compositePrimaryKey; + + const isNotAnyPrimaryKey = !columnJsonSchema.primaryKey && !columnJsonSchema.compositePrimaryKey; + return wasTheFieldARegularPrimaryKey && isNotAnyPrimaryKey; +}; + +const wasRegularPkModified = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldJsonSchema = collection.role.properties[oldName] || {}; + + const isRegularPrimaryKey = columnJsonSchema.primaryKey && !columnJsonSchema.compositePrimaryKey; + const wasTheFieldARegularPrimaryKey = oldJsonSchema?.primaryKey && !oldJsonSchema?.compositePrimaryKey; + + if (!(isRegularPrimaryKey && wasTheFieldARegularPrimaryKey)) { + return false; + } + const constraintOptions = getCustomPropertiesOfRegularPkForComparisonWithRegularPkOptions(columnJsonSchema); + const oldConstraintOptions = getCustomPropertiesOfRegularPkForComparisonWithRegularPkOptions(oldJsonSchema); + + return !_.isEqual(oldConstraintOptions, constraintOptions); +}; + +const getAddPkScriptDtos = collection => { + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + const entityName = getEntityName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + if (wasFieldChangedToBeARegularPk(jsonSchema, collection)) { + return true; + } + const transitionToRegularDto = wasRegularPkChangedInTransitionFromCompositeToRegular( + jsonSchema, + collection, + ); + if (transitionToRegularDto.didTransitionHappen) { + return transitionToRegularDto.wasPkChangedInTransition; + } + return wasRegularPkModified(jsonSchema, collection); + }) + .map(([name, jsonSchema]) => { + const ddlConfig = getCreateRegularPKDDLProviderConfig(name, jsonSchema, entityName, collection); + const statementDto = alterPkConstraint(fullTableName, isCollectionActivated, ddlConfig); + return new KeyScriptModificationDto(statementDto.statement, fullTableName, false, statementDto.isActivated); + }) + .filter(scriptDto => Boolean(scriptDto.script)); +}; + +const getDropPkScriptDto = collection => { + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + if (isFieldNoLongerARegularPk(jsonSchema, collection)) { + return true; + } + const transitionToRegularDto = wasRegularPkChangedInTransitionFromRegularToComposite( + jsonSchema, + collection, + ); + if (transitionToRegularDto.didTransitionHappen) { + return transitionToRegularDto.wasPkChangedInTransition; + } + return wasRegularPkModified(jsonSchema, collection); + }) + .map(([name, jsonSchema]) => { + const script = dropPK(fullTableName); + return new KeyScriptModificationDto(script, fullTableName, true, isCollectionActivated); + }) + .filter(scriptDto => Boolean(scriptDto.script)); +}; + +const getModifyPkScriptDtos = collection => { + const dropPkScriptDtos = getDropPkScriptDto(collection); + const addPkScriptDtos = getAddPkScriptDtos(collection); + + return [...dropPkScriptDtos, ...addPkScriptDtos].filter(Boolean); +}; + +const sortModifyPkConstraints = constraintDtos => { + return constraintDtos.sort((c1, c2) => { + if (c1.fullTableName === c2.fullTableName) { + // Number(true) = 1, Number(false) = 0; + // This ensures that DROP script appears before CREATE script + // if the same table has 2 scripts that drop and recreate PK + return Number(c2.isDropScript) - Number(c1.isDropScript); + } + // This sorts all statements based on full table name, ASC + return c1.fullTableName.localeCompare(c2.fullTableName); + }); +}; + +const getModifyPkConstraintsScriptDtos = collection => { + const modifyCompositePkScriptDtos = getModifyCompositePkScriptDtos(collection); + const modifyPkScriptDtos = getModifyPkScriptDtos(collection); + + const allDtos = [...modifyCompositePkScriptDtos, ...modifyPkScriptDtos]; + const sortedAllDtos = sortModifyPkConstraints(allDtos); + + return sortedAllDtos + .map(dto => { + return AlterScriptDto.getInstance([dto.script], dto.isActivated, dto.isDropScript); + }) + .filter(Boolean); +}; + +module.exports = { + getModifyPkConstraintsScriptDtos, +}; diff --git a/forward_engineering/alterScript/types/AlterKeyDto.js b/forward_engineering/alterScript/types/AlterKeyDto.js new file mode 100644 index 0000000..56e0421 --- /dev/null +++ b/forward_engineering/alterScript/types/AlterKeyDto.js @@ -0,0 +1,101 @@ +class KeyTransitionDto { + /** + * @type {boolean} + * */ + didTransitionHappen; + + /** + * @return {KeyTransitionDto} + * */ + static noTransition() { + return { + didTransitionHappen: false, + }; + } + + /** + * @return {KeyTransitionDto} + * */ + static transition() { + return { + didTransitionHappen: true, + }; + } +} + +class PrimaryKeyTransitionDto extends KeyTransitionDto { + /** + * @type {boolean | undefined} + * */ + wasPkChangedInTransition; + + /** + * @param {boolean} wasPkChangedInTransition + * @return {PrimaryKeyTransitionDto} + * */ + static transition(wasPkChangedInTransition) { + return { + didTransitionHappen: true, + wasPkChangedInTransition, + }; + } +} + +class UniqueKeyTransitionDto extends KeyTransitionDto { + /** + * @type {boolean | undefined} + * */ + wasUniqueKeyChangedInTransition; + + /** + * @param {boolean} wasUniqueKeyChangedInTransition + * @return {UniqueKeyTransitionDto} + * */ + static transition(wasUniqueKeyChangedInTransition) { + return { + didTransitionHappen: true, + wasUniqueKeyChangedInTransition, + }; + } +} + +class KeyScriptModificationDto { + /** + * @type {string} + * */ + script; + + /** + * @type {boolean} + * */ + isDropScript; + + /** + * @type {string} + * */ + fullTableName; + + /** + * @type {boolean} + * */ + isActivated; + + /** + * @param {string} fullTableName + * @param {string} script + * @param {boolean} isDropScript + * @param {boolean} isActivated + * */ + constructor(script, fullTableName, isDropScript, isActivated) { + this.script = script; + this.isDropScript = isDropScript; + this.fullTableName = fullTableName; + this.isActivated = isActivated; + } +} + +module.exports = { + KeyScriptModificationDto, + PrimaryKeyTransitionDto, + UniqueKeyTransitionDto, +}; diff --git a/forward_engineering/alterScript/types/AlterScriptDto.js b/forward_engineering/alterScript/types/AlterScriptDto.js new file mode 100644 index 0000000..599c33f --- /dev/null +++ b/forward_engineering/alterScript/types/AlterScriptDto.js @@ -0,0 +1,97 @@ +class ModificationScript { + /** + * @type string + * */ + script; + + /** + * @type boolean + * */ + isDropScript; +} + +class AlterScriptDto { + /** + * @type {boolean | undefined} + * */ + isActivated; + + /** + * @type {Array} + * */ + scripts; + + /** + * @param scripts {Array} + * @param isActivated {boolean} + * @param isDropScripts {boolean} + * @return {Array} + * */ + static getInstances(scripts, isActivated, isDropScripts) { + return (scripts || []).filter(Boolean).map(script => ({ + isActivated, + scripts: [ + { + isDropScript: isDropScripts, + script, + }, + ], + })); + } + + /** + * @param scripts {Array} + * @param isActivated {boolean} + * @param isDropScripts {boolean} + * @return {AlterScriptDto | undefined} + * */ + static getInstance(scripts, isActivated, isDropScripts) { + if (!scripts?.filter(Boolean)?.length) { + return undefined; + } + return { + isActivated, + scripts: scripts.filter(Boolean).map(script => ({ + isDropScript: isDropScripts, + script, + })), + }; + } + + /** + * @param dropScript {string | undefined} + * @param createScript {string | undefined} + * @param isActivated {boolean} + * @return {AlterScriptDto | undefined} + * */ + static getDropAndRecreateInstance(dropScript, createScript, isActivated) { + /** + * @type {ModificationScript[]} + * */ + const scriptModificationDtos = []; + if (dropScript) { + scriptModificationDtos.push({ + isDropScript: true, + script: dropScript, + }); + } + if (createScript) { + scriptModificationDtos.push({ + isDropScript: false, + script: createScript, + }); + } + if (!scriptModificationDtos?.length) { + return undefined; + } + return { + isActivated, + scripts: scriptModificationDtos, + }; + } +} + +module.exports = { + ModificationScript, + AlterScriptDto, +}; diff --git a/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js b/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js new file mode 100644 index 0000000..9236da9 --- /dev/null +++ b/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js @@ -0,0 +1,46 @@ +const _ = require('lodash'); +const { + commentIfDeactivated, + checkAllKeysDeactivated, + getColumnsList, + wrapInQuotes, +} = require('../../../utils/general'); +const { assignTemplates } = require('../../../utils/assignTemplates'); +const templates = require('../../templates'); + +const alterPkConstraint = (tableName, isParentActivated, keyData) => { + const constraintName = wrapInQuotes({ name: keyData.name.trim() }); + const isAllColumnsDeactivated = checkAllKeysDeactivated(keyData.columns || []); + const columns = _.isEmpty(keyData.columns) + ? '' + : getColumnsList(keyData.columns, isAllColumnsDeactivated, isParentActivated); + + const { deferClause, rely, indexClause, validate, exceptionClause } = keyData.options || {}; + const options = [deferClause, rely, indexClause, validate, exceptionClause] + .filter(Boolean) + .map(option => ` ${option}`) + .join(''); + + return { + statement: assignTemplates({ + template: templates.alterPkConstraint, + templateData: { + tableName, + constraintName, + columns, + options, + }, + }), + isActivated: !isAllColumnsDeactivated && isParentActivated, + }; +}; + +const dropPK = tableName => { + const templatesConfig = { tableName }; + return assignTemplates(templates.dropPK, templatesConfig); +}; + +module.exports = { + alterPkConstraint, + dropPK, +}; diff --git a/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js b/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js index b54d228..005d47d 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js +++ b/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js @@ -218,4 +218,5 @@ module.exports = { foreignKeysToString, foreignActiveKeysToString, customPropertiesForForeignKey, + KEY_TYPE, }; diff --git a/forward_engineering/ddlProvider/templates.js b/forward_engineering/ddlProvider/templates.js index 4635acc..8bb07e9 100644 --- a/forward_engineering/ddlProvider/templates.js +++ b/forward_engineering/ddlProvider/templates.js @@ -26,4 +26,8 @@ module.exports = { viewSelectStatement: 'SELECT ${keys}\n\tFROM ${tableName}', createIndex: 'CREATE${indexType} INDEX${indexName} ON ${indexTableName}${indexOptions};\n', + + alterPkConstraint: 'ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} PRIMARY KEY${columns}${options};', + + dropPK: 'ALTER TABLE ${tableName} DROP PRIMARY KEY;', }; diff --git a/forward_engineering/utils/general.js b/forward_engineering/utils/general.js index e29941d..6547c5c 100644 --- a/forward_engineering/utils/general.js +++ b/forward_engineering/utils/general.js @@ -1,4 +1,4 @@ -const { toLower } = require('lodash'); +const { toLower, omit } = require('lodash'); const { INLINE_COMMENT } = require('../../constants/constants'); /** @@ -116,6 +116,30 @@ const getColumnsList = (columns, isAllColumnsDeactivated, isParentActivated, map */ const toArray = ({ value }) => (Array.isArray(value) ? value : [value]); +const getEntityName = entityData => { + return (entityData && (entityData.code || entityData.collectionName)) || ''; +}; + +const getFullCollectionName = collectionSchema => { + const name = getEntityName(collectionSchema); + const schemaName = collectionSchema.compMod?.keyspaceName; + return getNamePrefixedWithSchemaName({ name, schemaName }); +}; + +const getSchemaOfAlterCollection = collection => { + return { ...collection, ...(omit(collection?.role, 'properties') || {}) }; +}; + +const isObjectInDeltaModelActivated = modelObject => { + return modelObject.compMod?.isActivated?.new ?? modelObject.role?.isActivated; +}; + +const isParentContainerActivated = collection => { + return ( + collection?.compMod?.bucketProperties?.isActivated ?? collection?.role?.compMod?.bucketProperties?.isActivated + ); +}; + module.exports = { setTab, hasType, @@ -128,4 +152,9 @@ module.exports = { getNamePrefixedWithSchemaName, getColumnsList, toArray, + getFullCollectionName, + getEntityName, + getSchemaOfAlterCollection, + isObjectInDeltaModelActivated, + isParentContainerActivated, }; From 6be916a65ef08e99d30af1c2f571fe68c4fc1b0b Mon Sep 17 00:00:00 2001 From: Alik Date: Thu, 8 Jan 2026 08:23:26 +0100 Subject: [PATCH 06/11] HCK-14212: Script generation options for FK (#65)
Sub-taskHCK-14212 [DB2] Enable script generation options for FK

--- constants/constants.js | 10 ++ .../alterScript/alterScriptFromDeltaHelper.js | 66 +++++++++- .../alterForeignKeyHelper.js | 121 ++++++++++++++++++ .../entityHelpers/primaryKeyHelper.js | 3 +- .../ddlProvider/ddlProvider.js | 8 ++ forward_engineering/ddlProvider/templates.js | 2 + forward_engineering/utils/general.js | 3 + 7 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js diff --git a/constants/constants.js b/constants/constants.js index 7a75406..b489e24 100644 --- a/constants/constants.js +++ b/constants/constants.js @@ -15,9 +15,19 @@ const INLINE_COMMENT = '--'; const PERSENT = '__PERCENT__'; +const CONSTRAINT_POSTFIX = { + primaryKey: 'pk', + foreignKey: 'fk', + uniqueKey: 'uk', + notNull: 'nn', + check: 'check', + default: 'default', +}; + module.exports = { ERROR_MESSAGE, TABLE_TYPE, INLINE_COMMENT, PERSENT, + CONSTRAINT_POSTFIX, }; diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index ff137d2..aa0d553 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -3,6 +3,11 @@ const { getModifyCollectionKeysScriptDtos, getModifyColumnScriptDtos, } = require('./alterScriptHelpers/alterEntityHelper'); +const { + getDeleteForeignKeyScriptDtos, + getAddForeignKeyScriptDtos, + getModifyForeignKeyScriptDtos, +} = require('./alterScriptHelpers/alterForeignKeyHelper'); const { getModifyViewScriptDtos } = require('./alterScriptHelpers/alterViewHelper'); const getItems = data => [data?.items].flat().filter(Boolean); @@ -40,6 +45,56 @@ const getAlterViewScriptDtos = (collection, app) => { return [...modifyViewScriptDtos].filter(Boolean); }; +const getAlterRelationshipsScriptDtos = ({ collection, app, ignoreRelationshipIDs = [] }) => { + const ddlProvider = require('../ddlProvider/ddlProvider')(null, null, app); + + const addedRelationships = getItems(collection.properties?.relationships?.properties?.added) + .filter(Boolean) + .map(item => Object.values(item.properties)[0]) + .filter( + relationship => + relationship?.role?.compMod?.created && !ignoreRelationshipIDs.includes(relationship?.role?.id), + ); + + const deletedRelationships = getItems(collection.properties?.relationships?.properties?.deleted) + .filter(Boolean) + .map(item => Object.values(item.properties)[0]) + .filter( + relationship => + relationship?.role?.compMod?.deleted && !ignoreRelationshipIDs.includes(relationship?.role?.id), + ); + + const modifiedRelationships = getItems(collection.properties?.relationships?.properties?.modified) + .filter(Boolean) + .map(item => Object.values(item.properties)[0]) + .filter( + relationship => + relationship?.role?.compMod?.modified && !ignoreRelationshipIDs.includes(relationship?.role?.id), + ); + + const deleteFkScriptDtos = getDeleteForeignKeyScriptDtos(ddlProvider)(deletedRelationships); + const addFkScriptDtos = getAddForeignKeyScriptDtos(ddlProvider)(addedRelationships); + const modifiedFkScriptDtos = getModifyForeignKeyScriptDtos(ddlProvider)(modifiedRelationships); + + return [...deleteFkScriptDtos, ...addFkScriptDtos, ...modifiedFkScriptDtos].filter(Boolean); +}; + +const getInlineRelationships = ({ collection, options }) => { + if (options?.scriptGenerationOptions?.feActiveOptions?.foreignKeys !== 'inline') { + return []; + } + + const addedCollectionIDs = getItems(collection.properties?.entities?.properties?.added) + .filter(item => item && Object.values(item.properties)?.[0]?.compMod?.created) + .map(item => Object.values(item.properties)[0].role.id); + + const addedRelationships = getItems(collection.properties?.relationships?.properties?.added) + .map(item => item && Object.values(item.properties)[0]) + .filter(r => r?.role?.compMod?.created && addedCollectionIDs.includes(r?.role?.childCollection)); + + return addedRelationships; +}; + const prettifyAlterScriptDto = dto => { if (!dto) { return undefined; @@ -76,6 +131,9 @@ const getAlterScriptDtos = (data, app) => { const externalDefinitions = JSON.parse(data.externalDefinitions); const dbVersion = data.modelData[0]?.dbVersion; + const inlineDeltaRelationships = getInlineRelationships({ collection, options: data.options }); + const ignoreRelationshipIDs = inlineDeltaRelationships.map(relationship => relationship.role.id); + const collectionsScriptDtos = getAlterCollectionScriptDtos({ collection, app, @@ -87,7 +145,13 @@ const getAlterScriptDtos = (data, app) => { const viewScriptDtos = getAlterViewScriptDtos({ collection, app }); - return [...collectionsScriptDtos, ...viewScriptDtos] + const relationshipScriptDtos = getAlterRelationshipsScriptDtos({ + collection, + app, + ignoreRelationshipIDs, + }); + + return [...collectionsScriptDtos, ...viewScriptDtos, ...relationshipScriptDtos] .filter(Boolean) .map(dto => dto && prettifyAlterScriptDto(dto)) .filter(Boolean); diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js new file mode 100644 index 0000000..fa1fedb --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js @@ -0,0 +1,121 @@ +const _ = require('lodash'); +const { AlterScriptDto } = require('../types/AlterScriptDto'); +const { getNamePrefixedWithSchemaName, wrapInQuotes, removeAllQuotes } = require('../../utils/general'); +const { CONSTRAINT_POSTFIX } = require('../../../constants/constants'); + +const getRelationshipName = relationship => { + const compMod = relationship.role.compMod; + const name = compMod.code?.new || compMod.name?.new || relationship.role.code || relationship.role.name; + return name; +}; + +const getFullChildTableName = relationship => { + const compMod = relationship.role.compMod; + + const childBucketName = compMod.child.bucket.name; + const childEntityName = compMod.child.collection.name; + return getNamePrefixedWithSchemaName({ name: childEntityName, schemaName: childBucketName }); +}; + +const getAddSingleForeignKeyStatementDto = ddlProvider => relationship => { + const compMod = relationship.role.compMod; + + const relationshipName = getRelationshipName(relationship); + + return ddlProvider.createForeignKey({ + name: relationshipName, + foreignKey: compMod.child.collection.fkFields, + primaryKey: compMod.parent.collection.fkFields, + customProperties: compMod.customProperties?.new, + foreignTable: compMod.child.collection.name, + foreignSchemaName: compMod.child.bucket.name, + foreignTableActivated: compMod.child.collection.isActivated, + primaryTable: compMod.parent.collection.name, + primarySchemaName: compMod.parent.bucket.name, + primaryTableActivated: compMod.parent.collection.isActivated, + isActivated: Boolean(relationship.role?.compMod?.isActivated?.new), + }); +}; + +const canRelationshipBeAdded = relationship => { + const compMod = relationship.role.compMod; + if (!compMod) { + return false; + } + return [ + getRelationshipName(relationship), + compMod.parent?.bucket, + compMod.parent?.collection, + compMod.parent?.collection?.fkFields?.length, + compMod.child?.bucket, + compMod.child?.collection, + compMod.child?.collection?.fkFields?.length, + ].every(Boolean); +}; + +const getAddForeignKeyScriptDtos = ddlProvider => addedRelationships => { + return addedRelationships + .filter(relationship => canRelationshipBeAdded(relationship)) + .map(relationship => { + const scriptDto = getAddSingleForeignKeyStatementDto(ddlProvider)(relationship); + return AlterScriptDto.getInstance([scriptDto.statement], scriptDto.isActivated, false); + }) + .filter(res => res?.scripts.some(scriptDto => Boolean(scriptDto.script))); +}; + +const getDeleteSingleForeignKeyStatementDto = ddlProvider => relationship => { + const compMod = relationship.role.compMod; + + const ddlChildEntityName = getFullChildTableName(relationship); + + const relationshipName = getRelationshipName(relationship); + const ddlRelationshipName = wrapInQuotes(relationshipName); + const statement = ddlProvider.dropForeignKey(ddlChildEntityName, ddlRelationshipName); + + const isRelationshipActivated = Boolean(relationship.role?.compMod?.isActivated?.new); + const isChildTableActivated = compMod.child.collection.isActivated; + return { + statement, + isActivated: isRelationshipActivated && isChildTableActivated, + }; +}; + +const canRelationshipBeDeleted = relationship => { + const compMod = relationship.role.compMod; + if (!compMod) { + return false; + } + return [compMod.code?.old || compMod.name?.old, compMod.child?.bucket, compMod.child?.collection].every(Boolean); +}; + +const getDeleteForeignKeyScriptDtos = ddlProvider => deletedRelationships => { + return deletedRelationships + .filter(relationship => canRelationshipBeDeleted(relationship)) + .map(relationship => { + const scriptDto = getDeleteSingleForeignKeyStatementDto(ddlProvider)(relationship); + return AlterScriptDto.getInstance([scriptDto.statement], scriptDto.isActivated, true); + }) + .filter(res => res?.scripts.some(scriptDto => Boolean(scriptDto.script))); +}; + +const getModifyForeignKeyScriptDtos = ddlProvider => modifiedRelationships => { + return modifiedRelationships + .filter(relationship => canRelationshipBeAdded(relationship) && canRelationshipBeDeleted(relationship)) + .map(relationship => { + const deleteScriptDto = getDeleteSingleForeignKeyStatementDto(ddlProvider)(relationship); + const addScriptDto = getAddSingleForeignKeyStatementDto(ddlProvider)(relationship); + const isActivated = addScriptDto.isActivated && deleteScriptDto.isActivated; + return AlterScriptDto.getDropAndRecreateInstance( + deleteScriptDto.statement, + addScriptDto.statement, + isActivated, + ); + }) + .filter(res => res?.scripts.some(scriptDto => Boolean(scriptDto.script))); +}; + +module.exports = { + getDeleteForeignKeyScriptDtos, + getModifyForeignKeyScriptDtos, + getAddForeignKeyScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js index f45bda9..da14a26 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/primaryKeyHelper.js @@ -11,11 +11,12 @@ const { } = require('../../../utils/general'); const { alterPkConstraint, dropPK } = require('../../../ddlProvider/ddlHelpers/key/constraintsHelper'); const { KEY_TYPE } = require('../../../ddlProvider/ddlHelpers/key/keyHelper'); +const { CONSTRAINT_POSTFIX } = require('../../../../constants/constants'); const amountOfColumnsInRegularPk = 1; const getDefaultConstraintName = entityName => { - return `${entityName}_pkey`; + return [entityName, CONSTRAINT_POSTFIX.primaryKey].join('_'); }; const extractOptionsForComparisonWithRegularPkOptions = (optionHolder = {}) => { diff --git a/forward_engineering/ddlProvider/ddlProvider.js b/forward_engineering/ddlProvider/ddlProvider.js index ddcceb6..56c6e36 100644 --- a/forward_engineering/ddlProvider/ddlProvider.js +++ b/forward_engineering/ddlProvider/ddlProvider.js @@ -274,6 +274,14 @@ module.exports = (baseProvider, options, app) => { }; }, + dropForeignKey(tableName, fkConstraintName) { + const templateConfig = { + tableName, + fkConstraintName, + }; + return assignTemplates(templates.dropForeignKey, templateConfig); + }, + hydrateTable({ tableData, entityData, jsonSchema }) { const detailsTab = entityData[0]; const superTableId = detailsTab.underSuperTable?.[0]?.parentTable; diff --git a/forward_engineering/ddlProvider/templates.js b/forward_engineering/ddlProvider/templates.js index 8bb07e9..3f2afbf 100644 --- a/forward_engineering/ddlProvider/templates.js +++ b/forward_engineering/ddlProvider/templates.js @@ -14,6 +14,8 @@ module.exports = { createForeignKey: 'ALTER TABLE ${foreignTable} ADD CONSTRAINT ${name} FOREIGN KEY (${foreignKey}) REFERENCES ${primaryTable} (${primaryKey})${onDelete};', + dropForeignKey: 'ALTER TABLE {$tableName} DROP FOREIGN KEY ${constraintName};', + createForeignKeyConstraint: '${name} FOREIGN KEY (${foreignKey}) REFERENCES ${primaryTable} (${primaryKey})${onDelete}', diff --git a/forward_engineering/utils/general.js b/forward_engineering/utils/general.js index 6547c5c..4ed51c3 100644 --- a/forward_engineering/utils/general.js +++ b/forward_engineering/utils/general.js @@ -81,6 +81,8 @@ const wrapInQuotes = ({ name }) => `"${name}"`; */ const wrapInSingleQuotes = ({ name }) => `'${name}'`; +const removeAllQuotes = str => str.replaceAll(/['"]/g, ''); + /** * @param {{ name: string, schemaName?: string }} * @returns {string} @@ -149,6 +151,7 @@ module.exports = { commentIfDeactivated, wrapInQuotes, wrapInSingleQuotes, + removeAllQuotes, getNamePrefixedWithSchemaName, getColumnsList, toArray, From 27671b722c8ce53288e2f1fc387b4cf8c7e4898e Mon Sep 17 00:00:00 2001 From: Alik Date: Thu, 8 Jan 2026 10:15:05 +0100 Subject: [PATCH 07/11] HCK-14214: script generation options for NOT NULL (#66)
Sub-taskHCK-14214 [DB2] Enable script generation options for Not null

## Content You have no Jira task for this PR? Describe your changes here... ... ## Technical details You feel the need to provide technical explanations? You can do it here... ... --- .../alterScript/alterScriptFromDeltaHelper.js | 7 +- .../alterScriptHelpers/alterEntityHelper.js | 41 ++++----- .../columnHelpers/nonNullConstraintHelper.js | 91 +++++++++++++++++++ forward_engineering/ddlProvider/templates.js | 4 + forward_engineering/utils/general.js | 9 +- .../field_level/fieldLevelConfig.json | 28 ------ 6 files changed, 123 insertions(+), 57 deletions(-) create mode 100644 forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index aa0d553..b08207a 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -24,12 +24,9 @@ const getAlterCollectionScriptDtos = ({ item => Object.values(item.properties)[0], ); - const modifyCollectionScriptDtos = modifyScriptsData.flatMap(getModifyCollectionScriptDtos({ dbVersion })); + const modifyCollectionScriptDtos = modifyScriptsData.flatMap(getModifyCollectionScriptDtos); const modifyCollectionKeysScriptDtos = modifyScriptsData.flatMap(getModifyCollectionKeysScriptDtos); - - const modifyColumnScriptDtos = modifyScriptsData.flatMap( - getModifyColumnScriptDtos({ app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions }), - ); + const modifyColumnScriptDtos = modifyScriptsData.flatMap(getModifyColumnScriptDtos); return [...modifyCollectionScriptDtos, ...modifyColumnScriptDtos, ...modifyCollectionKeysScriptDtos].filter( Boolean, diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js index b6eaacf..1d0724a 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -1,15 +1,14 @@ +const { getModifyNonNullColumnsScriptDtos } = require('./columnHelpers/nonNullConstraintHelper'); const { getModifyPkConstraintsScriptDtos } = require('./entityHelpers/primaryKeyHelper'); -const getModifyCollectionScriptDtos = - ({}) => - collection => { - // const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(...); - // const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(...); - return [ - // ...modifyCheckConstraintScriptDtos, - // ...modifyCommentScriptDtos, - ].filter(Boolean); - }; +const getModifyCollectionScriptDtos = collection => { + // const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(...); + // const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(...); + return [ + // ...modifyCheckConstraintScriptDtos, + // ...modifyCommentScriptDtos, + ].filter(Boolean); +}; const getModifyCollectionKeysScriptDtos = collection => { const modifyPkConstraintDtos = getModifyPkConstraintsScriptDtos(collection); @@ -20,19 +19,17 @@ const getModifyCollectionKeysScriptDtos = collection => { ].filter(Boolean); }; -const getModifyColumnScriptDtos = - ({}) => - collection => { - // const modifyNotNullScriptDtos = getModifyNonNullColumnScriptDtos(...); - // const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(...); - // const modifyDefaultColumnValueScriptDtos = getModifiedDefaultColumnValueScriptDtos(...); +const getModifyColumnScriptDtos = collection => { + const modifyNotNullScriptDtos = getModifyNonNullColumnsScriptDtos(collection); + // const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(...); + // const modifyDefaultColumnValueScriptDtos = getModifiedDefaultColumnValueScriptDtos(...); - return [ - // ...modifyNotNullScriptDtos, - // ...modifyDefaultColumnValueScriptDtos, - // ...modifyCommentScriptDtos, - ].filter(Boolean); - }; + return [ + ...modifyNotNullScriptDtos, + // ...modifyDefaultColumnValueScriptDtos, + // ...modifyCommentScriptDtos, + ].filter(Boolean); +}; module.exports = { getModifyCollectionScriptDtos, diff --git a/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js new file mode 100644 index 0000000..7ca0e1d --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js @@ -0,0 +1,91 @@ +const _ = require('lodash'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { + getFullCollectionName, + wrapInQuotes, + isObjectInDeltaModelActivated, + isParentContainerActivated, + getSchemaOfAlterCollection, +} = require('../../../utils/general'); +const { assignTemplates } = require('../../../utils/assignTemplates'); +const templates = require('../../../ddlProvider/templates'); + +/** + * @param tableName {string} + * @param columnName {string} + * @return string + * */ +const setNotNullConstraint = (tableName, columnName) => { + return assignTemplates({ + template: templates.alterNotNull, + templateData: { + tableName, + columnName, + }, + }); +}; + +/** + * @param tableName {string} + * @param columnName {string} + * @return string + * */ +const dropNotNullConstraint = (tableName, columnName) => { + return assignTemplates({ + template: templates.dropNotNull, + templateData: { + tableName, + columnName, + }, + }); +}; + +/** + * @param {Object} collection + * @return {AlterScriptDto[]} + * */ +const getModifyNonNullColumnsScriptDtos = collection => { + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isObjectInDeltaModelActivated(collection); + + const currentRequiredColumnNames = collection.required || []; + const previousRequiredColumnNames = collection.role.required || []; + + const columnNamesToAddNotNullConstraint = _.difference(currentRequiredColumnNames, previousRequiredColumnNames); + const columnNamesToRemoveNotNullConstraint = _.difference(previousRequiredColumnNames, currentRequiredColumnNames); + + const addNotNullConstraintsScript = _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + const oldName = jsonSchema.compMod.oldField.name; + const shouldRemoveForOldName = columnNamesToRemoveNotNullConstraint.includes(oldName); + const shouldAddForNewName = columnNamesToAddNotNullConstraint.includes(name); + return shouldAddForNewName && !shouldRemoveForOldName; + }) + .map(([name, jsonSchema]) => { + const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; + return { script: setNotNullConstraint(fullTableName, wrapInQuotes({ name })), isActivated }; + }) + .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, false)); + + const removeNotNullConstraint = _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + const oldName = jsonSchema.compMod.oldField.name; + const shouldRemoveForOldName = columnNamesToRemoveNotNullConstraint.includes(oldName); + const shouldAddForNewName = columnNamesToAddNotNullConstraint.includes(name); + return shouldRemoveForOldName && !shouldAddForNewName; + }) + .map(([name, jsonSchema]) => { + const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; + return { script: dropNotNullConstraint(fullTableName, wrapInQuotes({ name })), isActivated }; + }) + .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, true)); + + return [...addNotNullConstraintsScript, ...removeNotNullConstraint]; +}; + +module.exports = { + getModifyNonNullColumnsScriptDtos, +}; diff --git a/forward_engineering/ddlProvider/templates.js b/forward_engineering/ddlProvider/templates.js index 3f2afbf..3c91b5e 100644 --- a/forward_engineering/ddlProvider/templates.js +++ b/forward_engineering/ddlProvider/templates.js @@ -32,4 +32,8 @@ module.exports = { alterPkConstraint: 'ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} PRIMARY KEY${columns}${options};', dropPK: 'ALTER TABLE ${tableName} DROP PRIMARY KEY;', + + alterNotNull: 'ALTER TABLE ${tableName} ALTER COLUMN ${columnName} SET NOT NULL;', + + dropNotNull: 'ALTER TABLE ${tableName} ALTER COLUMN ${columnName} DROP NOT NULL;', }; diff --git a/forward_engineering/utils/general.js b/forward_engineering/utils/general.js index 4ed51c3..76a84d9 100644 --- a/forward_engineering/utils/general.js +++ b/forward_engineering/utils/general.js @@ -119,12 +119,16 @@ const getColumnsList = (columns, isAllColumnsDeactivated, isParentActivated, map const toArray = ({ value }) => (Array.isArray(value) ? value : [value]); const getEntityName = entityData => { - return (entityData && (entityData.code || entityData.collectionName)) || ''; + return entityData?.code || entityData?.collectionName || ''; +}; + +const getSchemaNameFromCollection = ({ collection }) => { + return collection.compMod?.keyspaceName; }; const getFullCollectionName = collectionSchema => { const name = getEntityName(collectionSchema); - const schemaName = collectionSchema.compMod?.keyspaceName; + const schemaName = getSchemaNameFromCollection({ collection: collectionSchema }); return getNamePrefixedWithSchemaName({ name, schemaName }); }; @@ -160,4 +164,5 @@ module.exports = { getSchemaOfAlterCollection, isObjectInDeltaModelActivated, isParentContainerActivated, + getSchemaNameFromCollection, }; diff --git a/properties_pane/field_level/fieldLevelConfig.json b/properties_pane/field_level/fieldLevelConfig.json index 576426f..dd41df5 100644 --- a/properties_pane/field_level/fieldLevelConfig.json +++ b/properties_pane/field_level/fieldLevelConfig.json @@ -453,20 +453,6 @@ making sure that you maintain a proper JSON format. }, "defaultValue": false }, - { - "propertyName": "Not null constraint name", - "propertyKeyword": "notNullConstraintName", - "propertyType": "text", - "dependency": { - "type": "and", - "values": [ - { - "key": "required", - "value": true - } - ] - } - }, { "propertyName": "Primary key", "propertyKeyword": "compositePrimaryKey", @@ -2949,20 +2935,6 @@ making sure that you maintain a proper JSON format. }, "defaultValue": false }, - { - "propertyName": "Not null constraint name", - "propertyKeyword": "notNullConstraintName", - "propertyType": "text", - "dependency": { - "type": "and", - "values": [ - { - "key": "required", - "value": true - } - ] - } - }, "minItems", "maxItems", "pattern", From ec3f0ad441c1c90d26a9980ffe918068425c6430 Mon Sep 17 00:00:00 2001 From: Alik Date: Thu, 8 Jan 2026 12:41:42 +0100 Subject: [PATCH 08/11] HCK-14213: Enable script generation options for UK (#67)
Sub-taskHCK-14213 [DB2] Enable script generation options for UK

## Technical details Note: UK requires a column to be NOT NULL. --- .../alterScript/alterScriptFromDeltaHelper.js | 11 +- .../alterScriptHelpers/alterEntityHelper.js | 8 +- .../alterForeignKeyHelper.js | 33 +- .../entityHelpers/uniqueKeyHelper.js | 473 ++++++++++++++++++ .../ddlHelpers/key/constraintsHelper.js | 48 +- .../ddlProvider/ddlProvider.js | 8 - forward_engineering/ddlProvider/templates.js | 4 + .../field_level/fieldLevelConfig.json | 204 +++++++- 8 files changed, 727 insertions(+), 62 deletions(-) create mode 100644 forward_engineering/alterScript/alterScriptHelpers/entityHelpers/uniqueKeyHelper.js diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index b08207a..ebca672 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -15,7 +15,6 @@ const getItems = data => [data?.items].flat().filter(Boolean); const getAlterCollectionScriptDtos = ({ collection, app, - dbVersion, modelDefinitions, internalDefinitions, externalDefinitions, @@ -43,8 +42,6 @@ const getAlterViewScriptDtos = (collection, app) => { }; const getAlterRelationshipsScriptDtos = ({ collection, app, ignoreRelationshipIDs = [] }) => { - const ddlProvider = require('../ddlProvider/ddlProvider')(null, null, app); - const addedRelationships = getItems(collection.properties?.relationships?.properties?.added) .filter(Boolean) .map(item => Object.values(item.properties)[0]) @@ -69,9 +66,9 @@ const getAlterRelationshipsScriptDtos = ({ collection, app, ignoreRelationshipID relationship?.role?.compMod?.modified && !ignoreRelationshipIDs.includes(relationship?.role?.id), ); - const deleteFkScriptDtos = getDeleteForeignKeyScriptDtos(ddlProvider)(deletedRelationships); - const addFkScriptDtos = getAddForeignKeyScriptDtos(ddlProvider)(addedRelationships); - const modifiedFkScriptDtos = getModifyForeignKeyScriptDtos(ddlProvider)(modifiedRelationships); + const deleteFkScriptDtos = getDeleteForeignKeyScriptDtos(deletedRelationships); + const addFkScriptDtos = getAddForeignKeyScriptDtos(addedRelationships); + const modifiedFkScriptDtos = getModifyForeignKeyScriptDtos(modifiedRelationships); return [...deleteFkScriptDtos, ...addFkScriptDtos, ...modifiedFkScriptDtos].filter(Boolean); }; @@ -126,7 +123,6 @@ const getAlterScriptDtos = (data, app) => { const modelDefinitions = JSON.parse(data.modelDefinitions); const internalDefinitions = JSON.parse(data.internalDefinitions); const externalDefinitions = JSON.parse(data.externalDefinitions); - const dbVersion = data.modelData[0]?.dbVersion; const inlineDeltaRelationships = getInlineRelationships({ collection, options: data.options }); const ignoreRelationshipIDs = inlineDeltaRelationships.map(relationship => relationship.role.id); @@ -134,7 +130,6 @@ const getAlterScriptDtos = (data, app) => { const collectionsScriptDtos = getAlterCollectionScriptDtos({ collection, app, - dbVersion, modelDefinitions, internalDefinitions, externalDefinitions, diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js index 1d0724a..2b8694f 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -1,5 +1,6 @@ const { getModifyNonNullColumnsScriptDtos } = require('./columnHelpers/nonNullConstraintHelper'); const { getModifyPkConstraintsScriptDtos } = require('./entityHelpers/primaryKeyHelper'); +const { getModifyUkConstraintsScriptDtos } = require('./entityHelpers/uniqueKeyHelper'); const getModifyCollectionScriptDtos = collection => { // const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(...); @@ -12,11 +13,8 @@ const getModifyCollectionScriptDtos = collection => { const getModifyCollectionKeysScriptDtos = collection => { const modifyPkConstraintDtos = getModifyPkConstraintsScriptDtos(collection); - // const modifyUkConstraintDtos = getModifyUkConstraintsScriptDtos(...); - return [ - ...modifyPkConstraintDtos, - // ...modifyUniqueKeyConstraintDtos, - ].filter(Boolean); + const modifyUkConstraintDtos = getModifyUkConstraintsScriptDtos(collection); + return [...modifyPkConstraintDtos, ...modifyUkConstraintDtos].filter(Boolean); }; const getModifyColumnScriptDtos = collection => { diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js index fa1fedb..d201455 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterForeignKeyHelper.js @@ -2,6 +2,8 @@ const _ = require('lodash'); const { AlterScriptDto } = require('../types/AlterScriptDto'); const { getNamePrefixedWithSchemaName, wrapInQuotes, removeAllQuotes } = require('../../utils/general'); const { CONSTRAINT_POSTFIX } = require('../../../constants/constants'); +const templates = require('../../ddlProvider/templates'); +const { assignTemplates } = require('../../utils/assignTemplates'); const getRelationshipName = relationship => { const compMod = relationship.role.compMod; @@ -17,10 +19,11 @@ const getFullChildTableName = relationship => { return getNamePrefixedWithSchemaName({ name: childEntityName, schemaName: childBucketName }); }; -const getAddSingleForeignKeyStatementDto = ddlProvider => relationship => { +const getAddSingleForeignKeyStatementDto = relationship => { const compMod = relationship.role.compMod; const relationshipName = getRelationshipName(relationship); + const ddlProvider = require('../../ddlProvider/ddlProvider')(); return ddlProvider.createForeignKey({ name: relationshipName, @@ -53,24 +56,30 @@ const canRelationshipBeAdded = relationship => { ].every(Boolean); }; -const getAddForeignKeyScriptDtos = ddlProvider => addedRelationships => { +const getAddForeignKeyScriptDtos = addedRelationships => { return addedRelationships .filter(relationship => canRelationshipBeAdded(relationship)) .map(relationship => { - const scriptDto = getAddSingleForeignKeyStatementDto(ddlProvider)(relationship); + const scriptDto = getAddSingleForeignKeyStatementDto(relationship); return AlterScriptDto.getInstance([scriptDto.statement], scriptDto.isActivated, false); }) .filter(res => res?.scripts.some(scriptDto => Boolean(scriptDto.script))); }; -const getDeleteSingleForeignKeyStatementDto = ddlProvider => relationship => { +const getDeleteSingleForeignKeyStatementDto = relationship => { const compMod = relationship.role.compMod; - const ddlChildEntityName = getFullChildTableName(relationship); + const tableName = getFullChildTableName(relationship); const relationshipName = getRelationshipName(relationship); - const ddlRelationshipName = wrapInQuotes(relationshipName); - const statement = ddlProvider.dropForeignKey(ddlChildEntityName, ddlRelationshipName); + const fkConstraintName = wrapInQuotes(relationshipName); + const statement = assignTemplates({ + template: templates.dropForeignKey, + templateData: { + tableName, + fkConstraintName, + }, + }); const isRelationshipActivated = Boolean(relationship.role?.compMod?.isActivated?.new); const isChildTableActivated = compMod.child.collection.isActivated; @@ -88,22 +97,22 @@ const canRelationshipBeDeleted = relationship => { return [compMod.code?.old || compMod.name?.old, compMod.child?.bucket, compMod.child?.collection].every(Boolean); }; -const getDeleteForeignKeyScriptDtos = ddlProvider => deletedRelationships => { +const getDeleteForeignKeyScriptDtos = deletedRelationships => { return deletedRelationships .filter(relationship => canRelationshipBeDeleted(relationship)) .map(relationship => { - const scriptDto = getDeleteSingleForeignKeyStatementDto(ddlProvider)(relationship); + const scriptDto = getDeleteSingleForeignKeyStatementDto(relationship); return AlterScriptDto.getInstance([scriptDto.statement], scriptDto.isActivated, true); }) .filter(res => res?.scripts.some(scriptDto => Boolean(scriptDto.script))); }; -const getModifyForeignKeyScriptDtos = ddlProvider => modifiedRelationships => { +const getModifyForeignKeyScriptDtos = modifiedRelationships => { return modifiedRelationships .filter(relationship => canRelationshipBeAdded(relationship) && canRelationshipBeDeleted(relationship)) .map(relationship => { - const deleteScriptDto = getDeleteSingleForeignKeyStatementDto(ddlProvider)(relationship); - const addScriptDto = getAddSingleForeignKeyStatementDto(ddlProvider)(relationship); + const deleteScriptDto = getDeleteSingleForeignKeyStatementDto(relationship); + const addScriptDto = getAddSingleForeignKeyStatementDto(relationship); const isActivated = addScriptDto.isActivated && deleteScriptDto.isActivated; return AlterScriptDto.getDropAndRecreateInstance( deleteScriptDto.statement, diff --git a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/uniqueKeyHelper.js b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/uniqueKeyHelper.js new file mode 100644 index 0000000..92b35d0 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/uniqueKeyHelper.js @@ -0,0 +1,473 @@ +const _ = require('lodash'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { UniqueKeyTransitionDto, KeyScriptModificationDto } = require('../../types/AlterKeyDto'); +const { alterUkConstraint, dropUkConstraint } = require('../../../ddlProvider/ddlHelpers/key/constraintsHelper'); +const { + getFullCollectionName, + getSchemaOfAlterCollection, + getEntityName, + wrapInQuotes, + isParentContainerActivated, + isObjectInDeltaModelActivated, +} = require('../../../utils/general'); +const { CONSTRAINT_POSTFIX } = require('../../../../constants/constants'); +const { KEY_TYPE } = require('../../../ddlProvider/ddlHelpers/key/keyHelper'); + +const amountOfColumnsInRegularUniqueKey = 1; + +const getDefaultConstraintName = entityName => { + return [entityName, CONSTRAINT_POSTFIX.uniqueKey].join('_'); +}; + +const extractOptionsForComparisonWithRegularUniqueKeyOptions = optionHolder => { + return { + constraintName: optionHolder.constraintName, + deferClause: optionHolder.deferClause, + exceptionClause: optionHolder.exceptionClause, + id: optionHolder.id, + indexClause: optionHolder.indexClause, + rely: optionHolder.rely, + validate: optionHolder.validate, + }; +}; + +const getCustomPropertiesOfRegularUniqueKeyForComparisonWithRegularUniqueKeyOptions = columnJsonSchema => { + return extractOptionsForComparisonWithRegularUniqueKeyOptions(columnJsonSchema.uniqueKeyOptions); +}; + +const getCustomPropertiesOfCompositeUniqueKeyForComparisonWithRegularUniqueKeyOptions = compositeUniqueKey => { + const optionsForComparison = extractOptionsForComparisonWithRegularUniqueKeyOptions(compositeUniqueKey); + return [optionsForComparison].filter(o => Object.values(o).some(Boolean)); +}; + +const wasCompositeUniqueKeyChangedInTransitionFromCompositeToRegular = collection => { + const uniqueDto = collection?.role?.compMod?.uniqueKey || {}; + const oldUniqueKeys = uniqueDto.old || []; + const idsOfColumns = oldUniqueKeys.flatMap(unique => unique.compositeUniqueKey?.map(dto => dto.keyId) || []); + if (idsOfColumns.length !== amountOfColumnsInRegularUniqueKey) { + // We return false, because it wouldn't count as transition between regular UniqueKey and composite UniqueKey + // if composite UniqueKey did not constraint exactly 1 column + return UniqueKeyTransitionDto.noTransition(); + } + const idOfUniqueKeyColumn = idsOfColumns[0]; + const newColumnJsonSchema = Object.values(collection.properties).find( + columnJsonSchema => columnJsonSchema.GUID === idOfUniqueKeyColumn, + ); + if (!newColumnJsonSchema) { + return UniqueKeyTransitionDto.noTransition(); + } + const isNewColumnARegularUniqueKey = newColumnJsonSchema?.unique && !newColumnJsonSchema?.compositeUniqueKey; + if (!isNewColumnARegularUniqueKey) { + return UniqueKeyTransitionDto.noTransition(); + } + const constraintOptions = + getCustomPropertiesOfRegularUniqueKeyForComparisonWithRegularUniqueKeyOptions(newColumnJsonSchema); + const areOptionsEqual = oldUniqueKeys.some(compositeUniqueKey => { + if (compositeUniqueKey.compositeUniqueKey?.length !== amountOfColumnsInRegularUniqueKey) { + return false; + } + const oldCompositeUniqueKeyAsRegularUniqueKeyOptions = + getCustomPropertiesOfCompositeUniqueKeyForComparisonWithRegularUniqueKeyOptions(compositeUniqueKey); + + return _.isEqual(oldCompositeUniqueKeyAsRegularUniqueKeyOptions, constraintOptions); + }); + + return UniqueKeyTransitionDto.transition(!areOptionsEqual); +}; + +const wasCompositeUniqueKeyChangedInTransitionFromRegularToComposite = collection => { + const uniqueDto = collection?.role?.compMod?.uniqueKey || {}; + const newUniqueKeys = uniqueDto.new || []; + const idsOfColumns = newUniqueKeys.flatMap(unique => unique.compositeUniqueKey?.map(dto => dto.keyId) || []); + if (idsOfColumns.length !== amountOfColumnsInRegularUniqueKey) { + // We return false, because it wouldn't count as transition between regular UniqueKey and composite UniqueKey + // if composite UniqueKey does not constraint exactly 1 column + return UniqueKeyTransitionDto.noTransition(); + } + const idOfUniqueKeyColumn = idsOfColumns[0]; + const oldColumnJsonSchema = Object.values(collection.role.properties).find( + columnJsonSchema => columnJsonSchema.GUID === idOfUniqueKeyColumn, + ); + if (!oldColumnJsonSchema) { + return UniqueKeyTransitionDto.noTransition(); + } + const isOldColumnARegularUniqueKey = oldColumnJsonSchema?.unique && !oldColumnJsonSchema?.compositeUniqueKey; + if (!isOldColumnARegularUniqueKey) { + return UniqueKeyTransitionDto.noTransition(); + } + const constraintOptions = + getCustomPropertiesOfRegularUniqueKeyForComparisonWithRegularUniqueKeyOptions(oldColumnJsonSchema); + const areOptionsEqual = newUniqueKeys.some(compositeUniqueKey => { + if (compositeUniqueKey.compositeUniqueKey?.length !== amountOfColumnsInRegularUniqueKey) { + return false; + } + const oldCompositeUniqueKeyAsRegularUniqueKeyOptions = + getCustomPropertiesOfCompositeUniqueKeyForComparisonWithRegularUniqueKeyOptions(compositeUniqueKey); + + return _.isEqual(oldCompositeUniqueKeyAsRegularUniqueKeyOptions, constraintOptions); + }); + + return UniqueKeyTransitionDto.transition(!areOptionsEqual); +}; + +const getConstraintNameForCompositeUniqueKey = (uniqueKey, entityName) => { + if (uniqueKey.constraintName) { + return uniqueKey.constraintName; + } + return getDefaultConstraintName(entityName); +}; + +const getCreateCompositeUniqueKeyDDLProviderConfig = (uniqueKey, entityName, entity) => { + const constraintName = getConstraintNameForCompositeUniqueKey(uniqueKey, entityName); + const pkColumns = _.toPairs(entity.role.properties) + .filter(([name, jsonSchema]) => + Boolean(uniqueKey.compositeUniqueKey?.find(keyDto => keyDto.keyId === jsonSchema.GUID)), + ) + .map(([name, jsonSchema]) => ({ + name, + isActivated: jsonSchema.isActivated, + })); + + return { + keyType: KEY_TYPE.uniqueKey, + name: constraintName, + columns: pkColumns, + }; +}; + +const getAddCompositeUniqueKeyScriptDtos = collection => { + const uniqueDto = collection?.role?.compMod?.uniqueKey || {}; + const newUniqueKeys = uniqueDto.new || []; + const oldUniqueKeys = uniqueDto.old || []; + if (newUniqueKeys.length === 0 && oldUniqueKeys.length === 0) { + return []; + } + const transitionToCompositeDto = wasCompositeUniqueKeyChangedInTransitionFromRegularToComposite(collection); + if (transitionToCompositeDto.didTransitionHappen && !transitionToCompositeDto.wasUniqueKeyChangedInTransition) { + return []; + } + if (newUniqueKeys.length === oldUniqueKeys.length) { + const areKeyArraysEqual = _(oldUniqueKeys).differenceWith(newUniqueKeys, _.isEqual).isEmpty(); + if (areKeyArraysEqual) { + return []; + } + } + + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + const entityName = getEntityName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return newUniqueKeys + .map(newUniqueKey => { + const ddlConfig = getCreateCompositeUniqueKeyDDLProviderConfig(newUniqueKey, entityName, collection); + if (_.isEmpty(ddlConfig.columns)) { + return null; + } + const statementDto = alterUkConstraint(fullTableName, isCollectionActivated, ddlConfig); + return new KeyScriptModificationDto(statementDto.statement, fullTableName, false, statementDto.isActivated); + }) + .filter(scriptDto => Boolean(scriptDto?.script)); +}; + +const getDropCompositeUniqueKeyScriptDtos = collection => { + const uniqueDto = collection?.role?.compMod?.uniqueKey || {}; + const newUniqueKeys = uniqueDto.new || []; + const oldUniqueKeys = uniqueDto.old || []; + if (newUniqueKeys.length === 0 && oldUniqueKeys.length === 0) { + return []; + } + const transitionToCompositeDto = wasCompositeUniqueKeyChangedInTransitionFromCompositeToRegular(collection); + if (transitionToCompositeDto.didTransitionHappen && !transitionToCompositeDto.wasUniqueKeyChangedInTransition) { + return []; + } + if (newUniqueKeys.length === oldUniqueKeys.length) { + const areKeyArraysEqual = _(oldUniqueKeys).differenceWith(newUniqueKeys, _.isEqual).isEmpty(); + if (areKeyArraysEqual) { + return []; + } + } + + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + const entityName = getEntityName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return oldUniqueKeys + .map(oldUniqueKey => { + let constraintName = getDefaultConstraintName(entityName); + if (oldUniqueKey.constraintName) { + constraintName = oldUniqueKey.constraintName; + } + const ddlConstraintName = wrapInQuotes(constraintName); + const script = dropUkConstraint(fullTableName, ddlConstraintName); + return new KeyScriptModificationDto(script, fullTableName, true, isCollectionActivated); + }) + .filter(scriptDto => Boolean(scriptDto.script)); +}; + +const getModifyCompositeUniqueKeyScriptDtos = collection => { + const dropCompositeUniqueKeyScriptDtos = getDropCompositeUniqueKeyScriptDtos(collection); + const addCompositeUniqueKeyScriptDtos = getAddCompositeUniqueKeyScriptDtos(collection); + + return [...dropCompositeUniqueKeyScriptDtos, ...addCompositeUniqueKeyScriptDtos].filter(Boolean); +}; + +const getConstraintNameForRegularUniqueKey = (columnJsonSchema, entityName) => { + const constraintOptions = columnJsonSchema.uniqueKeyOptions; + if (constraintOptions?.constraintName?.trim()) { + return constraintOptions.constraintName; + } + return getDefaultConstraintName(entityName); +}; + +const getCreateRegularUniqueKeyDDLProviderConfig = (columnName, columnJsonSchema, entityName, entity) => { + const constraintName = getConstraintNameForRegularUniqueKey(columnJsonSchema, entityName); + const ukColumns = [ + { + name: columnName, + isActivated: columnJsonSchema.isActivated, + }, + ]; + + return { + keyType: KEY_TYPE.uniqueKey, + name: constraintName, + columns: ukColumns, + options: columnJsonSchema.uniqueKeyOptions, + }; +}; + +const wasFieldChangedToBeARegularUniqueKey = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldColumnJsonSchema = collection.role.properties[oldName]; + + const isRegularUniqueKey = columnJsonSchema.unique && !columnJsonSchema.compositeUniqueKey; + const wasTheFieldAnyUniqueKey = oldColumnJsonSchema?.unique || oldColumnJsonSchema.compositeUniqueKey; + + return isRegularUniqueKey && !wasTheFieldAnyUniqueKey; +}; + +const wasRegularUniqueKeyChangedInTransitionFromCompositeToRegular = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldColumnJsonSchema = collection.role.properties[oldName]; + + const isRegularUniqueKey = columnJsonSchema.unique && !columnJsonSchema.compositeUniqueKey; + const wasTheFieldAnyUniqueKey = oldColumnJsonSchema?.unique || oldColumnJsonSchema.compositeUniqueKey; + + if (!(isRegularUniqueKey && wasTheFieldAnyUniqueKey)) { + return UniqueKeyTransitionDto.noTransition(); + } + + const uniqueDto = collection?.role?.compMod?.uniqueKey || {}; + const newUniqueKeys = uniqueDto.new || []; + + const oldUniqueKeys = uniqueDto.old || []; + const wasTheFieldACompositeUniqueKey = oldUniqueKeys.some(compUniqueKey => + compUniqueKey.compositeUniqueKey?.some(unique => unique.keyId === oldColumnJsonSchema.GUID), + ); + const isTheFieldACompositeUniqueKey = newUniqueKeys.some(compUniqueKey => + compUniqueKey.compositeUniqueKey?.some(unique => unique.keyId === columnJsonSchema.GUID), + ); + + const wasCompositeUniqueKeyRemoved = wasTheFieldACompositeUniqueKey && !isTheFieldACompositeUniqueKey; + + if (isRegularUniqueKey && wasCompositeUniqueKeyRemoved) { + // return compare custom properties and amount of columns. + // If there was a transition and amount of composite UniqueKey columns is not equal + // to amount of regular unique columns, we must recreate UniqueKey + const constraintOptions = + getCustomPropertiesOfRegularUniqueKeyForComparisonWithRegularUniqueKeyOptions(columnJsonSchema); + const areOptionsEqual = oldUniqueKeys.some(oldCompositeUniqueKey => { + if (oldCompositeUniqueKey.compositeUniqueKey?.length !== amountOfColumnsInRegularUniqueKey) { + return false; + } + const oldCompositeUniqueKeyAsRegularUniqueKeyOptions = + getCustomPropertiesOfCompositeUniqueKeyForComparisonWithRegularUniqueKeyOptions(oldCompositeUniqueKey); + + return _.isEqual(oldCompositeUniqueKeyAsRegularUniqueKeyOptions, constraintOptions); + }); + return UniqueKeyTransitionDto.transition(!areOptionsEqual); + } + + return UniqueKeyTransitionDto.noTransition(); +}; + +const wasRegularUniqueKeyChangedInTransitionFromRegularToComposite = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldColumnJsonSchema = collection.role.properties[oldName]; + + const wasRegularUniqueKey = oldColumnJsonSchema.unique && !oldColumnJsonSchema.compositeUniqueKey; + const isTheFieldAnyUniqueKey = Boolean(columnJsonSchema?.unique); + + if (!(wasRegularUniqueKey && isTheFieldAnyUniqueKey)) { + return UniqueKeyTransitionDto.noTransition(); + } + + const uniqueDto = collection?.role?.compMod?.uniqueKey || {}; + const newUniqueKeys = uniqueDto.new || []; + + const oldUniqueKeys = uniqueDto.old || []; + const wasTheFieldACompositeUniqueKey = oldUniqueKeys.some(compUniqueKey => + compUniqueKey.compositeUniqueKey?.some(unique => unique.keyId === oldColumnJsonSchema.GUID), + ); + const isTheFieldACompositeUniqueKey = newUniqueKeys.some(compUniqueKey => + compUniqueKey.compositeUniqueKey?.some(unique => unique.keyId === columnJsonSchema.GUID), + ); + + const wasCompositeUniqueKeyAdded = isTheFieldACompositeUniqueKey && !wasTheFieldACompositeUniqueKey; + + if (wasRegularUniqueKey && wasCompositeUniqueKeyAdded) { + // return compare custom properties and amount of columns. + // If there was a transition and amount of composite UniqueKey columns is not equal + // to amount of regular unique columns, we must recreate UniqueKey + const constraintOptions = + getCustomPropertiesOfRegularUniqueKeyForComparisonWithRegularUniqueKeyOptions(oldColumnJsonSchema); + const areOptionsEqual = newUniqueKeys.some(oldCompositeUniqueKey => { + if (oldCompositeUniqueKey.compositeUniqueKey?.length !== amountOfColumnsInRegularUniqueKey) { + return false; + } + const oldCompositeUniqueKeyAsRegularUniqueKeyOptions = + getCustomPropertiesOfCompositeUniqueKeyForComparisonWithRegularUniqueKeyOptions(oldCompositeUniqueKey); + + return _.isEqual(oldCompositeUniqueKeyAsRegularUniqueKeyOptions, constraintOptions); + }); + + return UniqueKeyTransitionDto.transition(!areOptionsEqual); + } + + return UniqueKeyTransitionDto.noTransition(); +}; + +const isFieldNoLongerARegularUniqueKey = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + + const oldJsonSchema = collection.role.properties[oldName]; + const wasTheFieldARegularUniqueKey = oldJsonSchema?.unique && !oldJsonSchema?.compositeUniqueKey; + + const isNotAnyUniqueKey = !columnJsonSchema.unique && !columnJsonSchema.compositeUniqueKey; + return wasTheFieldARegularUniqueKey && isNotAnyUniqueKey; +}; + +const wasRegularUniqueKeyModified = (columnJsonSchema, collection) => { + const oldName = columnJsonSchema.compMod.oldField.name; + const oldJsonSchema = collection.role.properties[oldName] || {}; + + const isRegularUniqueKey = columnJsonSchema.unique && !columnJsonSchema.compositeUniqueKey; + const wasTheFieldARegularUniqueKey = oldJsonSchema?.unique && !oldJsonSchema?.compositeUniqueKey; + + if (!(isRegularUniqueKey && wasTheFieldARegularUniqueKey)) { + return false; + } + const constraintOptions = + getCustomPropertiesOfRegularUniqueKeyForComparisonWithRegularUniqueKeyOptions(columnJsonSchema); + const oldConstraintOptions = + getCustomPropertiesOfRegularUniqueKeyForComparisonWithRegularUniqueKeyOptions(oldJsonSchema); + + return !_.isEqual(oldConstraintOptions, constraintOptions); +}; + +const getAddUniqueKeyScriptDtos = collection => { + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + const entityName = getEntityName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + if (wasFieldChangedToBeARegularUniqueKey(jsonSchema, collection)) { + return true; + } + const transitionToRegularDto = wasRegularUniqueKeyChangedInTransitionFromCompositeToRegular( + jsonSchema, + collection, + ); + if (transitionToRegularDto.didTransitionHappen) { + return transitionToRegularDto.wasUniqueKeyChangedInTransition; + } + return wasRegularUniqueKeyModified(jsonSchema, collection); + }) + .map(([name, jsonSchema]) => { + const ddlConfig = getCreateRegularUniqueKeyDDLProviderConfig(name, jsonSchema, entityName, collection); + const statementDto = alterUkConstraint(fullTableName, isCollectionActivated, ddlConfig); + return new KeyScriptModificationDto(statementDto.statement, fullTableName, false, statementDto.isActivated); + }) + .filter(scriptDto => Boolean(scriptDto.script)); +}; + +const getDropUniqueKeyScriptDto = collection => { + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + const entityName = getEntityName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + return _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + if (isFieldNoLongerARegularUniqueKey(jsonSchema, collection)) { + return true; + } + const transitionToRegularDto = wasRegularUniqueKeyChangedInTransitionFromRegularToComposite( + jsonSchema, + collection, + ); + if (transitionToRegularDto.didTransitionHappen) { + return transitionToRegularDto.wasUniqueKeyChangedInTransition; + } + return wasRegularUniqueKeyModified(jsonSchema, collection); + }) + .map(([name, jsonSchema]) => { + const oldName = jsonSchema.compMod.oldField.name; + const oldJsonSchema = collection.role.properties[oldName]; + const ddlConstraintName = wrapInQuotes(getConstraintNameForRegularUniqueKey(oldJsonSchema, entityName)); + + const script = dropUkConstraint(fullTableName, ddlConstraintName); + return new KeyScriptModificationDto(script, fullTableName, true, isCollectionActivated); + }) + .filter(scriptDto => Boolean(scriptDto.script)); +}; + +const getModifyUniqueKeyScriptDtos = collection => { + const dropUniqueKeyScriptDtos = getDropUniqueKeyScriptDto(collection); + const addUniqueKeyScriptDtos = getAddUniqueKeyScriptDtos(collection); + + return [...dropUniqueKeyScriptDtos, ...addUniqueKeyScriptDtos].filter(Boolean); +}; + +const sortModifyUniqueKeyConstraints = constraintDtos => { + return constraintDtos.sort((c1, c2) => { + if (c1.fullTableName === c2.fullTableName) { + // Number(true) = 1, Number(false) = 0; + // This ensures that DROP script appears before CREATE script + // if the same table has 2 scripts that drop and recreate UniqueKey + return Number(c2.isDropScript) - Number(c1.isDropScript); + } + // This sorts all statements based on full table name, ASC + return c1.fullTableName.localeCompare(c2.fullTableName); + }); +}; + +const getModifyUkConstraintsScriptDtos = collection => { + const modifyCompositeUniqueKeyScriptDtos = getModifyCompositeUniqueKeyScriptDtos(collection); + const modifyUniqueKeyScriptDtos = getModifyUniqueKeyScriptDtos(collection); + + const allDtos = [...modifyCompositeUniqueKeyScriptDtos, ...modifyUniqueKeyScriptDtos]; + const sortedAllDtos = sortModifyUniqueKeyConstraints(allDtos); + + return sortedAllDtos + .map(dto => { + return AlterScriptDto.getInstance([dto.script], dto.isActivated, dto.isDropScript); + }) + .filter(Boolean); +}; + +module.exports = { + getModifyUkConstraintsScriptDtos, +}; diff --git a/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js b/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js index 9236da9..32f4864 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js +++ b/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js @@ -8,7 +8,7 @@ const { const { assignTemplates } = require('../../../utils/assignTemplates'); const templates = require('../../templates'); -const alterPkConstraint = (tableName, isParentActivated, keyData) => { +const getKeyOptions = (keyData, isParentActivated) => { const constraintName = wrapInQuotes({ name: keyData.name.trim() }); const isAllColumnsDeactivated = checkAllKeysDeactivated(keyData.columns || []); const columns = _.isEmpty(keyData.columns) @@ -21,17 +21,26 @@ const alterPkConstraint = (tableName, isParentActivated, keyData) => { .map(option => ` ${option}`) .join(''); + return { + constraintName, + columns, + options, + isActivated: !isAllColumnsDeactivated && isParentActivated, + }; +}; + +const alterPkConstraint = (tableName, isParentActivated, keyData) => { + const { isActivated, ...templateData } = getKeyOptions(keyData, isParentActivated); + return { statement: assignTemplates({ template: templates.alterPkConstraint, templateData: { tableName, - constraintName, - columns, - options, + ...templateData, }, }), - isActivated: !isAllColumnsDeactivated && isParentActivated, + isActivated, }; }; @@ -40,7 +49,36 @@ const dropPK = tableName => { return assignTemplates(templates.dropPK, templatesConfig); }; +const alterUkConstraint = (tableName, isParentActivated, keyData) => { + const { isActivated, ...templateData } = getKeyOptions(keyData, isParentActivated); + + return { + statement: assignTemplates({ + template: templates.alterUkConstraint, + templateData: { + tableName, + ...templateData, + }, + }), + isActivated, + }; +}; + +/** + * @param tableName {string} + * @param constraintName {string} + * */ +const dropUkConstraint = (tableName, constraintName) => { + const templatesConfig = { + tableName, + constraintName, + }; + return assignTemplates(templates.dropUkConstraint, templatesConfig); +}; + module.exports = { alterPkConstraint, dropPK, + alterUkConstraint, + dropUkConstraint, }; diff --git a/forward_engineering/ddlProvider/ddlProvider.js b/forward_engineering/ddlProvider/ddlProvider.js index 56c6e36..ddcceb6 100644 --- a/forward_engineering/ddlProvider/ddlProvider.js +++ b/forward_engineering/ddlProvider/ddlProvider.js @@ -274,14 +274,6 @@ module.exports = (baseProvider, options, app) => { }; }, - dropForeignKey(tableName, fkConstraintName) { - const templateConfig = { - tableName, - fkConstraintName, - }; - return assignTemplates(templates.dropForeignKey, templateConfig); - }, - hydrateTable({ tableData, entityData, jsonSchema }) { const detailsTab = entityData[0]; const superTableId = detailsTab.underSuperTable?.[0]?.parentTable; diff --git a/forward_engineering/ddlProvider/templates.js b/forward_engineering/ddlProvider/templates.js index 3c91b5e..856802f 100644 --- a/forward_engineering/ddlProvider/templates.js +++ b/forward_engineering/ddlProvider/templates.js @@ -36,4 +36,8 @@ module.exports = { alterNotNull: 'ALTER TABLE ${tableName} ALTER COLUMN ${columnName} SET NOT NULL;', dropNotNull: 'ALTER TABLE ${tableName} ALTER COLUMN ${columnName} DROP NOT NULL;', + + alterUkConstraint: 'ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} UNIQUE${columns}${options};', + + dropUkConstraint: 'ALTER TABLE ${tableName} DROP UNIQUE ${constraintName};', }; diff --git a/properties_pane/field_level/fieldLevelConfig.json b/properties_pane/field_level/fieldLevelConfig.json index dd41df5..44f3c15 100644 --- a/properties_pane/field_level/fieldLevelConfig.json +++ b/properties_pane/field_level/fieldLevelConfig.json @@ -433,8 +433,21 @@ making sure that you maintain a proper JSON format. "enableForReference": true, "propertyType": "checkbox", "dependency": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] }, "disabled": true, "defaultValue": true @@ -447,8 +460,21 @@ making sure that you maintain a proper JSON format. "dependency": { "type": "not", "values": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] } }, "defaultValue": false @@ -1032,8 +1058,21 @@ making sure that you maintain a proper JSON format. "enableForReference": true, "propertyType": "checkbox", "dependency": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] }, "disabled": true, "defaultValue": true @@ -1046,8 +1085,21 @@ making sure that you maintain a proper JSON format. "dependency": { "type": "not", "values": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] } }, "defaultValue": false @@ -1783,8 +1835,21 @@ making sure that you maintain a proper JSON format. "enableForReference": true, "propertyType": "checkbox", "dependency": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] }, "disabled": true, "defaultValue": true @@ -1797,8 +1862,21 @@ making sure that you maintain a proper JSON format. "dependency": { "type": "not", "values": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] } }, "defaultValue": false @@ -2372,8 +2450,21 @@ making sure that you maintain a proper JSON format. "enableForReference": true, "propertyType": "checkbox", "dependency": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] }, "disabled": true, "defaultValue": true @@ -2386,8 +2477,21 @@ making sure that you maintain a proper JSON format. "dependency": { "type": "not", "values": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] } }, "defaultValue": false @@ -2915,8 +3019,21 @@ making sure that you maintain a proper JSON format. "enableForReference": true, "propertyType": "checkbox", "dependency": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] }, "disabled": true, "defaultValue": true @@ -2929,8 +3046,21 @@ making sure that you maintain a proper JSON format. "dependency": { "type": "not", "values": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] } }, "defaultValue": false @@ -3158,8 +3288,21 @@ making sure that you maintain a proper JSON format. "enableForReference": true, "propertyType": "checkbox", "dependency": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] }, "disabled": true, "defaultValue": true @@ -3172,8 +3315,21 @@ making sure that you maintain a proper JSON format. "dependency": { "type": "not", "values": { - "key": "primaryKey", - "value": true + "type": "or", + "values": [ + { + "key": "primaryKey", + "value": true + }, + { + "key": "unique", + "value": true + }, + { + "key": "compositeUniqueKey", + "value": true + } + ] } }, "defaultValue": false From dbfa7b9060b1722449eec5e24c65d06a4bc33f62 Mon Sep 17 00:00:00 2001 From: Alik Date: Thu, 8 Jan 2026 13:18:44 +0100 Subject: [PATCH 09/11] HCK-14210: script generation option for CHECK (#68)
Sub-taskHCK-14210 [DB2] Enable script generation options for Check constraints

## Technical details `wrapInQuotes` takes one string parameter now instead of an object --- .../alterScriptHelpers/alterEntityHelper.js | 5 +- .../columnHelpers/nonNullConstraintHelper.js | 4 +- .../entityHelpers/checkConstraintHelper.js | 122 ++++++++++++++++++ .../ddlHelpers/comment/commentHelper.js | 2 +- .../ddlHelpers/constraint/getOptionsString.js | 2 +- .../ddlHelpers/index/getIndexName.js | 4 +- .../ddlHelpers/index/getIndexOptions.js | 2 +- .../ddlHelpers/key/constraintsHelper.js | 2 +- .../ddlProvider/ddlHelpers/key/keyHelper.js | 6 +- .../ddlHelpers/table/getTableOptions.js | 4 +- .../ddlHelpers/table/getTableProps.js | 4 +- .../ddlHelpers/view/getViewData.js | 6 +- .../ddlProvider/ddlProvider.js | 10 +- forward_engineering/ddlProvider/templates.js | 4 + forward_engineering/utils/general.js | 8 +- 15 files changed, 154 insertions(+), 31 deletions(-) create mode 100644 forward_engineering/alterScript/alterScriptHelpers/entityHelpers/checkConstraintHelper.js diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js index 2b8694f..838f292 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -1,12 +1,13 @@ const { getModifyNonNullColumnsScriptDtos } = require('./columnHelpers/nonNullConstraintHelper'); +const { getModifyCheckConstraintScriptDtos } = require('./entityHelpers/checkConstraintHelper'); const { getModifyPkConstraintsScriptDtos } = require('./entityHelpers/primaryKeyHelper'); const { getModifyUkConstraintsScriptDtos } = require('./entityHelpers/uniqueKeyHelper'); const getModifyCollectionScriptDtos = collection => { - // const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(...); + const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(collection); // const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(...); return [ - // ...modifyCheckConstraintScriptDtos, + ...modifyCheckConstraintScriptDtos, // ...modifyCommentScriptDtos, ].filter(Boolean); }; diff --git a/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js index 7ca0e1d..6d38d13 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/nonNullConstraintHelper.js @@ -66,7 +66,7 @@ const getModifyNonNullColumnsScriptDtos = collection => { }) .map(([name, jsonSchema]) => { const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; - return { script: setNotNullConstraint(fullTableName, wrapInQuotes({ name })), isActivated }; + return { script: setNotNullConstraint(fullTableName, wrapInQuotes(name)), isActivated }; }) .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, false)); @@ -79,7 +79,7 @@ const getModifyNonNullColumnsScriptDtos = collection => { }) .map(([name, jsonSchema]) => { const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; - return { script: dropNotNullConstraint(fullTableName, wrapInQuotes({ name })), isActivated }; + return { script: dropNotNullConstraint(fullTableName, wrapInQuotes(name)), isActivated }; }) .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, true)); diff --git a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/checkConstraintHelper.js b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/checkConstraintHelper.js new file mode 100644 index 0000000..175701d --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/checkConstraintHelper.js @@ -0,0 +1,122 @@ +const _ = require('lodash'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { + getFullCollectionName, + wrapInQuotes, + isParentContainerActivated, + isObjectInDeltaModelActivated, + getSchemaOfAlterCollection, +} = require('../../../utils/general'); +const { assignTemplates } = require('../../../utils/assignTemplates'); +const templates = require('../../../ddlProvider/templates'); + +const addCheckConstraint = (tableName, constraintName, expression) => { + return assignTemplates({ + template: templates.alterCheckConstraint, + templateData: { + tableName, + constraintName, + expression, + }, + }); +}; + +const dropConstraint = (tableName, constraintName) => { + return assignTemplates({ + template: templates.dropCheckConstraint, + templateData: { + tableName, + constraintName, + }, + }); +}; + +const mapCheckConstraintNamesToChangeHistory = collection => { + const checkConstraintHistory = collection?.compMod?.chkConstr; + if (!checkConstraintHistory) { + return []; + } + const newConstraints = checkConstraintHistory.new || []; + const oldConstraints = checkConstraintHistory.old || []; + const constrNames = _.chain([...newConstraints, ...oldConstraints]) + .map(constr => constr.chkConstrName) + .uniq() + .value(); + + return constrNames.map(chkConstrName => { + return { + old: _.find(oldConstraints, { chkConstrName }), + new: _.find(newConstraints, { chkConstrName }), + }; + }); +}; + +const getDropCheckConstraintScriptDtos = (constraintHistory, fullTableName) => { + return constraintHistory + .filter(historyEntry => historyEntry.old?.constrExpression && !historyEntry.new?.constrExpression) + .map(historyEntry => { + const wrappedConstraintName = wrapInQuotes(historyEntry.old.chkConstrName); + return dropConstraint(fullTableName, wrappedConstraintName); + }) + .map(script => AlterScriptDto.getInstance([script], true, true)); +}; + +const getAddCheckConstraintScriptDtos = (constraintHistory, fullTableName) => { + return constraintHistory + .filter(historyEntry => historyEntry.new?.constrExpression && !historyEntry.old?.constrExpression) + .map(historyEntry => { + const { chkConstrName, constrExpression } = historyEntry.new; + return addCheckConstraint(fullTableName, wrapInQuotes(chkConstrName), constrExpression); + }) + .map(script => AlterScriptDto.getInstance([script], true, false)); +}; + +const getUpdateCheckConstraintScriptDtos = (constraintHistory, fullTableName) => { + return constraintHistory + .filter(historyEntry => { + if (historyEntry.old?.constrExpression && historyEntry.new?.constrExpression) { + const oldExpression = historyEntry.old.constrExpression; + const newExpression = historyEntry.new.constrExpression; + return oldExpression !== newExpression; + } + return false; + }) + .flatMap(historyEntry => { + const { chkConstrName: oldConstrainName } = historyEntry.old; + const dropConstraintScript = dropConstraint(fullTableName, wrapInQuotes(oldConstrainName)); + + const { chkConstrName: newConstrainName, constrExpression: newConstraintExpression } = historyEntry.new; + const addConstraintScript = addCheckConstraint( + fullTableName, + wrapInQuotes(newConstrainName), + newConstraintExpression, + ); + + return [ + AlterScriptDto.getInstance([dropConstraintScript], true, true), + AlterScriptDto.getInstance([addConstraintScript], true, false), + ]; + }); +}; + +const getModifyCheckConstraintScriptDtos = collection => { + const collectionSchema = getSchemaOfAlterCollection(collection); + const fullTableName = getFullCollectionName(collectionSchema); + const constraintHistory = mapCheckConstraintNamesToChangeHistory(collection); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isObjectInDeltaModelActivated(collection); + + const addCheckConstraintScripts = getAddCheckConstraintScriptDtos(constraintHistory, fullTableName); + const dropCheckConstraintScripts = getDropCheckConstraintScriptDtos(constraintHistory, fullTableName); + const updateCheckConstraintScripts = getUpdateCheckConstraintScriptDtos(constraintHistory, fullTableName); + + return [...addCheckConstraintScripts, ...dropCheckConstraintScripts, ...updateCheckConstraintScripts].map(dto => ({ + ...dto, + isActivated: isContainerActivated && isCollectionActivated, + })); +}; + +module.exports = { + getModifyCheckConstraintScriptDtos, +}; diff --git a/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js b/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js index 1f97b6a..d6c8db8 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js +++ b/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js @@ -42,7 +42,7 @@ const getCommentStatement = ({ objectName, objectType, description }) => { * @returns {string} */ const getColumnCommentStatement = ({ tableName, columnName, description }) => { - const objectName = tableName + '.' + wrapInQuotes({ name: columnName }); + const objectName = tableName + '.' + wrapInQuotes(columnName); return getCommentStatement({ objectName, objectType: OBJECT_TYPE.column, description }); }; diff --git a/forward_engineering/ddlProvider/ddlHelpers/constraint/getOptionsString.js b/forward_engineering/ddlProvider/ddlHelpers/constraint/getOptionsString.js index ff11821..253b35a 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/constraint/getOptionsString.js +++ b/forward_engineering/ddlProvider/ddlHelpers/constraint/getOptionsString.js @@ -12,7 +12,7 @@ const { wrapInQuotes } = require('../../../utils/general'); * @returns {string} */ const getOptionsString = ({ constraintName, deferClause, rely, validate, indexClause, exceptionClause }) => { - const constraintString = constraintName ? ` CONSTRAINT ${wrapInQuotes({ name: constraintName.trim() })}` : ''; + const constraintString = constraintName ? ` CONSTRAINT ${wrapInQuotes(constraintName.trim())}` : ''; const statement = [deferClause, rely, indexClause, validate, exceptionClause] .filter(Boolean) .map(option => ` ${option}`) diff --git a/forward_engineering/ddlProvider/ddlHelpers/index/getIndexName.js b/forward_engineering/ddlProvider/ddlHelpers/index/getIndexName.js index fd2b896..533a83b 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/index/getIndexName.js +++ b/forward_engineering/ddlProvider/ddlHelpers/index/getIndexName.js @@ -2,9 +2,9 @@ const { wrapInQuotes } = require('../../../utils/general'); const { getBasicValue } = require('../options/getOptionsByConfigs'); const getIndexName = ({ index }) => { - const indexName = getBasicValue({ prefix: '', modifier: name => wrapInQuotes({ name }) })(index.indxName); + const indexName = getBasicValue({ prefix: '', modifier: wrapInQuotes })(index.indxName); - return index.schemaName ? ` ${wrapInQuotes({ name: index.schemaName })}.${indexName}` : ` ${indexName}`; + return index.schemaName ? ` ${wrapInQuotes(index.schemaName)}.${indexName}` : ` ${indexName}`; }; module.exports = { diff --git a/forward_engineering/ddlProvider/ddlHelpers/index/getIndexOptions.js b/forward_engineering/ddlProvider/ddlHelpers/index/getIndexOptions.js index 22990d8..24dc962 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/index/getIndexOptions.js +++ b/forward_engineering/ddlProvider/ddlHelpers/index/getIndexOptions.js @@ -14,7 +14,7 @@ const getIndexKeys = (keys = []) => { const keysClause = keys .map(({ name, type }) => { const keyType = getBasicValue({ prefix: ' ', modifier: toUpper })(type); - const keyName = wrapInQuotes({ name }); + const keyName = wrapInQuotes(name); return keyName + keyType; }) diff --git a/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js b/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js index 32f4864..4c8ef4e 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js +++ b/forward_engineering/ddlProvider/ddlHelpers/key/constraintsHelper.js @@ -9,7 +9,7 @@ const { assignTemplates } = require('../../../utils/assignTemplates'); const templates = require('../../templates'); const getKeyOptions = (keyData, isParentActivated) => { - const constraintName = wrapInQuotes({ name: keyData.name.trim() }); + const constraintName = wrapInQuotes(keyData.name.trim()); const isAllColumnsDeactivated = checkAllKeysDeactivated(keyData.columns || []); const columns = _.isEmpty(keyData.columns) ? '' diff --git a/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js b/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js index 005d47d..f6a82a5 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js +++ b/forward_engineering/ddlProvider/ddlHelpers/key/keyHelper.js @@ -176,12 +176,10 @@ const getTableKeyConstraints = ({ jsonSchema }) => { */ const foreignKeysToString = ({ keys }) => { if (Array.isArray(keys)) { - const activatedKeys = keys - .filter(key => checkIsKeyActivated({ key })) - .map(key => wrapInQuotes({ name: trim(key.name) })); + const activatedKeys = keys.filter(key => checkIsKeyActivated({ key })).map(key => wrapInQuotes(trim(key.name))); const deactivatedKeys = keys .filter(key => !checkIsKeyActivated({ key })) - .map(key => wrapInQuotes({ name: trim(key.name) })); + .map(key => wrapInQuotes(trim(key.name))); const deactivatedKeysAsString = deactivatedKeys.length ? commentIfDeactivated(deactivatedKeys, { isActivated: false, isPartOfLine: true }) : ''; diff --git a/forward_engineering/ddlProvider/ddlHelpers/table/getTableOptions.js b/forward_engineering/ddlProvider/ddlHelpers/table/getTableOptions.js index 5534202..bd0aa9a 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/table/getTableOptions.js +++ b/forward_engineering/ddlProvider/ddlHelpers/table/getTableOptions.js @@ -20,7 +20,7 @@ const getTableOptions = tableData => { getValue: getBasicValue({ prefix: 'UNDER', postfix: 'INHERIT SELECT PRIVILEGES', - modifier: name => wrapInQuotes({ name }), + modifier: wrapInQuotes, }), }, { @@ -41,7 +41,7 @@ const getTableOptions = tableData => { }, { key: 'auxiliaryBaseColumn', - getValue: getBasicValue({ prefix: 'COLUMN', modifier: name => wrapInQuotes({ name }) }), + getValue: getBasicValue({ prefix: 'COLUMN', modifier: wrapInQuotes }), }, { key: 'auxiliaryPart', diff --git a/forward_engineering/ddlProvider/ddlHelpers/table/getTableProps.js b/forward_engineering/ddlProvider/ddlHelpers/table/getTableProps.js index 9274ff0..72e3b2a 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/table/getTableProps.js +++ b/forward_engineering/ddlProvider/ddlHelpers/table/getTableProps.js @@ -58,9 +58,7 @@ const createKeyConstraint = ({ keyData, isParentActivated }) => { const isAllColumnsDeactivated = checkAllKeysDeactivated({ keys: keyData.columns }); const columns = getColumnsList(keyData.columns, isAllColumnsDeactivated, isParentActivated); const options = getOptionsString(keyData).statement; - const constraintName = keyData.constraintName - ? `CONSTRAINT ${wrapInQuotes({ name: keyData.constraintName })} ` - : ''; + const constraintName = keyData.constraintName ? `CONSTRAINT ${wrapInQuotes(keyData.constraintName)} ` : ''; return { statement: assignTemplates({ diff --git a/forward_engineering/ddlProvider/ddlHelpers/view/getViewData.js b/forward_engineering/ddlProvider/ddlHelpers/view/getViewData.js index 19f96fa..9b9d2d5 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/view/getViewData.js +++ b/forward_engineering/ddlProvider/ddlHelpers/view/getViewData.js @@ -10,9 +10,9 @@ const getKeyWithAlias = ({ key }) => { } if (key.alias) { - return `${wrapInQuotes({ name: key.name })} as ${wrapInQuotes({ name: key.alias })}`; + return `${wrapInQuotes(key.name)} as ${wrapInQuotes(key.alias)}`; } else { - return wrapInQuotes({ name: key.name }); + return wrapInQuotes(key.name); } }; @@ -37,7 +37,7 @@ const getViewData = ({ keys }) => { return result; } - const tableName = `${wrapInQuotes({ name: key.dbName })}.${wrapInQuotes({ name: key.tableName })}`; + const tableName = `${wrapInQuotes(key.dbName)}.${wrapInQuotes(key.tableName)}`; if (!result.tables.includes(tableName)) { result.tables.push(tableName); diff --git a/forward_engineering/ddlProvider/ddlProvider.js b/forward_engineering/ddlProvider/ddlProvider.js index ddcceb6..dc487af 100644 --- a/forward_engineering/ddlProvider/ddlProvider.js +++ b/forward_engineering/ddlProvider/ddlProvider.js @@ -72,7 +72,7 @@ module.exports = (baseProvider, options, app) => { const schemaStatement = assignTemplates({ template: templates.createSchema, templateData: { - schemaName: wrapInQuotes({ name: schemaName }), + schemaName: wrapInQuotes(schemaName), authorization: authorizationName ? ' AUTHORIZATION ' + authorizationName : '', dataCapture: dataCapture ? ' DATA CAPTURE ' + dataCapture : '', }, @@ -128,7 +128,7 @@ module.exports = (baseProvider, options, app) => { const statement = assignTemplates({ template, templateData: { - name: wrapInQuotes({ name: columnDefinition.name }), + name: wrapInQuotes(columnDefinition.name), type: getColumnType(columnDefinition), default: getColumnDefault(columnDefinition), constraints: getColumnConstraints(columnDefinition), @@ -151,7 +151,7 @@ module.exports = (baseProvider, options, app) => { return assignTemplates({ template: templates.checkConstraint, templateData: { - name: name ? `CONSTRAINT ${wrapInQuotes({ name })} ` : '', + name: name ? `CONSTRAINT ${wrapInQuotes(name)} ` : '', expression: trim(expression).replace(/^\(([\s\S]*)\)$/, '$1'), }, }); @@ -187,7 +187,7 @@ module.exports = (baseProvider, options, app) => { name: primaryTable, schemaName: primarySchemaName || schemaData.schemaName, }); - const constraintName = name ? `CONSTRAINT ${wrapInQuotes({ name })}` : ''; + const constraintName = name ? `CONSTRAINT ${wrapInQuotes(name)}` : ''; const foreignKeyName = isActivated ? keyHelper.foreignKeysToString({ keys: foreignKeys }) : keyHelper.foreignActiveKeysToString({ keys: foreignKeys }); @@ -248,7 +248,7 @@ module.exports = (baseProvider, options, app) => { name: foreignTable, schemaName: foreignSchemaName || schemaData.schemaName, }); - const constraintName = name ? wrapInQuotes({ name }) : ''; + const constraintName = name ? wrapInQuotes(name) : ''; const foreignKeyName = isActivated ? keyHelper.foreignKeysToString({ keys: foreignKeys }) : keyHelper.foreignActiveKeysToString({ keys: foreignKeys }); diff --git a/forward_engineering/ddlProvider/templates.js b/forward_engineering/ddlProvider/templates.js index 856802f..4a358b0 100644 --- a/forward_engineering/ddlProvider/templates.js +++ b/forward_engineering/ddlProvider/templates.js @@ -40,4 +40,8 @@ module.exports = { alterUkConstraint: 'ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} UNIQUE${columns}${options};', dropUkConstraint: 'ALTER TABLE ${tableName} DROP UNIQUE ${constraintName};', + + alterCheckConstraint: 'ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} CHECK (${expression});', + + dropCheckConstraint: 'ALTER TABLE ${tableName} DROP CHECK ${constraintName};', }; diff --git a/forward_engineering/utils/general.js b/forward_engineering/utils/general.js index 76a84d9..afaf4ed 100644 --- a/forward_engineering/utils/general.js +++ b/forward_engineering/utils/general.js @@ -73,7 +73,7 @@ const commentIfDeactivated = (statement, { isActivated, isPartOfLine, inlineComm * @param {{ name: string }} * @returns {string} */ -const wrapInQuotes = ({ name }) => `"${name}"`; +const wrapInQuotes = str => `"${str}"`; /** * @param {{ name: string }} @@ -89,13 +89,13 @@ const removeAllQuotes = str => str.replaceAll(/['"]/g, ''); */ const getNamePrefixedWithSchemaName = ({ name, schemaName }) => { if (schemaName) { - return `${wrapInQuotes({ name: schemaName })}.${wrapInQuotes({ name })}`; + return `${wrapInQuotes(schemaName)}.${wrapInQuotes(name)}`; } - return wrapInQuotes({ name }); + return wrapInQuotes(name); }; -const columnMapToString = ({ name }) => wrapInQuotes({ name }); +const columnMapToString = ({ name }) => wrapInQuotes(name); const getColumnsList = (columns, isAllColumnsDeactivated, isParentActivated, mapColumn = columnMapToString) => { const dividedColumns = divideIntoActivatedAndDeactivated({ items: columns, mapFunction: mapColumn }); From cf3941331a79f03cd7e26f3b974450dc53729da0 Mon Sep 17 00:00:00 2001 From: chulanovskyi-bs <56116665+chulanovskyi-bs@users.noreply.github.com> Date: Thu, 8 Jan 2026 14:23:22 +0200 Subject: [PATCH 10/11] HCL-14209: DEFAULT script generation option (#69) ## Content * default column value as alter statement --- .../alterScriptHelpers/alterEntityHelper.js | 5 +- .../columnHelpers/defaultValueHelper.js | 118 ++++++++++++++++++ forward_engineering/ddlProvider/templates.js | 4 + 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 forward_engineering/alterScript/alterScriptHelpers/columnHelpers/defaultValueHelper.js diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js index 838f292..9da238c 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -2,6 +2,7 @@ const { getModifyNonNullColumnsScriptDtos } = require('./columnHelpers/nonNullCo const { getModifyCheckConstraintScriptDtos } = require('./entityHelpers/checkConstraintHelper'); const { getModifyPkConstraintsScriptDtos } = require('./entityHelpers/primaryKeyHelper'); const { getModifyUkConstraintsScriptDtos } = require('./entityHelpers/uniqueKeyHelper'); +const { getModifiedDefaultColumnValueScriptDtos } = require('./columnHelpers/defaultValueHelper'); const getModifyCollectionScriptDtos = collection => { const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(collection); @@ -21,11 +22,11 @@ const getModifyCollectionKeysScriptDtos = collection => { const getModifyColumnScriptDtos = collection => { const modifyNotNullScriptDtos = getModifyNonNullColumnsScriptDtos(collection); // const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(...); - // const modifyDefaultColumnValueScriptDtos = getModifiedDefaultColumnValueScriptDtos(...); + const modifyDefaultColumnValueScriptDtos = getModifiedDefaultColumnValueScriptDtos({ collection }); return [ ...modifyNotNullScriptDtos, - // ...modifyDefaultColumnValueScriptDtos, + ...modifyDefaultColumnValueScriptDtos, // ...modifyCommentScriptDtos, ].filter(Boolean); }; diff --git a/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/defaultValueHelper.js b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/defaultValueHelper.js new file mode 100644 index 0000000..cca83e2 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/defaultValueHelper.js @@ -0,0 +1,118 @@ +const { toPairs } = require('lodash'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { + getFullCollectionName, + wrapInQuotes, + isObjectInDeltaModelActivated, + isParentContainerActivated, + getSchemaOfAlterCollection, +} = require('../../../utils/general'); +const { assignTemplates } = require('../../../utils/assignTemplates'); +const templates = require('../../../ddlProvider/templates'); + +/** + * @param {Object} props + * @param {string} props.tableName + * @param {string} props.columnName + * @param {string} props.defaultValue + * @return string + * */ +const updateColumnDefaultValue = ({ tableName, columnName, defaultValue }) => { + const templateConfig = { + tableName, + columnName, + defaultValue, + }; + return assignTemplates({ template: templates.updateColumnDefaultValue, templateData: templateConfig }); +}; + +/** + * @param {Object} props + * @param {Object} props.collection + * @returns { Array } + * */ +const getUpdatedDefaultColumnValueScriptDtos = ({ collection }) => { + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isObjectInDeltaModelActivated(collection); + const collectionSchema = getSchemaOfAlterCollection(collection); + + return toPairs(collection.properties) + .filter(([_name, jsonSchema]) => { + const newDefault = jsonSchema.default; + const oldName = jsonSchema.compMod.oldField.name; + const oldDefault = collection.role.properties[oldName]?.default; + return newDefault !== undefined && (!oldDefault || newDefault !== oldDefault); + }) + .map(([columnName, jsonSchema]) => { + const newDefaultValue = jsonSchema.default; + const scriptGenerationConfig = { + tableName: getFullCollectionName(collectionSchema), + columnName: wrapInQuotes(columnName), + defaultValue: newDefaultValue, + }; + const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; + return { script: updateColumnDefaultValue(scriptGenerationConfig), isActivated }; + }) + .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, false)) + .filter(Boolean); +}; + +/** + * @param {Object} props + * @param {string} props.tableName + * @param {string} props.columnName + * @return string + * */ +const dropColumnDefaultValue = ({ tableName, columnName }) => { + const templateConfig = { + tableName, + columnName, + }; + return assignTemplates({ template: templates.dropColumnDefaultValue, templateData: templateConfig }); +}; + +/** + * @param {Object} props + * @param {Object} props.collection + * @returns { Array } + * */ +const getDeletedDefaultColumnValueScriptDtos = ({ collection }) => { + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isObjectInDeltaModelActivated(collection); + const collectionSchema = getSchemaOfAlterCollection(collection); + + return toPairs(collection.properties) + .filter(([_name, jsonSchema]) => { + const newDefault = jsonSchema.default; + const oldName = jsonSchema.compMod.oldField.name; + const oldDefault = collection.role.properties[oldName]?.default; + const hasPrevValue = oldDefault !== undefined; + const hasNewValue = newDefault !== undefined; + return hasPrevValue && !hasNewValue; + }) + .map(([columnName, jsonSchema]) => { + const scriptGenerationConfig = { + tableName: getFullCollectionName(collectionSchema), + columnName: wrapInQuotes(columnName), + }; + const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; + return { script: dropColumnDefaultValue(scriptGenerationConfig), isActivated }; + }) + .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, true)) + .filter(Boolean); +}; + +/** + * @param {Object} props + * @param {Object} props.collection + * @returns { Array } + * */ +const getModifiedDefaultColumnValueScriptDtos = ({ collection }) => { + const updatedDefaultValuesScriptDtos = getUpdatedDefaultColumnValueScriptDtos({ collection }); + const dropDefaultValuesScriptDtos = getDeletedDefaultColumnValueScriptDtos({ collection }); + return [...updatedDefaultValuesScriptDtos, ...dropDefaultValuesScriptDtos]; +}; + +module.exports = { + getModifiedDefaultColumnValueScriptDtos, +}; diff --git a/forward_engineering/ddlProvider/templates.js b/forward_engineering/ddlProvider/templates.js index 4a358b0..fe6725d 100644 --- a/forward_engineering/ddlProvider/templates.js +++ b/forward_engineering/ddlProvider/templates.js @@ -44,4 +44,8 @@ module.exports = { alterCheckConstraint: 'ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} CHECK (${expression});', dropCheckConstraint: 'ALTER TABLE ${tableName} DROP CHECK ${constraintName};', + + updateColumnDefaultValue: 'ALTER TABLE ${tableName} ALTER COLUMN ${columnName} SET DEFAULT ${defaultValue};', + + dropColumnDefaultValue: 'ALTER TABLE ${tableName} ALTER COLUMN ${columnName} DROP DEFAULT;', }; From 3146caefe34a2a85d3afe89a0124001b4f00fb2e Mon Sep 17 00:00:00 2001 From: Alik Date: Thu, 8 Jan 2026 13:45:28 +0100 Subject: [PATCH 11/11] HCK-14208: script generation options for COMMENT (#70)
Sub-taskHCK-14208 [DB2] Enable script generation options for Comments

## Content You have no Jira task for this PR? Describe your changes here... ... ## Technical details You feel the need to provide technical explanations? You can do it here... ... --- .../alterScript/alterScriptFromDeltaHelper.js | 6 +- .../alterScriptHelpers/alterEntityHelper.js | 19 +++--- .../alterScriptHelpers/alterViewHelper.js | 8 +-- .../columnHelpers/commentsHelper.js | 64 +++++++++++++++++++ .../entityHelpers/commentsHelper.js | 62 ++++++++++++++++++ .../viewHelpers/commentsHelper.js | 56 ++++++++++++++++ forward_engineering/utils/general.js | 2 +- 7 files changed, 197 insertions(+), 20 deletions(-) create mode 100644 forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js create mode 100644 forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js create mode 100644 forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index ebca672..fc1ab92 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -32,11 +32,11 @@ const getAlterCollectionScriptDtos = ({ ); }; -const getAlterViewScriptDtos = (collection, app) => { +const getAlterViewScriptDtos = collection => { const modifyViewScriptDtos = getItems(collection.properties?.views?.properties?.modified) .map(viewWrapper => Object.values(viewWrapper.properties)[0]) .map(view => ({ ...view, ...view.role })) - .flatMap(view => getModifyViewScriptDtos(view)); + .flatMap(getModifyViewScriptDtos); return [...modifyViewScriptDtos].filter(Boolean); }; @@ -135,7 +135,7 @@ const getAlterScriptDtos = (data, app) => { externalDefinitions, }); - const viewScriptDtos = getAlterViewScriptDtos({ collection, app }); + const viewScriptDtos = getAlterViewScriptDtos(collection); const relationshipScriptDtos = getAlterRelationshipsScriptDtos({ collection, diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js index 9da238c..ddf91b4 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -1,16 +1,15 @@ +const { getModifiedCommentOnColumnScriptDtos } = require('./columnHelpers/commentsHelper'); const { getModifyNonNullColumnsScriptDtos } = require('./columnHelpers/nonNullConstraintHelper'); const { getModifyCheckConstraintScriptDtos } = require('./entityHelpers/checkConstraintHelper'); +const { getModifyEntityCommentsScriptDtos } = require('./entityHelpers/commentsHelper'); const { getModifyPkConstraintsScriptDtos } = require('./entityHelpers/primaryKeyHelper'); const { getModifyUkConstraintsScriptDtos } = require('./entityHelpers/uniqueKeyHelper'); const { getModifiedDefaultColumnValueScriptDtos } = require('./columnHelpers/defaultValueHelper'); const getModifyCollectionScriptDtos = collection => { const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(collection); - // const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(...); - return [ - ...modifyCheckConstraintScriptDtos, - // ...modifyCommentScriptDtos, - ].filter(Boolean); + const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(collection); + return [...modifyCheckConstraintScriptDtos, ...modifyCommentScriptDtos].filter(Boolean); }; const getModifyCollectionKeysScriptDtos = collection => { @@ -21,14 +20,12 @@ const getModifyCollectionKeysScriptDtos = collection => { const getModifyColumnScriptDtos = collection => { const modifyNotNullScriptDtos = getModifyNonNullColumnsScriptDtos(collection); - // const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(...); + const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(collection); const modifyDefaultColumnValueScriptDtos = getModifiedDefaultColumnValueScriptDtos({ collection }); - return [ - ...modifyNotNullScriptDtos, - ...modifyDefaultColumnValueScriptDtos, - // ...modifyCommentScriptDtos, - ].filter(Boolean); + return [...modifyNotNullScriptDtos, ...modifyDefaultColumnValueScriptDtos, ...modifyCommentScriptDtos].filter( + Boolean, + ); }; module.exports = { diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js index 11e5c6c..c38dd89 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js @@ -1,11 +1,9 @@ -// const { getModifyViewCommentsScriptDtos } = require('./viewHelpers/commentsHelper'); +const { getModifyViewCommentsScriptDtos } = require('./viewHelpers/commentsHelper'); const getModifyViewScriptDtos = view => { - // const modifyCommentsScriptDtos = getModifyViewCommentsScriptDtos(...); + const modifyCommentsScriptDtos = getModifyViewCommentsScriptDtos(view); - return [ - // ...modifyCommentsScriptDtos, - ].filter(Boolean); + return [...modifyCommentsScriptDtos].filter(Boolean); }; module.exports = { diff --git a/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js new file mode 100644 index 0000000..485f048 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js @@ -0,0 +1,64 @@ +const _ = require('lodash'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { + isObjectInDeltaModelActivated, + isParentContainerActivated, + getSchemaOfAlterCollection, + getFullCollectionName, +} = require('../../../utils/general'); +const { getColumnCommentStatement } = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); + +const getUpdatedCommentOnColumnScriptDtos = collection => { + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isObjectInDeltaModelActivated(collection); + const collectionSchema = getSchemaOfAlterCollection(collection); + const tableName = getFullCollectionName(collectionSchema); + + return _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + const newComment = jsonSchema.description; + const oldName = jsonSchema.compMod.oldField.name; + const oldComment = collection.role.properties[oldName]?.description; + return newComment && (!oldComment || newComment !== oldComment); + }) + .map(([columnName, jsonSchema]) => { + const newComment = jsonSchema.description; + const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; + const script = getColumnCommentStatement({ tableName, columnName, description: newComment }); + + return { script, isActivated }; + }) + .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, false)); +}; + +const getDeletedCommentOnColumnScriptDtos = collection => { + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isObjectInDeltaModelActivated(collection); + const collectionSchema = getSchemaOfAlterCollection(collection); + const tableName = getFullCollectionName(collectionSchema); + + return _.toPairs(collection.properties) + .filter(([name, jsonSchema]) => { + const newComment = jsonSchema.description; + const oldName = jsonSchema.compMod.oldField.name; + const oldComment = collection.role.properties[oldName]?.description; + return oldComment && !newComment; + }) + .map(([columnName, jsonSchema]) => { + const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; + const script = getColumnCommentStatement({ tableName, columnName, description: '' }); + + return { script, isActivated }; + }) + .map(({ script, isActivated }) => AlterScriptDto.getInstance([script], isActivated, true)); +}; + +const getModifiedCommentOnColumnScriptDtos = collection => { + const updatedCommentScripts = getUpdatedCommentOnColumnScriptDtos(collection); + const deletedCommentScripts = getDeletedCommentOnColumnScriptDtos(collection); + return [...updatedCommentScripts, ...deletedCommentScripts]; +}; + +module.exports = { + getModifiedCommentOnColumnScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js new file mode 100644 index 0000000..b9e3a6c --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js @@ -0,0 +1,62 @@ +const _ = require('lodash'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { + isObjectInDeltaModelActivated, + isParentContainerActivated, + getSchemaOfAlterCollection, + getFullCollectionName, +} = require('../../../utils/general'); +const { getTableCommentStatement } = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); + +const getUpdatedCommentOnCollectionScriptDto = collection => { + const descriptionInfo = collection?.role.compMod?.description; + if (!descriptionInfo) { + return undefined; + } + + const { old: oldComment, new: newComment } = descriptionInfo; + if (!newComment || newComment === oldComment) { + return undefined; + } + + const collectionSchema = getSchemaOfAlterCollection(collection); + const tableName = getFullCollectionName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + const script = getTableCommentStatement({ tableName, description: newComment }); + return AlterScriptDto.getInstance([script], isCollectionActivated, false); +}; + +const getDeletedCommentOnCollectionScriptDto = collection => { + const descriptionInfo = collection?.role.compMod?.description; + if (!descriptionInfo) { + return undefined; + } + + const { old: oldComment, new: newComment } = descriptionInfo; + if (!oldComment || newComment) { + return undefined; + } + + const collectionSchema = getSchemaOfAlterCollection(collection); + const tableName = getFullCollectionName(collectionSchema); + + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + const script = getTableCommentStatement({ tableName, description: '' }); + return AlterScriptDto.getInstance([script], isCollectionActivated, true); +}; + +const getModifyEntityCommentsScriptDtos = collection => { + const updatedCommentScript = getUpdatedCommentOnCollectionScriptDto(collection); + const deletedCommentScript = getDeletedCommentOnCollectionScriptDto(collection); + + return [updatedCommentScript, deletedCommentScript].filter(Boolean); +}; + +module.exports = { + getModifyEntityCommentsScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js new file mode 100644 index 0000000..89bab01 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js @@ -0,0 +1,56 @@ +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { + isObjectInDeltaModelActivated, + isParentContainerActivated, + getFullCollectionName, + getSchemaOfAlterCollection, +} = require('../../../utils/general'); +const { getTableCommentStatement } = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); + +const extractDescription = view => { + return view?.role?.compMod?.description || {}; +}; + +const getUpsertCommentsScriptDto = view => { + const description = extractDescription(view); + if (description.new && description.new !== description.old) { + const comment = description.new; + + const viewSchema = getSchemaOfAlterCollection(view); + const viewName = getFullCollectionName(viewSchema); + + const isContainerActivated = isParentContainerActivated(view); + const isViewActivated = isContainerActivated && isObjectInDeltaModelActivated(view); + + const script = getTableCommentStatement({ tableName: viewName, description: comment }); + + return AlterScriptDto.getInstance([script], isViewActivated, false); + } + return undefined; +}; + +const getDropCommentsScriptDto = view => { + const description = extractDescription(view); + + if (description.old && !description.new) { + const viewSchema = getSchemaOfAlterCollection(view); + const viewName = getFullCollectionName(viewSchema); + + const isContainerActivated = isParentContainerActivated(view); + const isViewActivated = isContainerActivated && isObjectInDeltaModelActivated(view); + + const script = getTableCommentStatement({ tableName: viewName, description: '' }); + return AlterScriptDto.getInstance([script], isViewActivated, true); + } + return undefined; +}; + +const getModifyViewCommentsScriptDtos = view => { + const upsertCommentScript = getUpsertCommentsScriptDto(view); + const dropCommentScript = getDropCommentsScriptDto(view); + return [upsertCommentScript, dropCommentScript].filter(Boolean); +}; + +module.exports = { + getModifyViewCommentsScriptDtos, +}; diff --git a/forward_engineering/utils/general.js b/forward_engineering/utils/general.js index afaf4ed..dab44a8 100644 --- a/forward_engineering/utils/general.js +++ b/forward_engineering/utils/general.js @@ -119,7 +119,7 @@ const getColumnsList = (columns, isAllColumnsDeactivated, isParentActivated, map const toArray = ({ value }) => (Array.isArray(value) ? value : [value]); const getEntityName = entityData => { - return entityData?.code || entityData?.collectionName || ''; + return entityData?.code || entityData?.collectionName || entityData?.name || ''; }; const getSchemaNameFromCollection = ({ collection }) => {