Skip to content

Commit 9f035a0

Browse files
HCK-13050: generate FK in delta models inline or separate (#172)
* HCK-13050: generate FK in delta models inline or separate * fix
1 parent 6230157 commit 9f035a0

File tree

4 files changed

+129
-12
lines changed

4 files changed

+129
-12
lines changed

forward_engineering/alterScript/alterScriptFromDeltaHelper.js

Lines changed: 104 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,57 @@ const getAlterContainersScriptDtos = ({ collection }) => {
7878
return [...addContainersScriptDtos, ...deleteContainersScriptDtos, ...modifyContainersScriptDtos].filter(Boolean);
7979
};
8080

81+
const sortCollectionsByRelationships = (collections, relationships) => {
82+
const collectionToChildren = new Map(); // Map of collection IDs to their children
83+
const collectionParentCount = new Map(); // Track how many parents each collection has
84+
85+
// Initialize maps
86+
for (const collection of collections) {
87+
collectionToChildren.set(collection.role.id, []);
88+
collectionParentCount.set(collection.role.id, 0);
89+
}
90+
91+
for (const relationship of relationships) {
92+
const parent = relationship.role.parentCollection;
93+
const child = relationship.role.childCollection;
94+
if (collectionToChildren.has(parent)) {
95+
collectionToChildren.get(parent).push(child);
96+
}
97+
collectionParentCount.set(child, (collectionParentCount.get(child) || 0) + 1);
98+
}
99+
100+
// Find collections with no parents
101+
const queue = collections
102+
.filter(collection => collectionParentCount.get(collection.role.id) === 0)
103+
.map(collection => collection.role.id);
104+
105+
const sortedIds = [];
106+
107+
// Sort collections
108+
while (queue.length > 0) {
109+
const current = queue.shift();
110+
sortedIds.push(current);
111+
112+
for (const child of collectionToChildren.get(current) || []) {
113+
collectionParentCount.set(child, collectionParentCount.get(child) - 1);
114+
if (collectionParentCount.get(child) <= 0) {
115+
queue.push(child);
116+
}
117+
}
118+
}
119+
120+
// Add any unvisited collection
121+
for (const collection of collections) {
122+
if (!sortedIds.includes(collection.role.id)) {
123+
sortedIds.unshift(collection.role.id);
124+
}
125+
}
126+
127+
// Map back to collection objects in sorted order
128+
const idToCollection = Object.fromEntries(collections.map(c => [c.role.id, c]));
129+
return sortedIds.map(id => idToCollection[id]);
130+
};
131+
81132
/**
82133
* @param dto {{
83134
* collection: Object,
@@ -96,6 +147,7 @@ const getAlterCollectionsScriptDtos = ({
96147
modelDefinitions,
97148
internalDefinitions,
98149
externalDefinitions,
150+
inlineDeltaRelationships,
99151
}) => {
100152
const createScriptsData = []
101153
.concat(collection.properties?.entities?.properties?.added?.items)
@@ -112,9 +164,19 @@ const getAlterCollectionsScriptDtos = ({
112164
.filter(Boolean)
113165
.map(item => Object.values(item.properties)[0]);
114166

115-
const createCollectionsScriptDtos = createScriptsData
116-
.filter(collection => collection.compMod?.created)
117-
.map(getAddCollectionScriptDto({ app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions }));
167+
const createCollectionsScriptDtos = sortCollectionsByRelationships(
168+
createScriptsData.filter(collection => collection.compMod?.created),
169+
inlineDeltaRelationships,
170+
).map(
171+
getAddCollectionScriptDto({
172+
app,
173+
dbVersion,
174+
modelDefinitions,
175+
internalDefinitions,
176+
externalDefinitions,
177+
inlineDeltaRelationships,
178+
}),
179+
);
118180

119181
const deleteCollectionScriptDtos = deleteScriptsData
120182
.filter(collection => collection.compMod?.deleted)
@@ -138,13 +200,13 @@ const getAlterCollectionsScriptDtos = ({
138200
);
139201

140202
return [
141-
...createCollectionsScriptDtos,
142203
...deleteCollectionScriptDtos,
143204
...modifyCollectionScriptDtos,
144205
...addColumnScriptDtos,
145206
...deleteColumnScriptDtos,
146207
...modifyColumnScriptDtos,
147208
...modifyCollectionKeysScriptDtos,
209+
...createCollectionsScriptDtos,
148210
].filter(Boolean);
149211
};
150212

@@ -261,26 +323,35 @@ const getAlterModelDefinitionsScriptDtos = ({
261323
/**
262324
* @return Array<AlterScriptDto>
263325
* */
264-
const getAlterRelationshipsScriptDtos = ({ collection, app }) => {
326+
const getAlterRelationshipsScriptDtos = ({ collection, app, ignoreRelationshipIDs = [] }) => {
265327
const ddlProvider = require('../ddlProvider/ddlProvider')(null, null, app);
266328

267329
const addedRelationships = []
268330
.concat(collection.properties?.relationships?.properties?.added?.items)
269331
.filter(Boolean)
270332
.map(item => Object.values(item.properties)[0])
271-
.filter(relationship => relationship?.role?.compMod?.created);
333+
.filter(
334+
relationship =>
335+
relationship?.role?.compMod?.created && !ignoreRelationshipIDs.includes(relationship?.role?.id),
336+
);
272337

273338
const deletedRelationships = []
274339
.concat(collection.properties?.relationships?.properties?.deleted?.items)
275340
.filter(Boolean)
276341
.map(item => Object.values(item.properties)[0])
277-
.filter(relationship => relationship?.role?.compMod?.deleted);
342+
.filter(
343+
relationship =>
344+
relationship?.role?.compMod?.deleted && !ignoreRelationshipIDs.includes(relationship?.role?.id),
345+
);
278346

279347
const modifiedRelationships = []
280348
.concat(collection.properties?.relationships?.properties?.modified?.items)
281349
.filter(Boolean)
282350
.map(item => Object.values(item.properties)[0])
283-
.filter(relationship => relationship?.role?.compMod?.modified);
351+
.filter(
352+
relationship =>
353+
relationship?.role?.compMod?.modified && !ignoreRelationshipIDs.includes(relationship?.role?.id),
354+
);
284355

285356
const deleteFkScriptDtos = getDeleteForeignKeyScriptDtos(ddlProvider)(deletedRelationships);
286357
const addFkScriptDtos = getAddForeignKeyScriptDtos(ddlProvider)(addedRelationships);
@@ -350,6 +421,24 @@ const getAlterContainersSequencesScriptDtos = ({ collection, app }) => {
350421
);
351422
};
352423

424+
const getInlineRelationships = ({ collection, options }) => {
425+
if (options?.scriptGenerationOptions?.feActiveOptions?.foreignKeys !== 'inline') {
426+
return [];
427+
}
428+
429+
const addedCollectionIDs = []
430+
.concat(collection.properties?.entities?.properties?.added?.items)
431+
.filter(item => item && Object.values(item.properties)?.[0]?.compMod?.created)
432+
.map(item => Object.values(item.properties)[0].role.id);
433+
434+
const addedRelationships = []
435+
.concat(collection.properties?.relationships?.properties?.added?.items)
436+
.map(item => item && Object.values(item.properties)[0])
437+
.filter(r => r?.role?.compMod?.created && addedCollectionIDs.includes(r?.role?.childCollection));
438+
439+
return addedRelationships;
440+
};
441+
353442
/**
354443
* @param data {CoreData}
355444
* @param app {App}
@@ -367,6 +456,7 @@ const getAlterScriptDtos = (data, app) => {
367456
const internalDefinitions = JSON.parse(data.internalDefinitions);
368457
const externalDefinitions = JSON.parse(data.externalDefinitions);
369458
const dbVersion = data.modelData[0]?.dbVersion;
459+
const inlineDeltaRelationships = getInlineRelationships({ collection, options: data.options });
370460
const containersScriptDtos = getAlterContainersScriptDtos({ collection });
371461
const collectionsScriptDtos = getAlterCollectionsScriptDtos({
372462
collection,
@@ -375,6 +465,7 @@ const getAlterScriptDtos = (data, app) => {
375465
modelDefinitions,
376466
internalDefinitions,
377467
externalDefinitions,
468+
inlineDeltaRelationships,
378469
});
379470
const viewScriptDtos = getAlterViewScriptDtos(collection, app);
380471
const modelDefinitionsScriptDtos = getAlterModelDefinitionsScriptDtos({
@@ -385,7 +476,11 @@ const getAlterScriptDtos = (data, app) => {
385476
internalDefinitions,
386477
externalDefinitions,
387478
});
388-
const relationshipScriptDtos = getAlterRelationshipsScriptDtos({ collection, app });
479+
const relationshipScriptDtos = getAlterRelationshipsScriptDtos({
480+
collection,
481+
app,
482+
ignoreRelationshipIDs: inlineDeltaRelationships.map(relationship => relationship.role.id),
483+
});
389484
const containersSequencesScriptDtos = getAlterContainersSequencesScriptDtos({ collection, app });
390485

391486
return [

forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ const {
2424
isParentContainerActivated,
2525
isObjectInDeltaModelActivated,
2626
} = require('../../utils/general');
27+
const { getRelationshipName } = require('./alterRelationshipsHelper');
2728

2829
/**
2930
* @return {(collection: AlterCollectionDto) => AlterScriptDto | undefined}
3031
* */
3132
const getAddCollectionScriptDto =
32-
({ app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions }) =>
33+
({ app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions, inlineDeltaRelationships = [] }) =>
3334
collection => {
3435
const ddlProvider = require('../../ddlProvider/ddlProvider')(null, null, app);
3536
const { createColumnDefinitionBySchema } = require('./createColumnDefinition')(app);
@@ -58,11 +59,31 @@ const getAddCollectionScriptDto =
5859
const checkConstraints = (jsonSchema.chkConstr || []).map(check =>
5960
ddlProvider.createCheckConstraint(ddlProvider.hydrateCheckConstraint(check)),
6061
);
62+
const foreignKeyConstraints = inlineDeltaRelationships
63+
.filter(relationship => relationship.role.childCollection === collection.role.id)
64+
.map(relationship => {
65+
const compMod = relationship.role.compMod;
66+
const relationshipName =
67+
compMod.code?.new || compMod.name?.new || getRelationshipName(relationship) || '';
68+
return ddlProvider.createForeignKeyConstraint({
69+
name: relationshipName,
70+
foreignKey: compMod.child.collection.fkFields,
71+
primaryKey: compMod.parent.collection.fkFields,
72+
customProperties: compMod.customProperties?.new,
73+
foreignTable: compMod.child.collection.name,
74+
foreignSchemaName: compMod.child.bucket.name,
75+
foreignTableActivated: compMod.child.collection.isActivated,
76+
primaryTable: compMod.parent.collection.name,
77+
primarySchemaName: compMod.parent.bucket.name,
78+
primaryTableActivated: compMod.parent.collection.isActivated,
79+
isActivated: Boolean(relationship.role?.compMod?.isActivated?.new),
80+
});
81+
});
6182
const tableData = {
6283
name: getEntityName(jsonSchema),
6384
columns: columnDefinitions.map(ddlProvider.convertColumnDefinition),
6485
checkConstraints: checkConstraints,
65-
foreignKeyConstraints: [],
86+
foreignKeyConstraints,
6687
schemaData,
6788
columnDefinitions,
6889
dbData: { dbVersion },

forward_engineering/alterScript/alterScriptHelpers/alterRelationshipsHelper.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,5 @@ module.exports = {
160160
getDeleteForeignKeyScriptDtos,
161161
getModifyForeignKeyScriptDtos,
162162
getAddForeignKeyScriptDtos,
163+
getRelationshipName,
163164
};

forward_engineering/ddlProvider/ddlProvider.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ module.exports = (baseProvider, options, app) => {
361361
additionalPropertiesForForeignKey(customProperties);
362362

363363
const foreignKeyStatement = assignTemplates(templates.createForeignKeyConstraint, {
364-
primaryTable: getNamePrefixedWithSchemaName(primaryTable, primarySchemaName || schemaData.schemaName),
364+
primaryTable: getNamePrefixedWithSchemaName(primaryTable, primarySchemaName || schemaData?.schemaName),
365365
name: name ? `CONSTRAINT ${wrapInQuotes(name)}` : '',
366366
foreignKey: areKeysActivated ? foreignKeysToString(foreignKey) : foreignActiveKeysToString(foreignKey),
367367
primaryKey: areKeysActivated ? foreignKeysToString(primaryKey) : foreignActiveKeysToString(primaryKey),

0 commit comments

Comments
 (0)