Fix to make foreign keys auto-columns when used in relationships as well as making sure that when fetching tables that they can be removed, using the old fetch mechanism (to be replaced, but needs to work for now).

This commit is contained in:
mike12345567 2023-06-23 18:09:52 +01:00
parent 4788972362
commit c2b4dec88f
5 changed files with 84 additions and 18 deletions

View File

@ -183,9 +183,7 @@ export async function buildSchemaFromDb(ctx: UserCtx) {
let { tables, error } = await buildSchemaHelper(datasource) let { tables, error } = await buildSchemaHelper(datasource)
if (tablesFilter) { if (tablesFilter) {
if (!datasource.entities) { datasource.entities = {}
datasource.entities = {}
}
for (let key in tables) { for (let key in tables) {
if ( if (
tablesFilter.some( tablesFilter.some(
@ -200,7 +198,7 @@ export async function buildSchemaFromDb(ctx: UserCtx) {
} }
setDefaultDisplayColumns(datasource) setDefaultDisplayColumns(datasource)
const dbResp = await db.put(datasource) const dbResp = await db.put(sdk.tables.checkExternalTableSchemas(datasource))
datasource._rev = dbResp.rev datasource._rev = dbResp.rev
const cleanedDatasource = await sdk.datasources.removeSecretSingle(datasource) const cleanedDatasource = await sdk.datasources.removeSecretSingle(datasource)
@ -286,7 +284,9 @@ export async function update(ctx: UserCtx<any, UpdateDatasourceResponse>) {
datasource.config!.auth = auth datasource.config!.auth = auth
} }
const response = await db.put(datasource) const response = await db.put(
sdk.tables.checkExternalTableSchemas(datasource)
)
await events.datasource.updated(datasource) await events.datasource.updated(datasource)
datasource._rev = response.rev datasource._rev = response.rev
@ -327,7 +327,7 @@ export async function save(
setDefaultDisplayColumns(datasource) setDefaultDisplayColumns(datasource)
} }
const dbResp = await db.put(datasource) const dbResp = await db.put(sdk.tables.checkExternalTableSchemas(datasource))
await events.datasource.created(datasource) await events.datasource.created(datasource)
datasource._rev = dbResp.rev datasource._rev = dbResp.rev

View File

@ -1,32 +1,34 @@
import { import {
buildExternalTableId,
breakExternalTableId, breakExternalTableId,
buildExternalTableId,
} from "../../../integrations/utils" } from "../../../integrations/utils"
import { import {
foreignKeyStructure,
generateForeignKey, generateForeignKey,
generateJunctionTableName, generateJunctionTableName,
foreignKeyStructure,
hasTypeChanged, hasTypeChanged,
setStaticSchemas, setStaticSchemas,
} from "./utils" } from "./utils"
import { FieldTypes } from "../../../constants" import { FieldTypes } from "../../../constants"
import { makeExternalQuery } from "../../../integrations/base/query" import { makeExternalQuery } from "../../../integrations/base/query"
import { handleRequest } from "../row/external" import { handleRequest } from "../row/external"
import { events, context } from "@budibase/backend-core" import { context, events } from "@budibase/backend-core"
import { parse, isRows, isSchema } from "../../../utilities/schema" import { isRows, isSchema, parse } from "../../../utilities/schema"
import { import {
AutoReason,
Datasource, Datasource,
Table,
QueryJson,
Operation,
RenameColumn,
FieldSchema, FieldSchema,
UserCtx, Operation,
TableRequest, QueryJson,
RelationshipTypes, RelationshipTypes,
RenameColumn,
Table,
TableRequest,
UserCtx,
} from "@budibase/types" } from "@budibase/types"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import { builderSocket } from "../../../websockets" import { builderSocket } from "../../../websockets"
const { cloneDeep } = require("lodash/fp") const { cloneDeep } = require("lodash/fp")
async function makeTableRequest( async function makeTableRequest(
@ -317,7 +319,7 @@ export async function save(ctx: UserCtx) {
delete tableToSave._rename delete tableToSave._rename
// store it into couch now for budibase reference // store it into couch now for budibase reference
datasource.entities[tableToSave.name] = tableToSave datasource.entities[tableToSave.name] = tableToSave
await db.put(datasource) await db.put(sdk.tables.checkExternalTableSchemas(datasource))
// Since tables are stored inside datasources, we need to notify clients // Since tables are stored inside datasources, we need to notify clients
// that the datasource definition changed // that the datasource definition changed
@ -348,7 +350,7 @@ export async function destroy(ctx: UserCtx) {
datasource.entities = tables datasource.entities = tables
} }
await db.put(datasource) await db.put(sdk.tables.checkExternalTableSchemas(datasource))
// Since tables are stored inside datasources, we need to notify clients // Since tables are stored inside datasources, we need to notify clients
// that the datasource definition changed // that the datasource definition changed

View File

@ -7,6 +7,7 @@ import {
} from "../../../integrations/utils" } from "../../../integrations/utils"
import { Table, Database } from "@budibase/types" import { Table, Database } from "@budibase/types"
import datasources from "../datasources" import datasources from "../datasources"
import { checkExternalTableSchemas } from "./validation"
async function getAllInternalTables(db?: Database): Promise<Table[]> { async function getAllInternalTables(db?: Database): Promise<Table[]> {
if (!db) { if (!db) {
@ -60,4 +61,5 @@ export default {
getAllExternalTables, getAllExternalTables,
getExternalTable, getExternalTable,
getTable, getTable,
checkExternalTableSchemas,
} }

View File

@ -0,0 +1,57 @@
import {
Datasource,
FieldType,
RelationshipTypes,
AutoReason,
} from "@budibase/types"
function checkForeignKeysAreAutoColumns(datasource: Datasource) {
if (!datasource.entities) {
return datasource
}
const tables = Object.values(datasource.entities)
// make sure all foreign key columns are marked as auto columns
const foreignKeys: { tableId: string; key: string }[] = []
for (let table of tables) {
const relationships = Object.values(table.schema).filter(
column => column.type === FieldType.LINK
)
relationships.forEach(relationship => {
if (relationship.relationshipType === RelationshipTypes.MANY_TO_MANY) {
const tableId = relationship.through!
foreignKeys.push({ key: relationship.throughTo!, tableId })
foreignKeys.push({ key: relationship.throughFrom!, tableId })
} else {
const fk = relationship.foreignKey!
const oneSide =
relationship.relationshipType === RelationshipTypes.ONE_TO_MANY
foreignKeys.push({
tableId: oneSide ? table._id! : relationship.tableId!,
key: fk,
})
}
})
}
// now make sure schemas are all accurate
for (let table of tables) {
for (let column of Object.values(table.schema)) {
const shouldBeForeign = foreignKeys.find(
options => options.tableId === table._id && options.key === column.name
)
if (shouldBeForeign) {
column.autocolumn = true
column.autoReason = AutoReason.FOREIGN_KEY
} else if (column.autoReason === AutoReason.FOREIGN_KEY) {
delete column.autocolumn
delete column.autoReason
}
}
}
return datasource
}
export function checkExternalTableSchemas(datasource: Datasource) {
return checkForeignKeysAreAutoColumns(datasource)
}

View File

@ -9,6 +9,10 @@ export enum RelationshipTypes {
MANY_TO_MANY = "many-to-many", MANY_TO_MANY = "many-to-many",
} }
export enum AutoReason {
FOREIGN_KEY = "foreign_key",
}
export interface FieldSchema { export interface FieldSchema {
type: FieldType type: FieldType
externalType?: string externalType?: string
@ -21,6 +25,7 @@ export interface FieldSchema {
foreignKey?: string foreignKey?: string
icon?: string icon?: string
autocolumn?: boolean autocolumn?: boolean
autoReason?: AutoReason
subtype?: string subtype?: string
throughFrom?: string throughFrom?: string
throughTo?: string throughTo?: string