From 1357c53ff818b5fab83523779d3044f77a273a06 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 7 Mar 2022 16:31:35 +0000 Subject: [PATCH] Fixing issue #4811 - when renaming SQL columns use an actual rename alteration rather than dropping the column. --- .../src/api/controllers/table/external.js | 18 +++++++++-- packages/server/src/definitions/datasource.ts | 6 ++++ .../server/src/integrations/base/sqlTable.ts | 30 +++++++++++++++---- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/packages/server/src/api/controllers/table/external.js b/packages/server/src/api/controllers/table/external.js index b27eebb0c4..86d855a28e 100644 --- a/packages/server/src/api/controllers/table/external.js +++ b/packages/server/src/api/controllers/table/external.js @@ -25,7 +25,8 @@ async function makeTableRequest( operation, table, tables, - oldTable = null + oldTable = null, + renamed = null ) { const json = { endpoint: { @@ -41,6 +42,9 @@ async function makeTableRequest( if (oldTable) { json.meta.table = oldTable } + if (renamed) { + json.meta.renamed = renamed + } return makeExternalQuery(datasource, json) } @@ -160,6 +164,7 @@ function isRelationshipSetup(column) { exports.save = async function (ctx) { const table = ctx.request.body + const { _rename: renamed } = table // can't do this right now delete table.dataImport const datasourceId = getDatasourceId(ctx.request.body) @@ -241,7 +246,14 @@ exports.save = async function (ctx) { const operation = oldTable ? DataSourceOperation.UPDATE_TABLE : DataSourceOperation.CREATE_TABLE - await makeTableRequest(datasource, operation, tableToSave, tables, oldTable) + await makeTableRequest( + datasource, + operation, + tableToSave, + tables, + oldTable, + renamed + ) // update any extra tables (like foreign keys in other tables) for (let extraTable of extraTablesToUpdate) { const oldExtraTable = oldTables[extraTable.name] @@ -258,6 +270,8 @@ exports.save = async function (ctx) { ) } + // remove the rename prop + delete tableToSave._rename // store it into couch now for budibase reference datasource.entities[tableToSave.name] = tableToSave await db.put(datasource) diff --git a/packages/server/src/definitions/datasource.ts b/packages/server/src/definitions/datasource.ts index 6c8c8dc07d..2e2ad25f58 100644 --- a/packages/server/src/definitions/datasource.ts +++ b/packages/server/src/definitions/datasource.ts @@ -138,6 +138,11 @@ export interface PaginationJson { page?: string | number } +export interface RenameColumn { + old: string + updated: string +} + export interface RelationshipsJson { through?: string from?: string @@ -166,6 +171,7 @@ export interface QueryJson { meta?: { table?: Table tables?: Record + renamed: RenameColumn } extra?: { idFilter?: SearchFilters diff --git a/packages/server/src/integrations/base/sqlTable.ts b/packages/server/src/integrations/base/sqlTable.ts index b9ea7107fc..0c63b707ae 100644 --- a/packages/server/src/integrations/base/sqlTable.ts +++ b/packages/server/src/integrations/base/sqlTable.ts @@ -1,6 +1,10 @@ import { Knex, knex } from "knex" import { Table } from "../../definitions/common" -import { Operation, QueryJson } from "../../definitions/datasource" +import { + Operation, + QueryJson, + RenameColumn, +} from "../../definitions/datasource" import { breakExternalTableId } from "../utils" import SchemaBuilder = Knex.SchemaBuilder import CreateTableBuilder = Knex.CreateTableBuilder @@ -10,7 +14,8 @@ function generateSchema( schema: CreateTableBuilder, table: Table, tables: Record, - oldTable: null | Table = null + oldTable: null | Table = null, + renamed?: RenameColumn ) { let primaryKey = table && table.primary ? table.primary[0] : null const columns = Object.values(table.schema) @@ -29,7 +34,11 @@ function generateSchema( for (let [key, column] of Object.entries(table.schema)) { // skip things that are already correct const oldColumn = oldTable ? oldTable.schema[key] : null - if ((oldColumn && oldColumn.type) || (primaryKey === key && !isJunction)) { + if ( + (oldColumn && oldColumn.type) || + (primaryKey === key && !isJunction) || + renamed?.updated === key + ) { continue } switch (column.type) { @@ -81,6 +90,10 @@ function generateSchema( } } + if (renamed) { + schema.renameColumn(renamed.old, renamed.updated) + } + // need to check if any columns have been deleted if (oldTable) { const deletedColumns = Object.entries(oldTable.schema) @@ -90,6 +103,9 @@ function generateSchema( ) .map(([key]) => key) deletedColumns.forEach(key => { + if (renamed?.old === key) { + return + } if (oldTable.constrained && oldTable.constrained.indexOf(key) !== -1) { schema.dropForeign(key) } @@ -114,10 +130,11 @@ function buildUpdateTable( knex: SchemaBuilder, table: Table, tables: Record, - oldTable: Table + oldTable: Table, + renamed: RenameColumn ): SchemaBuilder { return knex.alterTable(table.name, schema => { - generateSchema(schema, table, tables, oldTable) + generateSchema(schema, table, tables, oldTable, renamed) }) } @@ -167,7 +184,8 @@ class SqlTableQueryBuilder { client, json.table, json.meta.tables, - json.meta.table + json.meta.table, + json.meta.renamed ) break case Operation.DELETE_TABLE: