From 3dc05de23bc35d556f2dccc8766e11d56d00528f Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Tue, 16 Dec 2025 14:54:55 +0100 Subject: [PATCH 1/2] HCK-13862: fix order of tables with FKs --- .../generateContainerScript.js | 45 ++++++++++++- .../helpers/alterScriptFromDeltaHelper.js | 63 +++++++++++++++++-- 2 files changed, 102 insertions(+), 6 deletions(-) diff --git a/forward_engineering/generateContainerScript.js b/forward_engineering/generateContainerScript.js index ee41165..4257197 100644 --- a/forward_engineering/generateContainerScript.js +++ b/forward_engineering/generateContainerScript.js @@ -11,6 +11,44 @@ const { parseEntities } = require('./helpers/parseEntities'); const { getWorkloadManagementStatements } = require('./helpers/getWorkloadManagementStatements'); const { getIsPkOrFkConstraintAvailable } = require('./helpers/constraintHelper'); +const sortEntitiesByForeignKeyDependencies = ({ entities, relationships }) => { + const entitySet = new Set(entities); + const childrenMap = new Map(); + const inDegree = new Map(); + + entities.forEach(entityId => { + inDegree.set(entityId, 0); + childrenMap.set(entityId, []); + }); + + relationships.forEach(relationship => { + const { parentCollection, childCollection } = relationship; + if (entitySet.has(parentCollection) && entitySet.has(childCollection) && parentCollection !== childCollection) { + childrenMap.get(parentCollection).push(childCollection); + inDegree.set(childCollection, (inDegree.get(childCollection) || 0) + 1); + } + }); + + const queue = entities.filter(entityId => (inDegree.get(entityId) || 0) === 0); + const sorted = []; + + while (queue.length > 0) { + const current = queue.shift(); + sorted.push(current); + + childrenMap.get(current).forEach(child => { + const newDegree = (inDegree.get(child) || 0) - 1; + inDegree.set(child, newDegree); + if (newDegree === 0) { + queue.push(child); + } + }); + } + + const remaining = entities.filter(entityId => !sorted.includes(entityId)); + return sorted.concat(remaining); +}; + const generateContainerScript = (data, logger, callback, app) => { try { const containerData = data.containerData; @@ -59,7 +97,12 @@ const generateContainerScript = (data, logger, callback, app) => { relatedSchemas: relatedSchemas, }); - const entities = data.entities.reduce((result, entityId) => { + const sortedEntities = sortEntitiesByForeignKeyDependencies({ + entities: data.entities, + relationships: data.relationships, + }); + + const entities = sortedEntities.reduce((result, entityId) => { const foreignKeys = foreignKeyHelper.getForeignKeyStatementsByHashItem(foreignKeyHashTable[entityId] || {}); const args = [ diff --git a/forward_engineering/helpers/alterScriptFromDeltaHelper.js b/forward_engineering/helpers/alterScriptFromDeltaHelper.js index 68f2033..b25981d 100644 --- a/forward_engineering/helpers/alterScriptFromDeltaHelper.js +++ b/forward_engineering/helpers/alterScriptFromDeltaHelper.js @@ -37,6 +37,57 @@ const getAlterContainersScripts = (schema, provider) => { }; }; +const sortCollectionsByRelationships = (collections, relationships) => { + const collectionToChildren = new Map(); // Map of collection IDs to their children + const collectionParentCount = new Map(); // Track how many parents each collection has + + // Initialize maps + for (const collection of collections) { + collectionToChildren.set(collection.role.id, []); + collectionParentCount.set(collection.role.id, 0); + } + + for (const relationship of relationships) { + const parent = relationship.role.parentCollection; + const child = relationship.role.childCollection; + if (collectionToChildren.has(parent)) { + collectionToChildren.get(parent).push(child); + } + collectionParentCount.set(child, (collectionParentCount.get(child) || 0) + 1); + } + + // Find collections with no parents + const queue = collections + .filter(collection => collectionParentCount.get(collection.role.id) === 0) + .map(collection => collection.role.id); + + const sortedIds = []; + + // Sort collections + while (queue.length > 0) { + const current = queue.shift(); + sortedIds.push(current); + + for (const child of collectionToChildren.get(current) || []) { + collectionParentCount.set(child, collectionParentCount.get(child) - 1); + if (collectionParentCount.get(child) <= 0) { + queue.push(child); + } + } + } + + // Add any unvisited collection + for (const collection of collections) { + if (!sortedIds.includes(collection.role.id)) { + sortedIds.unshift(collection.role.id); + } + } + + // Map back to collection objects in sorted order + const idToCollection = Object.fromEntries(collections.map(c => [c.role.id, c])); + return sortedIds.map(id => idToCollection[id]); +}; + const getAlterCollectionsScripts = ({ schema, definitions, provider, data, inlineDeltaRelationships }) => { let currentSchemaName = ''; @@ -55,11 +106,13 @@ const getAlterCollectionsScripts = ({ schema, definitions, provider, data, inlin const deletedCollectionsItems = getItems(schema, 'entities', 'deleted'); const modifiedCollectionsItems = getItems(schema, 'entities', 'modified'); - const addedCollectionsScripts = addedCollectionsItems - .filter(item => item.compMod?.created) - .flatMap(item => - setCurrentSchemaName(item, getAddCollectionsScripts(definitions, data, inlineDeltaRelationships)), - ); + const addedCollectionsScripts = addedCollectionsItems; + sortCollectionsByRelationships( + addedCollectionsItems.filter(collection => collection.compMod?.created), + inlineDeltaRelationships, + ).flatMap(item => + setCurrentSchemaName(item, getAddCollectionsScripts(definitions, data, inlineDeltaRelationships)), + ); const deletedCollectionsScripts = deletedCollectionsItems .filter(item => item.compMod?.deleted) .flatMap(getDeleteCollectionsScripts(provider)); From b2ccba9cdec1f8bc52149a0ebdc01807fa3c7fe4 Mon Sep 17 00:00:00 2001 From: Alik Rakhmonov Date: Tue, 16 Dec 2025 15:01:09 +0100 Subject: [PATCH 2/2] fix --- forward_engineering/helpers/alterScriptFromDeltaHelper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forward_engineering/helpers/alterScriptFromDeltaHelper.js b/forward_engineering/helpers/alterScriptFromDeltaHelper.js index b25981d..e6334e3 100644 --- a/forward_engineering/helpers/alterScriptFromDeltaHelper.js +++ b/forward_engineering/helpers/alterScriptFromDeltaHelper.js @@ -106,13 +106,13 @@ const getAlterCollectionsScripts = ({ schema, definitions, provider, data, inlin const deletedCollectionsItems = getItems(schema, 'entities', 'deleted'); const modifiedCollectionsItems = getItems(schema, 'entities', 'modified'); - const addedCollectionsScripts = addedCollectionsItems; - sortCollectionsByRelationships( + const addedCollectionsScripts = sortCollectionsByRelationships( addedCollectionsItems.filter(collection => collection.compMod?.created), inlineDeltaRelationships, ).flatMap(item => setCurrentSchemaName(item, getAddCollectionsScripts(definitions, data, inlineDeltaRelationships)), ); + const deletedCollectionsScripts = deletedCollectionsItems .filter(item => item.compMod?.deleted) .flatMap(getDeleteCollectionsScripts(provider));