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

View file

@ -306,7 +306,8 @@ class OracleIntegration extends Sql implements DatasourcePlus {
presence: false, presence: false,
}, },
...this.internalConvertType(oracleColumn), ...this.internalConvertType(oracleColumn),
} } as any // TODO
table.schema[columnName] = fieldSchema 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 { context, db as dbCore, objectStore } from "@budibase/backend-core"
import { InternalTables } from "../../db/utils" import { InternalTables } from "../../db/utils"
import { TYPE_TRANSFORM_MAP } from "./map" 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 { cloneDeep } from "lodash/fp"
import { import {
processInputBBReferences, processInputBBReferences,
@ -71,7 +77,7 @@ export function processAutoColumn(
continue continue
} }
if (!schema.subtype) { if (!schema.subtype) {
schema = fixAutoColumnSubType(schema) schema = fixAutoColumnSubType(schema as AutoColumnFieldMetadata)
} }
switch (schema.subtype) { switch (schema.subtype) {
case AutoFieldSubTypes.CREATED_BY: case AutoFieldSubTypes.CREATED_BY:
@ -94,8 +100,12 @@ export function processAutoColumn(
break break
case AutoFieldSubTypes.AUTO_ID: case AutoFieldSubTypes.AUTO_ID:
if (creating) { if (creating) {
schema.lastID = !schema.lastID ? BASE_AUTO_ID : schema.lastID + 1 const safeSchema = schema as AutoColumnFieldMetadata
row[key] = schema.lastID
safeSchema.lastID = !safeSchema.lastID
? BASE_AUTO_ID
: safeSchema.lastID + 1
row[key] = safeSchema.lastID
} }
break break
} }

View file

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