diff --git a/reverse_engineering/helpers/bigQueryHelper.js b/reverse_engineering/helpers/bigQueryHelper.js index 9c6eacf..90022b3 100644 --- a/reverse_engineering/helpers/bigQueryHelper.js +++ b/reverse_engineering/helpers/bigQueryHelper.js @@ -27,22 +27,31 @@ const createBigQueryHelper = (client, log) => { return ( await client.query({ query: `SELECT - CCU.column_name as \`parent_column\`, - KCU.column_name as \`child_column\`, + PK.column_name as \`parent_column\`, + FK.column_name as \`child_column\`, + FK.ordinal_position, TC.constraint_catalog, TC.constraint_name, TC.constraint_schema, TC.constraint_type, TC.table_catalog, - CCU.table_schema as \`parent_schema\`, - KCU.table_schema as \`child_schema\`, - CCU.table_name as \`parent_table\`, - KCU.table_name as \`child_table\` - FROM (${projectId}.${datasetId}.INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS CCU - INNER JOIN ${projectId}.${datasetId}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU - USING(constraint_name)) + REF.table_schema as \`parent_schema\`, + FK.table_schema as \`child_schema\`, + REF.table_name as \`parent_table\`, + FK.table_name as \`child_table\` + FROM ${projectId}.${datasetId}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS FK INNER JOIN ${projectId}.${datasetId}.INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC USING(constraint_name) + INNER JOIN ( + SELECT DISTINCT constraint_name, table_schema, table_name + FROM ${projectId}.${datasetId}.INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE + ) AS REF + USING(constraint_name) + INNER JOIN ${projectId}.${datasetId}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS PK + ON PK.table_schema = REF.table_schema + AND PK.table_name = REF.table_name + AND PK.position_in_unique_constraint IS NULL + AND PK.ordinal_position = FK.position_in_unique_constraint WHERE TC.constraint_type = "FOREIGN KEY";`, }) )[0]; diff --git a/reverse_engineering/helpers/constraintsHelper.js b/reverse_engineering/helpers/constraintsHelper.js index bef9dba..d30948c 100644 --- a/reverse_engineering/helpers/constraintsHelper.js +++ b/reverse_engineering/helpers/constraintsHelper.js @@ -90,39 +90,28 @@ const getConstraintBusinessName = constraintNameFromCloud => { }; const reverseForeignKeys = foreignKeyConstraintsData => { - return foreignKeyConstraintsData.reduce((constraints, fkConstraintData) => { - const constraintNameToUse = getConstraintBusinessName(fkConstraintData.constraint_name); - const constraintInList = constraints.find(({ relationshipName }) => relationshipName === constraintNameToUse); - const { parent_column, child_column } = fkConstraintData; - if (constraintInList) { - const isParentAdded = constraintInList.parentField.includes(parent_column); - const isChildAdded = constraintInList.childField.includes(child_column); - const newConstraintData = { - ...constraintInList, - childField: isChildAdded ? constraintInList.childField : [...constraintInList.childField, child_column], - parentField: isParentAdded - ? constraintInList.parentField - : [...constraintInList.parentField, parent_column], - }; - return [ - ...constraints.filter(({ relationshipName }) => relationshipName !== constraintNameToUse), - newConstraintData, - ]; - } else { - const newConstraint = { - relationshipName: constraintNameToUse, - relationshipType: 'Foreign Key', - childDbName: fkConstraintData.child_schema, - childCollection: fkConstraintData.child_table, - childField: [fkConstraintData.child_column], - dbName: fkConstraintData.parent_schema, - parentCollection: fkConstraintData.parent_table, - parentField: [fkConstraintData.parent_column], - relationshipInfo: {}, - }; - return [...constraints, newConstraint]; - } - }, []); + const constraintNames = [ + ...new Set(foreignKeyConstraintsData.map(({ constraint_name }) => getConstraintBusinessName(constraint_name))), + ]; + + return constraintNames.map(constraintName => { + const columns = foreignKeyConstraintsData + .filter(({ constraint_name }) => getConstraintBusinessName(constraint_name) === constraintName) + .toSorted((a, b) => a.ordinal_position - b.ordinal_position); + const [firstColumn] = columns; + + return { + relationshipName: constraintName, + relationshipType: 'Foreign Key', + childDbName: firstColumn.child_schema, + childCollection: firstColumn.child_table, + childField: columns.map(({ child_column }) => child_column), + dbName: firstColumn.parent_schema, + parentCollection: firstColumn.parent_table, + parentField: columns.map(({ parent_column }) => parent_column), + relationshipInfo: {}, + }; + }); }; module.exports = {