diff --git a/packages/server/src/api/controllers/datasource.ts b/packages/server/src/api/controllers/datasource.ts index 062a185a23..f8836d1958 100644 --- a/packages/server/src/api/controllers/datasource.ts +++ b/packages/server/src/api/controllers/datasource.ts @@ -198,7 +198,9 @@ export async function buildSchemaFromDb(ctx: UserCtx) { } setDefaultDisplayColumns(datasource) - const dbResp = await db.put(sdk.tables.checkExternalTableSchemas(datasource)) + const dbResp = await db.put( + sdk.tables.populateExternalTableSchemas(datasource) + ) datasource._rev = dbResp.rev const cleanedDatasource = await sdk.datasources.removeSecretSingle(datasource) @@ -285,7 +287,7 @@ export async function update(ctx: UserCtx) { } const response = await db.put( - sdk.tables.checkExternalTableSchemas(datasource) + sdk.tables.populateExternalTableSchemas(datasource) ) await events.datasource.updated(datasource) datasource._rev = response.rev @@ -327,7 +329,9 @@ export async function save( setDefaultDisplayColumns(datasource) } - const dbResp = await db.put(sdk.tables.checkExternalTableSchemas(datasource)) + const dbResp = await db.put( + sdk.tables.populateExternalTableSchemas(datasource) + ) await events.datasource.created(datasource) datasource._rev = dbResp.rev diff --git a/packages/server/src/api/controllers/table/external.ts b/packages/server/src/api/controllers/table/external.ts index 8877f0f8d0..9029d0468a 100644 --- a/packages/server/src/api/controllers/table/external.ts +++ b/packages/server/src/api/controllers/table/external.ts @@ -319,7 +319,7 @@ export async function save(ctx: UserCtx) { delete tableToSave._rename // store it into couch now for budibase reference datasource.entities[tableToSave.name] = tableToSave - await db.put(sdk.tables.checkExternalTableSchemas(datasource)) + await db.put(sdk.tables.populateExternalTableSchemas(datasource)) // Since tables are stored inside datasources, we need to notify clients // that the datasource definition changed @@ -350,7 +350,7 @@ export async function destroy(ctx: UserCtx) { datasource.entities = tables } - await db.put(sdk.tables.checkExternalTableSchemas(datasource)) + await db.put(sdk.tables.populateExternalTableSchemas(datasource)) // Since tables are stored inside datasources, we need to notify clients // that the datasource definition changed diff --git a/packages/server/src/sdk/app/tables/index.ts b/packages/server/src/sdk/app/tables/index.ts index fcb32f387b..c7de1b327c 100644 --- a/packages/server/src/sdk/app/tables/index.ts +++ b/packages/server/src/sdk/app/tables/index.ts @@ -7,7 +7,7 @@ import { } from "../../../integrations/utils" import { Table, Database } from "@budibase/types" import datasources from "../datasources" -import { checkExternalTableSchemas, isEditableColumn } from "./validation" +import { populateExternalTableSchemas, isEditableColumn } from "./validation" async function getAllInternalTables(db?: Database): Promise { if (!db) { @@ -61,6 +61,6 @@ export default { getAllExternalTables, getExternalTable, getTable, - checkExternalTableSchemas, + populateExternalTableSchemas, isEditableColumn, } diff --git a/packages/server/src/sdk/app/tables/tests/validation.spec.ts b/packages/server/src/sdk/app/tables/tests/validation.spec.ts index 8acc315125..ffc34d0afd 100644 --- a/packages/server/src/sdk/app/tables/tests/validation.spec.ts +++ b/packages/server/src/sdk/app/tables/tests/validation.spec.ts @@ -1,6 +1,7 @@ -import { checkExternalTableSchemas } from "../validation" +import { populateExternalTableSchemas } from "../validation" import { cloneDeep } from "lodash/fp" -import { Datasource } from "@budibase/types" +import { Datasource, Table } from "@budibase/types" +import { isEqual } from "lodash" const SCHEMA = { entities: { @@ -71,28 +72,58 @@ const SCHEMA = { }, } +const OTHER_CLIENT_COLS = ["idC", "Name", "project"] +const OTHER_PROJECT_COLS = ["idP", "Name", "client"] + describe("validation and update of external table schemas", () => { function getForeignKeyColumn(datasource: Datasource) { return datasource.entities!["project"].schema.idC } + function checkOtherColumns( + table: Table, + compareTable: Table, + columnsToCheck: string[] + ) { + for (let columnName of columnsToCheck) { + const columnA = table.schema[columnName] + const columnB = table.schema[columnName] + expect(isEqual(columnA, columnB)).toBe(true) + } + } + + function noOtherTableChanges(response: any) { + checkOtherColumns( + response.entities!.client!, + SCHEMA.entities.client as Table, + OTHER_CLIENT_COLS + ) + checkOtherColumns( + response.entities!.project!, + SCHEMA.entities.project as Table, + OTHER_PROJECT_COLS + ) + } + it("should correctly set utilised foreign keys to autocolumns", () => { - const response = checkExternalTableSchemas(cloneDeep(SCHEMA) as any) + const response = populateExternalTableSchemas(cloneDeep(SCHEMA) as any) const foreignKey = getForeignKeyColumn(response) expect(foreignKey.autocolumn).toBe(true) expect(foreignKey.autoReason).toBe("foreign_key") + noOtherTableChanges(response) }) it("should correctly unset foreign keys when no longer used", () => { - const setResponse = checkExternalTableSchemas(cloneDeep(SCHEMA) as any) + const setResponse = populateExternalTableSchemas(cloneDeep(SCHEMA) as any) const beforeFk = getForeignKeyColumn(setResponse) delete setResponse.entities!.client.schema.project delete setResponse.entities!.project.schema.client - const response = checkExternalTableSchemas(cloneDeep(setResponse)) + const response = populateExternalTableSchemas(cloneDeep(setResponse)) const afterFk = getForeignKeyColumn(response) expect(beforeFk.autocolumn).toBe(true) expect(beforeFk.autoReason).toBe("foreign_key") expect(afterFk.autocolumn).toBeUndefined() expect(afterFk.autoReason).toBeUndefined() + noOtherTableChanges(response) }) }) diff --git a/packages/server/src/sdk/app/tables/validation.ts b/packages/server/src/sdk/app/tables/validation.ts index 52385afb25..e09380c309 100644 --- a/packages/server/src/sdk/app/tables/validation.ts +++ b/packages/server/src/sdk/app/tables/validation.ts @@ -62,6 +62,6 @@ export function isEditableColumn(column: FieldSchema) { return !(isAutoColumn || isFormula) } -export function checkExternalTableSchemas(datasource: Datasource) { +export function populateExternalTableSchemas(datasource: Datasource) { return checkForeignKeysAreAutoColumns(datasource) }