1
0
Fork 0
mirror of synced 2024-07-06 15:00:49 +12:00

Fix relationship types

This commit is contained in:
Adria Navarro 2023-10-05 14:25:25 +02:00
parent c8ffa98844
commit 21e2d7ddbe
4 changed files with 73 additions and 30 deletions

View file

@ -5,8 +5,11 @@ import {
FieldType,
FilterType,
IncludeRelationship,
ManyToManyRelationshipFieldMetadata,
OneToManyRelationshipFieldMetadata,
Operation,
PaginationJson,
RelationshipFieldMetadata,
RelationshipsJson,
RelationshipType,
Row,
@ -254,12 +257,20 @@ function fixArrayTypes(row: Row, table: Table) {
return row
}
function isOneSide(field: FieldSchema) {
function isOneSide(
field: RelationshipFieldMetadata
): field is OneToManyRelationshipFieldMetadata {
return (
field.relationshipType && field.relationshipType.split("-")[0] === "one"
)
}
function isManyToMany(
field: RelationshipFieldMetadata
): field is ManyToManyRelationshipFieldMetadata {
return !!(field as ManyToManyRelationshipFieldMetadata).through
}
function isEditableColumn(column: FieldSchema) {
const isExternalAutoColumn =
column.autocolumn &&
@ -352,11 +363,11 @@ export class ExternalRequest<T extends Operation> {
}
}
// many to many
else if (field.through) {
else if (isManyToMany(field)) {
// we're not inserting a doc, will be a bunch of update calls
const otherKey: string = field.throughFrom || linkTablePrimary
const thisKey: string = field.throughTo || tablePrimary
row[key].forEach((relationship: any) => {
for (const relationship of row[key]) {
manyRelationships.push({
tableId: field.through || field.tableId,
isUpdate: false,
@ -365,14 +376,14 @@ export class ExternalRequest<T extends Operation> {
// leave the ID for enrichment later
[thisKey]: `{{ literal ${tablePrimary} }}`,
})
})
}
}
// many to one
else {
const thisKey: string = "id"
// @ts-ignore
const otherKey: string = field.fieldName
row[key].forEach((relationship: any) => {
for (const relationship of row[key]) {
manyRelationships.push({
tableId: field.tableId,
isUpdate: true,
@ -381,7 +392,7 @@ export class ExternalRequest<T extends Operation> {
// leave the ID for enrichment later
[otherKey]: `{{ literal ${tablePrimary} }}`,
})
})
}
}
}
// we return the relationships that may need to be created in the through table
@ -551,20 +562,24 @@ export class ExternalRequest<T extends Operation> {
}
const definition: any = {
// if no foreign key specified then use the name of the field in other table
from: field.foreignKey || table.primary[0],
from: (field as any).foreignKey || table.primary[0],
to: field.fieldName,
tableName: linkTableName,
// need to specify where to put this back into
column: fieldName,
}
if (field.through) {
if ((field as ManyToManyRelationshipFieldMetadata).through) {
const { tableName: throughTableName } = breakExternalTableId(
field.through
(field as ManyToManyRelationshipFieldMetadata).through
)
definition.through = throughTableName
// don't support composite keys for relationships
definition.from = field.throughTo || table.primary[0]
definition.to = field.throughFrom || linkTable.primary[0]
definition.from =
(field as ManyToManyRelationshipFieldMetadata).throughTo ||
table.primary[0]
definition.to =
(field as ManyToManyRelationshipFieldMetadata).throughFrom ||
linkTable.primary[0]
definition.fromPrimary = table.primary[0]
definition.toPrimary = linkTable.primary[0]
}
@ -597,12 +612,15 @@ export class ExternalRequest<T extends Operation> {
continue
}
const isMany = field.relationshipType === RelationshipType.MANY_TO_MANY
const tableId = isMany ? field.through : field.tableId
const tableId = isMany
? (field as ManyToManyRelationshipFieldMetadata).through
: field.tableId
const { tableName: relatedTableName } = breakExternalTableId(tableId)
// @ts-ignore
const linkPrimaryKey = this.tables[relatedTableName].primary[0]
const manyKey = field.throughTo || primaryKey
const lookupField = isMany ? primaryKey : field.foreignKey
const manyKey =
(field as ManyToManyRelationshipFieldMetadata).throughTo || primaryKey
const lookupField = isMany ? primaryKey : (field as any).foreignKey
const fieldName = isMany ? manyKey : field.fieldName
if (!lookupField || !row[lookupField]) {
continue
@ -617,7 +635,10 @@ export class ExternalRequest<T extends Operation> {
})
// this is the response from knex if no rows found
const rows = !response[0].read ? response : []
const storeTo = isMany ? field.throughFrom || linkPrimaryKey : fieldName
const storeTo = isMany
? (field as ManyToManyRelationshipFieldMetadata).throughFrom ||
linkPrimaryKey
: fieldName
related[storeTo] = { rows, isMany, tableId }
}
return related

View file

@ -306,7 +306,8 @@ class OracleIntegration extends Sql implements DatasourcePlus {
presence: false,
},
...this.internalConvertType(oracleColumn),
}
} as any // TODO
table.schema[columnName] = fieldSchema
}

View file

@ -5,7 +5,13 @@ import { ObjectStoreBuckets } from "../../constants"
import { context, db as dbCore, objectStore } from "@budibase/backend-core"
import { InternalTables } from "../../db/utils"
import { TYPE_TRANSFORM_MAP } from "./map"
import { FieldSubtype, Row, RowAttachment, Table } from "@budibase/types"
import {
AutoColumnFieldMetadata,
FieldSubtype,
Row,
RowAttachment,
Table,
} from "@budibase/types"
import { cloneDeep } from "lodash/fp"
import {
processInputBBReferences,
@ -71,7 +77,7 @@ export function processAutoColumn(
continue
}
if (!schema.subtype) {
schema = fixAutoColumnSubType(schema)
schema = fixAutoColumnSubType(schema as AutoColumnFieldMetadata)
}
switch (schema.subtype) {
case AutoFieldSubTypes.CREATED_BY:
@ -94,8 +100,12 @@ export function processAutoColumn(
break
case AutoFieldSubTypes.AUTO_ID:
if (creating) {
schema.lastID = !schema.lastID ? BASE_AUTO_ID : schema.lastID + 1
row[key] = schema.lastID
const safeSchema = schema as AutoColumnFieldMetadata
safeSchema.lastID = !safeSchema.lastID
? BASE_AUTO_ID
: safeSchema.lastID + 1
row[key] = safeSchema.lastID
}
break
}

View file

@ -15,22 +15,33 @@ export interface UIFieldMetadata {
icon?: string
}
interface ManyToManyRelationshipFieldMetadata {
interface BaseRelationshipFieldMetadata extends BaseFieldSchema {
type: FieldType.LINK
main?: boolean
fieldName?: string
tableId: string
}
export interface ManyToManyRelationshipFieldMetadata
extends BaseRelationshipFieldMetadata {
relationshipType: RelationshipType.MANY_TO_MANY
through: string
throughFrom: string
throughTo: string
}
interface OneSidedRelationshipFieldMetadata {
relationshipType: RelationshipType.ONE_TO_MANY | RelationshipType.MANY_TO_ONE
export interface OneToManyRelationshipFieldMetadata
extends BaseRelationshipFieldMetadata {
relationshipType: RelationshipType.ONE_TO_MANY
foreignKey: string
}
export type RelationshipFieldMetadata = BaseFieldSchema & {
type: FieldType.LINK
main?: boolean
fieldName?: string
tableId: string
} & (ManyToManyRelationshipFieldMetadata | OneSidedRelationshipFieldMetadata)
export interface ManyToOneRelationshipFieldMetadata
extends BaseRelationshipFieldMetadata {
relationshipType: RelationshipType.MANY_TO_ONE
foreignKey: string
}
export type RelationshipFieldMetadata =
| ManyToManyRelationshipFieldMetadata
| OneToManyRelationshipFieldMetadata
| ManyToOneRelationshipFieldMetadata
export interface AutoColumnFieldMetadata extends BaseFieldSchema {
type: FieldType.AUTO
@ -106,6 +117,7 @@ interface BaseFieldSchema extends UIFieldMetadata {
externalType?: string
constraints?: FieldConstraints
autocolumn?: boolean
autoReason?: AutoReason
subtype?: string
}
@ -113,7 +125,6 @@ interface OtherFieldMetadata extends BaseFieldSchema {
type: Exclude<
FieldType,
| FieldType.DATETIME
| FieldType.DATETIME
| FieldType.LINK
| FieldType.AUTO
| FieldType.STRING