1
0
Fork 0
mirror of synced 2024-08-15 01:51:33 +12:00

Action Michael's feedback about the structure of this feature.

This commit is contained in:
Sam Rose 2023-10-18 15:14:34 +01:00
parent 5747f30b5f
commit c25de74e17
No known key found for this signature in database
3 changed files with 97 additions and 49 deletions

View file

@ -11,7 +11,6 @@ import {
BulkImportRequest, BulkImportRequest,
BulkImportResponse, BulkImportResponse,
FetchTablesResponse, FetchTablesResponse,
InternalTable,
MigrateRequest, MigrateRequest,
MigrateResponse, MigrateResponse,
SaveTableRequest, SaveTableRequest,
@ -19,8 +18,6 @@ import {
Table, Table,
TableResponse, TableResponse,
UserCtx, UserCtx,
isBBReferenceField,
isRelationshipField,
} from "@budibase/types" } from "@budibase/types"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import { jsonFromCsvString } from "../../../utilities/csv" import { jsonFromCsvString } from "../../../utilities/csv"
@ -164,53 +161,8 @@ export async function validateExistingTableImport(ctx: UserCtx) {
} }
} }
function error(ctx: UserCtx, message: string, status = 400) {
ctx.status = status
ctx.body = { message }
}
export async function migrate(ctx: UserCtx<MigrateRequest, MigrateResponse>) { export async function migrate(ctx: UserCtx<MigrateRequest, MigrateResponse>) {
const { tableId, oldColumn, newColumn } = ctx.request.body const { tableId, oldColumn, newColumn } = ctx.request.body
// For now we're only supporting migrations of user relationships to user
// columns in internal tables. In future we may want to support other
// migrations but for now return an error if we aren't migrating a user
// relationship.
if (isExternalTable(tableId)) {
return error(ctx, "External tables cannot be migrated")
}
const table = await sdk.tables.getTable(tableId) const table = await sdk.tables.getTable(tableId)
await sdk.tables.migrate(table, oldColumn, newColumn)
if (!(oldColumn.name in table.schema)) {
return error(
ctx,
`Column "${oldColumn.name}" does not exist on table "${table.name}"`
)
}
if (newColumn.name in table.schema) {
return error(
ctx,
`Column "${newColumn.name}" already exists on table "${table.name}"`
)
}
if (!isBBReferenceField(newColumn)) {
return error(ctx, `Column "${newColumn.name}" is not a user column`)
}
if (newColumn.subtype !== "user" && newColumn.subtype !== "users") {
return error(ctx, `Column "${newColumn.name}" is not a user column`)
}
if (!isRelationshipField(oldColumn)) {
return error(ctx, `Column "${oldColumn.name}" is not a user relationship`)
}
if (oldColumn.tableId !== InternalTable.USER_METADATA) {
return error(ctx, `Column "${oldColumn.name}" is not a user relationship`)
}
let rows = await sdk.rows.fetch(tableId)
} }

View file

@ -7,6 +7,7 @@ import {
} from "../../../integrations/utils" } from "../../../integrations/utils"
import { import {
Database, Database,
FieldSchema,
Table, Table,
TableResponse, TableResponse,
TableViewsResponse, TableViewsResponse,
@ -14,6 +15,7 @@ import {
import datasources from "../datasources" import datasources from "../datasources"
import { populateExternalTableSchemas } from "./validation" import { populateExternalTableSchemas } from "./validation"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import { migrate } from "./migration"
async function getAllInternalTables(db?: Database): Promise<Table[]> { async function getAllInternalTables(db?: Database): Promise<Table[]> {
if (!db) { if (!db) {
@ -84,6 +86,14 @@ async function saveTable(table: Table) {
} }
} }
async function addColumn(table: Table, newColumn: FieldSchema) {
if (newColumn.name in table.schema) {
throw `Column "${newColumn.name}" already exists on table "${table.name}"`
}
table.schema[newColumn.name] = newColumn
await saveTable(table)
}
export default { export default {
getAllInternalTables, getAllInternalTables,
getAllExternalTables, getAllExternalTables,
@ -92,4 +102,6 @@ export default {
populateExternalTableSchemas, populateExternalTableSchemas,
enrichViewSchemas, enrichViewSchemas,
saveTable, saveTable,
addColumn,
migrate,
} }

View file

@ -0,0 +1,84 @@
import { BadRequestError } from "@budibase/backend-core"
import {
BBReferenceFieldMetadata,
FieldSchema,
InternalTable,
RelationshipFieldMetadata,
Table,
isBBReferenceField,
isRelationshipField,
} from "@budibase/types"
import { isExternalTable } from "src/integrations/utils"
import sdk from "../../../sdk"
export async function migrate(
table: Table,
oldColumn: FieldSchema,
newColumn: FieldSchema
) {
let migrator = getColumnMigrator(table, oldColumn, newColumn)
await sdk.tables.addColumn(table, newColumn)
migrator.doMigration()
}
interface ColumnMigrator {
doMigration(): Promise<void>
}
function getColumnMigrator(
table: Table,
oldColumn: FieldSchema,
newColumn: FieldSchema
): ColumnMigrator {
// For now we're only supporting migrations of user relationships to user
// columns in internal tables. In future we may want to support other
// migrations but for now return an error if we aren't migrating a user
// relationship.
if (isExternalTable(table._id!)) {
throw new BadRequestError("External tables cannot be migrated")
}
if (!(oldColumn.name in table.schema)) {
throw new BadRequestError(`Column "${oldColumn.name}" does not exist`)
}
if (newColumn.name in table.schema) {
throw new BadRequestError(`Column "${newColumn.name}" already exists`)
}
if (!isBBReferenceField(newColumn)) {
throw new BadRequestError(`Column "${newColumn.name}" is not a user column`)
}
if (newColumn.subtype !== "user" && newColumn.subtype !== "users") {
throw new BadRequestError(`Column "${newColumn.name}" is not a user column`)
}
if (!isRelationshipField(oldColumn)) {
throw new BadRequestError(
`Column "${oldColumn.name}" is not a user relationship`
)
}
if (oldColumn.tableId !== InternalTable.USER_METADATA) {
throw new BadRequestError(
`Column "${oldColumn.name}" is not a user relationship`
)
}
return new UserColumnMigrator(table, oldColumn, newColumn)
}
class UserColumnMigrator implements ColumnMigrator {
constructor(
private table: Table,
private oldColumn: RelationshipFieldMetadata,
private newColumn: BBReferenceFieldMetadata
) {}
async doMigration() {
let rows = await sdk.rows.fetch(this.table._id!)
}
}