diff --git a/packages/tools/src/diffTools.ts b/packages/tools/src/diffTools.ts index 29877f6dc..f1f8944b5 100644 --- a/packages/tools/src/diffTools.ts +++ b/packages/tools/src/diffTools.ts @@ -5,15 +5,15 @@ import { AlterPlan } from './alterPlan'; type DbDiffSchemaMode = 'strict' | 'ignore' | 'ignoreImplicit'; export interface DbDiffOptions { - allowRecreateTable: boolean; - allowRecreateConstraint: boolean; - allowRecreateSpecificObject: boolean; - allowPairRenamedTables: boolean; + allowRecreateTable?: boolean; + allowRecreateConstraint?: boolean; + allowRecreateSpecificObject?: boolean; + allowPairRenamedTables?: boolean; - ignoreCase: boolean; - schemaMode: DbDiffSchemaMode; - leftImplicitSchema: string; - rightImplicitSchema: string; + ignoreCase?: boolean; + schemaMode?: DbDiffSchemaMode; + leftImplicitSchema?: string; + rightImplicitSchema?: string; } export function generateTablePairingId(table: TableInfo): TableInfo { @@ -69,12 +69,12 @@ function testEqualFullNames(lft: NamedObjectInfo, rgt: NamedObjectInfo, opts: Db return testEqualSchemas(lft.schemaName, rgt.schemaName, opts) && testEqualNames(lft.pureName, rgt.pureName, opts); } -function testEqualsColumns( +export function testEqualColumns( a: ColumnInfo, b: ColumnInfo, checkName: boolean, checkDefault: boolean, - opts: DbDiffOptions + opts: DbDiffOptions = {} ) { if (checkName && !testEqualNames(a.columnName, b.columnName, opts)) { // opts.DiffLogger.Trace("Column, different name: {0}; {1}", a, b); @@ -178,7 +178,7 @@ function testEqualsColumns( return true; } -function testEqualTypes(a: ColumnInfo, b: ColumnInfo, opts: DbDiffOptions) { +export function testEqualTypes(a: ColumnInfo, b: ColumnInfo, opts: DbDiffOptions = {}) { if (a.dataType != b.dataType) { // opts.DiffLogger.Trace("Column {0}, {1}: different types: {2}; {3}", a, b, a.DataType, b.DataType); return false; @@ -254,8 +254,8 @@ function planAlterTable(plan: AlterPlan, oldTable: TableInfo, newTable: TableInf columnPairs .filter(x => x[0] && x[1]) .forEach(x => { - if (!testEqualsColumns(x[0], x[1], true, true, opts)) { - if (testEqualsColumns(x[0], x[1], false, true, opts)) { + if (!testEqualColumns(x[0], x[1], true, true, opts)) { + if (testEqualColumns(x[0], x[1], false, true, opts)) { // console.log('PLAN RENAME COLUMN') plan.renameColumn(x[0], x[1].columnName); } else { diff --git a/packages/types/alter-processor.d.ts b/packages/types/alter-processor.d.ts index af939abf4..5d61162dc 100644 --- a/packages/types/alter-processor.d.ts +++ b/packages/types/alter-processor.d.ts @@ -4,7 +4,7 @@ export interface AlterProcessor { createTable(table: TableInfo); dropTable(table: TableInfo); createColumn(column: ColumnInfo, constraints: ConstraintInfo[]); - changeColumn(oldColumn: ColumnInfo, newColumn: ColumnInfo); + changeColumn(oldColumn: ColumnInfo, newColumn: ColumnInfo, constraints: ConstraintInfo[]); dropColumn(column: ColumnInfo); createConstraint(constraint: ConstraintInfo); changeConstraint(oldConstraint: ConstraintInfo, newConstraint: ConstraintInfo); diff --git a/plugins/dbgate-plugin-mssql/src/frontend/MsSqlDumper.js b/plugins/dbgate-plugin-mssql/src/frontend/MsSqlDumper.js index 428e0d6b0..5ed8f7dcc 100644 --- a/plugins/dbgate-plugin-mssql/src/frontend/MsSqlDumper.js +++ b/plugins/dbgate-plugin-mssql/src/frontend/MsSqlDumper.js @@ -1,4 +1,4 @@ -const { SqlDumper } = global.DBGATE_TOOLS; +const { SqlDumper, testEqualColumns } = global.DBGATE_TOOLS; class MsSqlDumper extends SqlDumper { autoIncrement() { @@ -88,6 +88,21 @@ class MsSqlDumper extends SqlDumper { this.putCmd("^execute sp_rename '%f.%i', '%s', 'COLUMN'", column, column.columnName, newcol); } + changeColumn(oldcol, newcol, constraints) { + if (testEqualColumns(oldcol, newcol, false, false)) { + this.dropDefault(oldcol); + if (oldcol.columnName != newcol.columnName) this.renameColumn(oldcol, newcol.columnName); + this.createDefault(oldcol); + } else { + this.dropDefault(oldcol); + if (oldcol.columnName != newcol.columnName) this.renameColumn(oldcol, newcol.columnName); + this.put('^alter ^table %f ^alter ^column %i ', oldcol, oldcol.columnName, newcol.columnName); + this.columnDefinition(newcol, { includeDefault: false }); + this.endCommand(); + this.createDefault(oldcol); + } + } + renameConstraint(cnt, newname) { if (cnt.constraintType == 'index') this.putCmd("^execute sp_rename '%f.%i', '%s', 'INDEX'", cnt, cnt.constraintName, newname); diff --git a/plugins/dbgate-plugin-mysql/src/frontend/Dumper.js b/plugins/dbgate-plugin-mysql/src/frontend/Dumper.js index 65e21801d..c944ab357 100644 --- a/plugins/dbgate-plugin-mysql/src/frontend/Dumper.js +++ b/plugins/dbgate-plugin-mysql/src/frontend/Dumper.js @@ -32,7 +32,7 @@ class Dumper extends SqlDumper { changeColumn(oldcol, newcol, constraints) { this.put('^alter ^table %f ^change ^column %i %i ', oldcol, oldcol.columnName, newcol.columnName); - this.columnDefinition(newcol, true, true, true); + this.columnDefinition(newcol); this.inlineConstraints(constraints); this.endCommand(); } diff --git a/plugins/dbgate-plugin-postgres/src/frontend/Dumper.js b/plugins/dbgate-plugin-postgres/src/frontend/Dumper.js index 36182f71f..aea162365 100644 --- a/plugins/dbgate-plugin-postgres/src/frontend/Dumper.js +++ b/plugins/dbgate-plugin-postgres/src/frontend/Dumper.js @@ -1,4 +1,4 @@ -const { SqlDumper } = global.DBGATE_TOOLS; +const { SqlDumper, testEqualTypes } = global.DBGATE_TOOLS; class Dumper extends SqlDumper { /** @param type {import('dbgate-types').TransformType} */ @@ -61,6 +61,31 @@ class Dumper extends SqlDumper { } super.columnDefinition(col, options); } + + changeColumn(oldcol, newcol, constraints) { + if (oldcol.columnName != newcol.columnName) { + this.putCmd('^alter ^table %f ^rename ^column %i ^to %i', oldcol, oldcol.columnName, newcol.columnName); + } + if (!testEqualTypes(oldcol, newcol)) { + this.putCmd('^alter ^table %f ^alter ^column %i ^type %s', oldcol, oldcol.columnName, newcol.dataType); + } + if (oldcol.notNull != newcol.notNull) { + if (newcol.notNull) this.putCmd('^alter ^table %f ^alter ^column %i ^set ^not ^null', newcol, newcol.columnName); + else this.putCmd('^alter ^table %f ^alter ^column %i ^drop ^not ^null', newcol, newcol.columnName); + } + if (oldcol.defaultValue != newcol.defaultValue) { + if (newcol.defaultValue == null) { + this.putCmd('^alter ^table %f ^alter ^column %i ^drop ^default', newcol, newcol.columnName); + } else { + this.putCmd( + '^alter ^table %f ^alter ^column %i ^set ^default %s', + newcol, + newcol.columnName, + newcol.defaultValue + ); + } + } + } } module.exports = Dumper;