Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion forward_engineering/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"value": {
"inline": {
"default": false,
"disabled": true,
"disabled": false,
"disabledLabel": ""
},
"separate": {
Expand Down
10 changes: 7 additions & 3 deletions forward_engineering/helpers/columnHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ const getTypeByProperty =
}
};

const getColumn = (name, type, comment, constraints, isActivated, generatedExpression) => ({
[name]: { type, comment, constraints, isActivated, generatedExpression },
const getColumn = (name, type, comment, constraints, isActivated, generatedExpression, maskingFunction) => ({
[name]: { type, comment, constraints, isActivated, generatedExpression, maskingFunction },
});

const getGeneratedExpression = (expressionData, defaultValue = '') => {
Expand Down Expand Up @@ -370,6 +370,7 @@ const getColumns = (jsonSchema, definitions, dbVersion) => {
},
property.isActivated,
getGeneratedExpression(property.generatedDefaultValue, property.default),
property.maskingFunction,
),
);
}, {});
Expand Down Expand Up @@ -403,12 +404,15 @@ const getColumnStatement = ({
isActivated,
isParentActivated,
generatedExpression,
maskingFunction,
}) => {
const commentStatement = comment ? ` COMMENT '${encodeStringLiteral(comment)}'` : '';
const constraintsStatement = constraints ? getColumnConstraintsStatement(constraints) : '';
const isColumnActivated = isParentActivated ? isActivated : true;
const maskingStatement = maskingFunction ? ` MASK ${maskingFunction}` : '';

return commentDeactivatedStatements(
`${replaceSpaceWithUnderscore(name)} ${type}${generatedExpression}${constraintsStatement}${commentStatement}`,
`${replaceSpaceWithUnderscore(name)} ${type}${generatedExpression}${maskingStatement}${constraintsStatement}${commentStatement}`,
isColumnActivated,
);
};
Expand Down
151 changes: 151 additions & 0 deletions forward_engineering/helpers/foreignKeyHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
const _ = require('lodash');
const schemaHelper = require('./jsonSchemaHelper');
const { getName, getTab, commentDeactivatedStatements, prepareName } = require('../utils/general');

const getIdToNameHashTable = (
relationships,
entities,
jsonSchemas,
internalDefinitions,
otherDefinitions,
relatedSchemas,
) => {
const entitiesForHashing = entities
.concat(Object.keys(relatedSchemas))
.filter(entityId =>
relationships.find(
relationship => relationship.childCollection === entityId || relationship.parentCollection === entityId,
),
);

return entitiesForHashing.reduce((hashTable, entityId) => {
return {
...hashTable,
...schemaHelper.getIdToNameHashTable(
[
jsonSchemas[entityId] ?? relatedSchemas[entityId],
internalDefinitions[entityId],
...otherDefinitions,
].filter(Boolean),
),
};
}, {});
};

const getForeignKeyHashTable = ({
relationships,
entities,
entityData,
jsonSchemas,
internalDefinitions,
otherDefinitions,
isContainerActivated,
relatedSchemas,
}) => {
const idToNameHashTable = getIdToNameHashTable(
relationships,
entities,
jsonSchemas,
internalDefinitions,
otherDefinitions,
relatedSchemas,
);

return relationships.reduce((hashTable, relationship) => {
if (!hashTable[relationship.childCollection]) {
hashTable[relationship.childCollection] = {};
}

const constraintName = relationship.code || relationship.name;
const parentSchema =
jsonSchemas[relationship.parentCollection] ?? relatedSchemas[relationship.parentCollection];
const childSchema = jsonSchemas[relationship.childCollection] ?? relatedSchemas[relationship.childCollection];
const parentDifferentSchemaName = prepareName(parentSchema?.bucketName) || '';
const parentTableData = getTab(0, entityData[relationship.parentCollection]);
const parentTableSingleName = prepareName(getName(parentTableData) || parentSchema?.collectionName) || '';
const parentTableName = parentDifferentSchemaName
? `${parentDifferentSchemaName}.${parentTableSingleName}`
: parentTableSingleName;
const childTableData = getTab(0, entityData[relationship.childCollection]);
const childTableName = prepareName(getName(childTableData) || childSchema?.collectionName) || '';
const groupKey = parentTableName + constraintName;
const childFieldActivated = relationship.childField.reduce((isActivated, field) => {
const fieldData = schemaHelper.getItemByPath(field.slice(1), childSchema);
return isActivated && _.get(fieldData, 'isActivated');
}, true);
const parentFieldActivated = relationship.parentField.reduce((isActivated, field) => {
const fieldData = schemaHelper.getItemByPath(field.slice(1), parentSchema);
return isActivated && _.get(fieldData, 'isActivated');
}, true);

if (!hashTable[relationship.childCollection][groupKey]) {
hashTable[relationship.childCollection][groupKey] = [];
}
const disableNoValidate = relationship?.customProperties?.disableNoValidate;

hashTable[relationship.childCollection][groupKey].push({
name: relationship.name,
code: relationship.code,
disableNoValidate: disableNoValidate,
parentTableName: parentTableName,
childTableName: childTableName,
parentColumn: getPreparedForeignColumns(relationship.parentField, idToNameHashTable),
childColumn: getPreparedForeignColumns(relationship.childField, idToNameHashTable),
isActivated:
isContainerActivated &&
_.get(parentTableData, 'isActivated') &&
_.get(childTableData, 'isActivated') &&
childFieldActivated &&
parentFieldActivated,
});

return hashTable;
}, {});
};

const getForeignKeyConstraint = ({ constraintName, childColumns, parentTableName, parentColumns }) => {
const constraintNameStatement = constraintName ? `CONSTRAINT ${prepareName(constraintName)} ` : '';
return `${constraintNameStatement}FOREIGN KEY (${childColumns}) REFERENCES ${parentTableName}(${parentColumns})`.trim();
};

const getForeignKeyStatementsByHashItem = hashItem => {
return Object.keys(hashItem || {})
.map(groupKey => {
const keys = hashItem[groupKey];
const firstKey = keys[0] || {};
const keyName = firstKey.code || firstKey.name || '';
const constraintName = keyName.includes(' ') ? `\`${keyName}\`` : keyName;
const parentTableName = firstKey.parentTableName;
const disableNoValidate = keys.some(item => item?.disableNoValidate);
const childColumns = keys.map(item => item.childColumn).join(', ');
const parentColumns = keys.map(item => item.parentColumn).join(', ');
const isActivated = firstKey.isActivated;

const statement = getForeignKeyConstraint({
constraintName,
childColumns,
parentTableName,
parentColumns,
disableNoValidate,
});

return commentDeactivatedStatements(statement, isActivated);
})
.join(',\n');
};

const getPreparedForeignColumns = (columnsPaths, idToNameHashTable) => {
if (columnsPaths.length > 0 && Array.isArray(columnsPaths[0])) {
return columnsPaths
.map(path => schemaHelper.getNameByPath(idToNameHashTable, (path || []).slice(1)))
.join(', ');
} else {
return schemaHelper.getNameByPath(idToNameHashTable, (columnsPaths || []).slice(1));
}
};

module.exports = {
getForeignKeyHashTable,
getForeignKeyStatementsByHashItem,
getForeignKeyConstraint,
};
25 changes: 22 additions & 3 deletions forward_engineering/helpers/scriptBuilder/feScriptBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const {
} = require('../../utils/general');
const { generateSamplesScript, generateSamplesForEntity } = require('../../sampleGeneration/sampleGenerationService');
const { getDataForSampleGeneration } = require('../../sampleGeneration/getDataForSampleGeneration');
const foreignKeyHelper = require('../foreignKeyHelper');

/**
* @param data {CoreData}
Expand Down Expand Up @@ -136,27 +137,45 @@ const getContainerLevelEntitiesScriptDtos =
}) => {
const scriptDtos = [];

const foreignKeyHashTable = foreignKeyHelper.getForeignKeyHashTable({
relationships: data.relationships,
entities: data.entities,
entityData: data.entityData,
jsonSchemas: entitiesJsonSchema,
internalDefinitions: internalDefinitions,
otherDefinitions: [modelDefinitions, externalDefinitions],
isContainerActivated: containerData[0]?.isActivated,
relatedSchemas: relatedSchemas,
});

for (const entityId of data.entities) {
const entityData = data.entityData[entityId];

const tableData = getTab(0, entityData);
const isStreaming = tableData?.streamingTable;
const dbVersion = data.modelData[0].dbVersion;
const likeTableData = data.entityData[getTab(0, entityData)?.like];
const likeTableData = data.entityData[tableData?.like];
const entityJsonSchema = entitiesJsonSchema[entityId];
const definitions = [internalDefinitions[entityId], modelDefinitions, externalDefinitions];
const createTableStatementArgs = [containerData, entityData, entityJsonSchema, definitions];

const foreignKeyStatement = foreignKeyHelper.getForeignKeyStatementsByHashItem(
foreignKeyHashTable[entityId] || {},
);

const tableStatement = getTableStatement(app)(
...createTableStatementArgs,
arePkFkConstraintsAvailable,
areNotNullConstraintsAvailable,
likeTableData,
dbVersion,
false,
foreignKeyStatement,
);

const indexScript = getIndexes(...createTableStatementArgs);

let relationshipScripts = [];
if (includeRelationshipsInEntityScripts && arePkFkConstraintsAvailable) {
if (includeRelationshipsInEntityScripts && arePkFkConstraintsAvailable && !isStreaming) {
const relationshipsWithThisTableAsChild = data.relationships.filter(
relationship => relationship.childCollection === entityId,
);
Expand Down
Loading