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:
parent
4788972362
commit
c2b4dec88f
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue