Skip to content

Commit 4ed1727

Browse files
HCK-13862: fix order of tables with FKs (#133)
* HCK-13862: fix order of tables with FKs * fix
1 parent 9bc6e62 commit 4ed1727

2 files changed

Lines changed: 102 additions & 6 deletions

File tree

forward_engineering/generateContainerScript.js

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,44 @@ const { parseEntities } = require('./helpers/parseEntities');
1111
const { getWorkloadManagementStatements } = require('./helpers/getWorkloadManagementStatements');
1212
const { getIsPkOrFkConstraintAvailable } = require('./helpers/constraintHelper');
1313

14+
const sortEntitiesByForeignKeyDependencies = ({ entities, relationships }) => {
15+
const entitySet = new Set(entities);
16+
const childrenMap = new Map();
17+
const inDegree = new Map();
18+
19+
entities.forEach(entityId => {
20+
inDegree.set(entityId, 0);
21+
childrenMap.set(entityId, []);
22+
});
23+
24+
relationships.forEach(relationship => {
25+
const { parentCollection, childCollection } = relationship;
26+
if (entitySet.has(parentCollection) && entitySet.has(childCollection) && parentCollection !== childCollection) {
27+
childrenMap.get(parentCollection).push(childCollection);
28+
inDegree.set(childCollection, (inDegree.get(childCollection) || 0) + 1);
29+
}
30+
});
31+
32+
const queue = entities.filter(entityId => (inDegree.get(entityId) || 0) === 0);
33+
const sorted = [];
34+
35+
while (queue.length > 0) {
36+
const current = queue.shift();
37+
sorted.push(current);
38+
39+
childrenMap.get(current).forEach(child => {
40+
const newDegree = (inDegree.get(child) || 0) - 1;
41+
inDegree.set(child, newDegree);
42+
if (newDegree === 0) {
43+
queue.push(child);
44+
}
45+
});
46+
}
47+
48+
const remaining = entities.filter(entityId => !sorted.includes(entityId));
49+
return sorted.concat(remaining);
50+
};
51+
1452
const generateContainerScript = (data, logger, callback, app) => {
1553
try {
1654
const containerData = data.containerData;
@@ -59,7 +97,12 @@ const generateContainerScript = (data, logger, callback, app) => {
5997
relatedSchemas: relatedSchemas,
6098
});
6199

62-
const entities = data.entities.reduce((result, entityId) => {
100+
const sortedEntities = sortEntitiesByForeignKeyDependencies({
101+
entities: data.entities,
102+
relationships: data.relationships,
103+
});
104+
105+
const entities = sortedEntities.reduce((result, entityId) => {
63106
const foreignKeys = foreignKeyHelper.getForeignKeyStatementsByHashItem(foreignKeyHashTable[entityId] || {});
64107

65108
const args = [

forward_engineering/helpers/alterScriptFromDeltaHelper.js

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,57 @@ const getAlterContainersScripts = (schema, provider) => {
3737
};
3838
};
3939

40+
const sortCollectionsByRelationships = (collections, relationships) => {
41+
const collectionToChildren = new Map(); // Map of collection IDs to their children
42+
const collectionParentCount = new Map(); // Track how many parents each collection has
43+
44+
// Initialize maps
45+
for (const collection of collections) {
46+
collectionToChildren.set(collection.role.id, []);
47+
collectionParentCount.set(collection.role.id, 0);
48+
}
49+
50+
for (const relationship of relationships) {
51+
const parent = relationship.role.parentCollection;
52+
const child = relationship.role.childCollection;
53+
if (collectionToChildren.has(parent)) {
54+
collectionToChildren.get(parent).push(child);
55+
}
56+
collectionParentCount.set(child, (collectionParentCount.get(child) || 0) + 1);
57+
}
58+
59+
// Find collections with no parents
60+
const queue = collections
61+
.filter(collection => collectionParentCount.get(collection.role.id) === 0)
62+
.map(collection => collection.role.id);
63+
64+
const sortedIds = [];
65+
66+
// Sort collections
67+
while (queue.length > 0) {
68+
const current = queue.shift();
69+
sortedIds.push(current);
70+
71+
for (const child of collectionToChildren.get(current) || []) {
72+
collectionParentCount.set(child, collectionParentCount.get(child) - 1);
73+
if (collectionParentCount.get(child) <= 0) {
74+
queue.push(child);
75+
}
76+
}
77+
}
78+
79+
// Add any unvisited collection
80+
for (const collection of collections) {
81+
if (!sortedIds.includes(collection.role.id)) {
82+
sortedIds.unshift(collection.role.id);
83+
}
84+
}
85+
86+
// Map back to collection objects in sorted order
87+
const idToCollection = Object.fromEntries(collections.map(c => [c.role.id, c]));
88+
return sortedIds.map(id => idToCollection[id]);
89+
};
90+
4091
const getAlterCollectionsScripts = ({ schema, definitions, provider, data, inlineDeltaRelationships }) => {
4192
let currentSchemaName = '';
4293

@@ -55,11 +106,13 @@ const getAlterCollectionsScripts = ({ schema, definitions, provider, data, inlin
55106
const deletedCollectionsItems = getItems(schema, 'entities', 'deleted');
56107
const modifiedCollectionsItems = getItems(schema, 'entities', 'modified');
57108

58-
const addedCollectionsScripts = addedCollectionsItems
59-
.filter(item => item.compMod?.created)
60-
.flatMap(item =>
61-
setCurrentSchemaName(item, getAddCollectionsScripts(definitions, data, inlineDeltaRelationships)),
62-
);
109+
const addedCollectionsScripts = sortCollectionsByRelationships(
110+
addedCollectionsItems.filter(collection => collection.compMod?.created),
111+
inlineDeltaRelationships,
112+
).flatMap(item =>
113+
setCurrentSchemaName(item, getAddCollectionsScripts(definitions, data, inlineDeltaRelationships)),
114+
);
115+
63116
const deletedCollectionsScripts = deletedCollectionsItems
64117
.filter(item => item.compMod?.deleted)
65118
.flatMap(getDeleteCollectionsScripts(provider));

0 commit comments

Comments
 (0)