Merge pull request #14966 from Budibase/BUDI-8746/multiple-many-to-many-relationships-between-two-tables

Support setting multiple many to many relationships between two tables
This commit is contained in:
Adria Navarro 2024-11-05 12:13:53 +01:00 committed by GitHub
commit 40d19a5d06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 18 deletions

View File

@ -65,7 +65,7 @@
let tableOptions let tableOptions
let errorChecker = new RelationshipErrorChecker( let errorChecker = new RelationshipErrorChecker(
invalidThroughTable, invalidThroughTable,
relationshipExists manyToManyRelationshipExistsFn
) )
let errors = {} let errors = {}
let fromPrimary, fromForeign, fromColumn, toColumn let fromPrimary, fromForeign, fromColumn, toColumn
@ -125,7 +125,7 @@
} }
return false return false
} }
function relationshipExists() { function manyToManyRelationshipExistsFn() {
if ( if (
originalFromTable && originalFromTable &&
originalToTable && originalToTable &&
@ -141,16 +141,14 @@
datasource.entities[getTable(toId).name].schema datasource.entities[getTable(toId).name].schema
).filter(value => value.through) ).filter(value => value.through)
const matchAgainstUserInput = (fromTableId, toTableId) => const matchAgainstUserInput = link =>
(fromTableId === fromId && toTableId === toId) || (link.throughTo === throughToKey &&
(fromTableId === toId && toTableId === fromId) link.throughFrom === throughFromKey) ||
(link.throughTo === throughFromKey && link.throughFrom === throughToKey)
return !!fromThroughLinks.find(from => const allLinks = [...fromThroughLinks, ...toThroughLinks]
toThroughLinks.find( return !!allLinks.find(
to => link => link.through === throughId && matchAgainstUserInput(link)
from.through === to.through &&
matchAgainstUserInput(from.tableId, to.tableId)
)
) )
} }
@ -181,16 +179,15 @@
relationshipType: errorChecker.relationshipTypeSet(relationshipType), relationshipType: errorChecker.relationshipTypeSet(relationshipType),
fromTable: fromTable:
errorChecker.tableSet(fromTable) || errorChecker.tableSet(fromTable) ||
errorChecker.doesRelationshipExists() ||
errorChecker.differentTables(fromId, toId, throughId), errorChecker.differentTables(fromId, toId, throughId),
toTable: toTable:
errorChecker.tableSet(toTable) || errorChecker.tableSet(toTable) ||
errorChecker.doesRelationshipExists() ||
errorChecker.differentTables(toId, fromId, throughId), errorChecker.differentTables(toId, fromId, throughId),
throughTable: throughTable:
errorChecker.throughTableSet(throughTable) || errorChecker.throughTableSet(throughTable) ||
errorChecker.throughIsNullable() || errorChecker.throughIsNullable() ||
errorChecker.differentTables(throughId, fromId, toId), errorChecker.differentTables(throughId, fromId, toId) ||
errorChecker.doesRelationshipExists(),
throughFromKey: throughFromKey:
errorChecker.manyForeignKeySet(throughFromKey) || errorChecker.manyForeignKeySet(throughFromKey) ||
errorChecker.manyTypeMismatch( errorChecker.manyTypeMismatch(
@ -198,7 +195,8 @@
throughTable, throughTable,
fromTable.primary[0], fromTable.primary[0],
throughToKey throughToKey
), ) ||
errorChecker.differentColumns(throughFromKey, throughToKey),
throughToKey: throughToKey:
errorChecker.manyForeignKeySet(throughToKey) || errorChecker.manyForeignKeySet(throughToKey) ||
errorChecker.manyTypeMismatch( errorChecker.manyTypeMismatch(
@ -372,6 +370,16 @@
fromColumn = selectedFromTable.name fromColumn = selectedFromTable.name
fromPrimary = selectedFromTable?.primary[0] || null fromPrimary = selectedFromTable?.primary[0] || null
} }
if (relationshipType === RelationshipType.MANY_TO_MANY) {
relationshipPart1 = PrettyRelationshipDefinitions.MANY
relationshipPart2 = PrettyRelationshipDefinitions.MANY
} else if (relationshipType === RelationshipType.MANY_TO_ONE) {
relationshipPart1 = PrettyRelationshipDefinitions.ONE
relationshipPart2 = PrettyRelationshipDefinitions.MANY
} else {
relationshipPart1 = PrettyRelationshipDefinitions.MANY
relationshipPart2 = PrettyRelationshipDefinitions.ONE
}
}) })
</script> </script>

View File

@ -3,6 +3,7 @@ import { RelationshipType } from "@budibase/types"
const typeMismatch = "Column type of the foreign key must match the primary key" const typeMismatch = "Column type of the foreign key must match the primary key"
const columnBeingUsed = "Column name cannot be an existing column" const columnBeingUsed = "Column name cannot be an existing column"
const mustBeDifferentTables = "From/to/through tables must be different" const mustBeDifferentTables = "From/to/through tables must be different"
const mustBeDifferentColumns = "Foreign keys must be different"
const primaryKeyNotSet = "Please pick the primary key" const primaryKeyNotSet = "Please pick the primary key"
const throughNotNullable = const throughNotNullable =
"Ensure non-key columns are nullable or auto-generated" "Ensure non-key columns are nullable or auto-generated"
@ -30,9 +31,9 @@ function typeMismatchCheck(fromTable, toTable, primary, foreign) {
} }
export class RelationshipErrorChecker { export class RelationshipErrorChecker {
constructor(invalidThroughTableFn, relationshipExistsFn) { constructor(invalidThroughTableFn, manyToManyRelationshipExistsFn) {
this.invalidThroughTable = invalidThroughTableFn this.invalidThroughTable = invalidThroughTableFn
this.relationshipExists = relationshipExistsFn this.manyToManyRelationshipExists = manyToManyRelationshipExistsFn
} }
setType(type) { setType(type) {
@ -72,7 +73,7 @@ export class RelationshipErrorChecker {
} }
doesRelationshipExists() { doesRelationshipExists() {
return this.isMany() && this.relationshipExists() return this.isMany() && this.manyToManyRelationshipExists()
? relationshipAlreadyExists ? relationshipAlreadyExists
: null : null
} }
@ -83,6 +84,11 @@ export class RelationshipErrorChecker {
return error ? mustBeDifferentTables : null return error ? mustBeDifferentTables : null
} }
differentColumns(columnA, columnB) {
const error = columnA && columnB && columnA === columnB
return error ? mustBeDifferentColumns : null
}
columnBeingUsed(table, column, ogName) { columnBeingUsed(table, column, ogName) {
return isColumnNameBeingUsed(table, column, ogName) ? columnBeingUsed : null return isColumnNameBeingUsed(table, column, ogName) ? columnBeingUsed : null
} }