From 9206c1cf36df716b7763b7775156fffaf427cdc0 Mon Sep 17 00:00:00 2001 From: yevhenii moroziuk Date: Tue, 29 Jul 2025 09:34:10 +0300 Subject: [PATCH 1/6] HCK-12141: Generate FK name if necessary --- forward_engineering/ddlProvider.js | 23 +++++++++++++++++-- .../alterRelationshipsHelper.js | 1 - forward_engineering/helpers/general.js | 15 ++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index 74f21af2..6b303860 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -31,6 +31,7 @@ module.exports = (baseProvider, options, app) => { getTempTableTime, foreignActiveKeysToString, additionalPropertiesForForeignKey, + getFKConstraintName, } = require('./helpers/general')(app); const keyHelper = require('./helpers/keyHelper')(app); const { getTerminator } = require('./helpers/optionsHelper'); @@ -285,12 +286,21 @@ module.exports = (baseProvider, options, app) => { primaryTableActivated && foreignTableActivated; + const relationshipName = + name || + getFKConstraintName({ + primaryTableName: primaryTable, + foreignTableName: '', + primaryTableColumns: primaryKey, + foreignTableColumns: foreignKey, + }); + const { foreignOnDelete, foreignOnUpdate } = additionalPropertiesForForeignKey(customProperties); return { statement: assignTemplates(templates.createForeignKeyConstraint, { primaryTable: getTableName(primaryTable, primarySchemaName || schemaData.schemaName, true), - name: wrapInBrackets(name), + name: wrapInBrackets(relationshipName), foreignKey: isActivated ? foreignKeysToString(foreignKey) : foreignActiveKeysToString(foreignKey), primaryKey: isActivated ? foreignKeysToString(primaryKey) : foreignActiveKeysToString(primaryKey), onDelete: foreignOnDelete ? ` ON DELETE ${foreignOnDelete}` : '', @@ -320,11 +330,20 @@ module.exports = (baseProvider, options, app) => { const { foreignOnDelete, foreignOnUpdate } = additionalPropertiesForForeignKey(customProperties); + const relationshipName = + name || + getFKConstraintName({ + primaryTableName: primaryTable, + foreignTableName: foreignTable, + primaryTableColumns: primaryKey, + foreignTableColumns: foreignKey, + }); + return { statement: assignTemplates(templates.createForeignKey, { primaryTable: getTableName(primaryTable, schemaData.schemaName, true), foreignTable: getTableName(foreignTable, schemaData.schemaName, true), - name: wrapInBrackets(name), + name: wrapInBrackets(relationshipName), foreignKey: foreignKeysToString(foreignKey), primaryKey: foreignKeysToString(primaryKey), onDelete: foreignOnDelete ? ` ON DELETE ${foreignOnDelete}` : '', diff --git a/forward_engineering/helpers/alterScriptHelpers/alterRelationshipsHelper.js b/forward_engineering/helpers/alterScriptHelpers/alterRelationshipsHelper.js index adcb87cf..3fdbe175 100644 --- a/forward_engineering/helpers/alterScriptHelpers/alterRelationshipsHelper.js +++ b/forward_engineering/helpers/alterScriptHelpers/alterRelationshipsHelper.js @@ -63,7 +63,6 @@ const canRelationshipBeAdded = relationship => { return false; } return [ - compMod.name?.new || getRelationshipName(relationship), compMod.parent?.bucket, compMod.parent?.collection, compMod.parent?.collection?.fkFields?.length, diff --git a/forward_engineering/helpers/general.js b/forward_engineering/helpers/general.js index 13a4d9e8..257973fd 100644 --- a/forward_engineering/helpers/general.js +++ b/forward_engineering/helpers/general.js @@ -251,6 +251,20 @@ module.exports = app => { return ''; }; + /** + * @param {Object} params + * @param {string} params.primaryTableName + * @param {string} params.foreignTableName + * @param {Array} params.primaryTableColumns + * @param {Array} params.foreignTableColumns + * @returns {string} + */ + const getFKConstraintName = ({ primaryTableName, foreignTableName, primaryTableColumns, foreignTableColumns }) => { + return sanitizeConstraintName( + `FK_${[primaryTableName, foreignTableColumns.map(k => k.name).join('_'), foreignTableName, primaryTableColumns.map(k => k.name).join('_')].filter(Boolean).join('_')}`, + ); + }; + return { filterColumnStoreProperties, getKeyWithAlias, @@ -266,5 +280,6 @@ module.exports = app => { foreignActiveKeysToString, getDefaultValue, getTempTableTime, + getFKConstraintName, }; }; From aeff809130827381cb53da1863b2f9ed480495d9 Mon Sep 17 00:00:00 2001 From: yevhenii moroziuk Date: Tue, 29 Jul 2025 16:31:01 +0300 Subject: [PATCH 2/6] HCK-12141: Improve no check constraint --- forward_engineering/configs/templates.js | 2 +- forward_engineering/ddlProvider.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/forward_engineering/configs/templates.js b/forward_engineering/configs/templates.js index edff7e32..31532327 100644 --- a/forward_engineering/configs/templates.js +++ b/forward_engineering/configs/templates.js @@ -23,7 +23,7 @@ module.exports = { spatialIndex: 'CREATE SPATIAL INDEX ${name} ON ${table} (${column})${using}\n${options}${terminator}\n', - checkConstraint: 'CONSTRAINT [${name}] CHECK${notForReplication} (${expression})', + checkConstraint: 'CONSTRAINT [${name}] ${check}${notForReplication} (${expression})', createForeignKeyConstraint: 'CONSTRAINT ${name} FOREIGN KEY (${foreignKey}) REFERENCES ${primaryTable} (${primaryKey}) ${onDelete}${onUpdate}', diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index 6b303860..15720a7f 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -258,6 +258,7 @@ module.exports = (baseProvider, options, app) => { createCheckConstraint(checkConstraint) { return assignTemplates(templates.checkConstraint, { name: checkConstraint.name, + check: checkConstraint.check ? 'CHECK' : 'NO CHECK', notForReplication: checkConstraint.enforceForReplication ? '' : ' NOT FOR REPLICATION', expression: _.trim(checkConstraint.expression).replace(/^\(([\s\S]*)\)$/, '$1'), terminator, @@ -533,6 +534,7 @@ module.exports = (baseProvider, options, app) => { hydrateCheckConstraint(checkConstraint) { return { name: checkConstraint.chkConstrName, + check: checkConstraint.constrCheck, expression: checkConstraint.constrExpression, existingData: checkConstraint.constrCheck, enforceForUpserts: checkConstraint.constrEnforceUpserts, From e48aac8f837454956a84e7256e6c034b79a5b606 Mon Sep 17 00:00:00 2001 From: yevhenii moroziuk Date: Tue, 29 Jul 2025 16:40:21 +0300 Subject: [PATCH 3/6] HCK-12142: Do not decorate default value --- forward_engineering/helpers/general.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/forward_engineering/helpers/general.js b/forward_engineering/helpers/general.js index 257973fd..48e33ef5 100644 --- a/forward_engineering/helpers/general.js +++ b/forward_engineering/helpers/general.js @@ -22,13 +22,11 @@ module.exports = app => { return ''; } - const value = decorateDefault(type, defaultConstraint.value); - if (!_.isUndefined(defaultConstraint.name)) { - return ` CONSTRAINT ${defaultConstraint.name} DEFAULT ${value}`; + return ` CONSTRAINT ${defaultConstraint.name} DEFAULT ${defaultConstraint.value}`; } - return ` DEFAULT ${value}`; + return ` DEFAULT ${defaultConstraint.value}`; }; const sanitizeConstraintName = str => { From 9d324db58e3a34cbcec5d57de4726db2631a14fb Mon Sep 17 00:00:00 2001 From: yevhenii moroziuk Date: Tue, 29 Jul 2025 17:22:42 +0300 Subject: [PATCH 4/6] HCK-12142: Do not decorate default value in some cases --- forward_engineering/helpers/columnDefinitionHelper.js | 2 +- forward_engineering/helpers/general.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/forward_engineering/helpers/columnDefinitionHelper.js b/forward_engineering/helpers/columnDefinitionHelper.js index 0eefc7d4..87b4462a 100644 --- a/forward_engineering/helpers/columnDefinitionHelper.js +++ b/forward_engineering/helpers/columnDefinitionHelper.js @@ -67,7 +67,7 @@ module.exports = app => { const decorateDefault = (type, defaultValue) => { if (isString(type) && defaultValue !== 'NULL') { - return `'${escapeQuotes(defaultValue)}'`; + return escapeQuotes(defaultValue); } else if (type === 'XML') { return `CAST(N'${defaultValue}' AS xml)`; } diff --git a/forward_engineering/helpers/general.js b/forward_engineering/helpers/general.js index 48e33ef5..257973fd 100644 --- a/forward_engineering/helpers/general.js +++ b/forward_engineering/helpers/general.js @@ -22,11 +22,13 @@ module.exports = app => { return ''; } + const value = decorateDefault(type, defaultConstraint.value); + if (!_.isUndefined(defaultConstraint.name)) { - return ` CONSTRAINT ${defaultConstraint.name} DEFAULT ${defaultConstraint.value}`; + return ` CONSTRAINT ${defaultConstraint.name} DEFAULT ${value}`; } - return ` DEFAULT ${defaultConstraint.value}`; + return ` DEFAULT ${value}`; }; const sanitizeConstraintName = str => { From 8b33dcedb7972818b6d3e97f54a9d933ad852317 Mon Sep 17 00:00:00 2001 From: yevhenii moroziuk Date: Wed, 30 Jul 2025 14:11:24 +0300 Subject: [PATCH 5/6] HCK-12141: Improve logic of escaping single quotes for default value --- .../columnHelpers/defaultValueColumnHelper.js | 15 +++++++++++---- .../helpers/columnDefinitionHelper.js | 7 ++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/forward_engineering/helpers/alterScriptHelpers/columnHelpers/defaultValueColumnHelper.js b/forward_engineering/helpers/alterScriptHelpers/columnHelpers/defaultValueColumnHelper.js index 09a87aea..ab473a37 100644 --- a/forward_engineering/helpers/alterScriptHelpers/columnHelpers/defaultValueColumnHelper.js +++ b/forward_engineering/helpers/alterScriptHelpers/columnHelpers/defaultValueColumnHelper.js @@ -1,6 +1,8 @@ module.exports = (app, ddlProvider) => { + const _ = app.require('lodash'); const { AlterScriptDto } = require('../types/AlterScriptDto'); - const { sanitizeConstraintName } = require('../../../helpers/general')(app); + const { sanitizeConstraintName, hasType, getTableName } = require('../../../helpers/general')(app); + const { decorateDefault } = require('../../columnDefinitionHelper')(app); const getDefaultValueChangeDto = (collection, fullName) => { const scripts = []; @@ -8,6 +10,10 @@ module.exports = (app, ddlProvider) => { const getDefaultConstraintName = columnName => sanitizeConstraintName(`DF_${fullName}_${columnName}`); Object.entries(collection?.properties ?? []).forEach(([columnName, collectionSchema]) => { + const type = hasType(collectionSchema.type) + ? _.toUpper(collectionSchema.type) + : getTableName(collectionSchema.type, collectionSchema.schemaName); + const newDefaultValue = collectionSchema.default; const newConstraintName = collectionSchema.defaultConstraintName; const oldDefaultValue = collection.role.properties[columnName]?.default; @@ -24,6 +30,7 @@ module.exports = (app, ddlProvider) => { !!oldConstraintName && !!newConstraintName && oldConstraintName !== newConstraintName; + const decoratedValue = decorateDefault(type, newDefaultValue); switch (true) { case defaultValueWasRemoved: { @@ -40,7 +47,7 @@ module.exports = (app, ddlProvider) => { { constraintName, columnName, - value: newDefaultValue, + value: decoratedValue, }, fullName, ); @@ -58,7 +65,7 @@ module.exports = (app, ddlProvider) => { { constraintName, columnName, - value: newDefaultValue, + value: decoratedValue, }, fullName, ); @@ -72,7 +79,7 @@ module.exports = (app, ddlProvider) => { { constraintName: newConstraintName, columnName, - value: newDefaultValue, + value: decoratedValue, }, fullName, ); diff --git a/forward_engineering/helpers/columnDefinitionHelper.js b/forward_engineering/helpers/columnDefinitionHelper.js index 87b4462a..59f321e5 100644 --- a/forward_engineering/helpers/columnDefinitionHelper.js +++ b/forward_engineering/helpers/columnDefinitionHelper.js @@ -63,7 +63,12 @@ module.exports = app => { const isString = type => ['CHAR', 'VARCHAR', 'NCHAR', 'NVARCHAR', 'TEXT', 'NTEXT'].includes(_.toUpper(type)); - const escapeQuotes = str => _.trim(str).replace(/(\')+/g, "'$1"); + /** + * Escape only inner single quotes. + * @param {string} str + * @returns {string} + */ + const escapeQuotes = str => _.trim(str).replace(/(? { if (isString(type) && defaultValue !== 'NULL') { From 9fc3d0013e3037484f847469d51173334fd601b3 Mon Sep 17 00:00:00 2001 From: yevhenii moroziuk Date: Wed, 30 Jul 2025 15:56:01 +0300 Subject: [PATCH 6/6] Temporary revert the logic of wrapping default values in single quotes --- forward_engineering/helpers/columnDefinitionHelper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forward_engineering/helpers/columnDefinitionHelper.js b/forward_engineering/helpers/columnDefinitionHelper.js index 59f321e5..3d170bdc 100644 --- a/forward_engineering/helpers/columnDefinitionHelper.js +++ b/forward_engineering/helpers/columnDefinitionHelper.js @@ -68,11 +68,11 @@ module.exports = app => { * @param {string} str * @returns {string} */ - const escapeQuotes = str => _.trim(str).replace(/(? _.trim(str).replace(/(\')+/g, "'$1"); const decorateDefault = (type, defaultValue) => { if (isString(type) && defaultValue !== 'NULL') { - return escapeQuotes(defaultValue); + return `'${escapeQuotes(defaultValue)}'`; } else if (type === 'XML') { return `CAST(N'${defaultValue}' AS xml)`; }