Action Michael's feedback about the structure of this feature.
This commit is contained in:
parent
5747f30b5f
commit
c25de74e17
|
@ -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)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue