diff --git a/packages/tools/src/SqlDumper.ts b/packages/tools/src/SqlDumper.ts index 89897e1f..f24f227b 100644 --- a/packages/tools/src/SqlDumper.ts +++ b/packages/tools/src/SqlDumper.ts @@ -16,6 +16,7 @@ import { UniqueInfo, CheckInfo, AlterProcessor, + SqlObjectInfo, } from 'dbgate-types'; import _isString from 'lodash/isString'; import _isNumber from 'lodash/isNumber'; @@ -577,4 +578,27 @@ export class SqlDumper implements AlterProcessor { this.dropTable({ ...oldTable, pureName: tmpTable }); } + + createSqlObject(obj: SqlObjectInfo) { + this.putCmd(obj.createSql); + } + + getSqlObjectSqlName(ojectTypeField: string) { + switch (ojectTypeField) { + case 'procedures': + return 'PROCEDURE'; + case 'views': + return 'VIEW'; + case 'functions': + return 'FUNCTION'; + case 'triggers': + return 'TRIGGER'; + case 'matviews': + return 'MATERIALIZED VIEW'; + } + } + + dropSqlObject(obj: SqlObjectInfo) { + this.putCmd('^drop %s %f', this.getSqlObjectSqlName(obj.objectTypeField), obj); + } } diff --git a/packages/tools/src/alterPlan.ts b/packages/tools/src/alterPlan.ts index 20ca2e1d..0b972bc7 100644 --- a/packages/tools/src/alterPlan.ts +++ b/packages/tools/src/alterPlan.ts @@ -4,7 +4,7 @@ import { ColumnInfo, ConstraintInfo, DatabaseInfo, - NamedObjectInfo, + SqlObjectInfo, SqlDialect, TableInfo, } from '../../types'; @@ -21,6 +21,16 @@ interface AlterOperation_DropTable { oldObject: TableInfo; } +interface AlterOperation_CreateSqlObject { + operationType: 'createSqlObject'; + newObject: SqlObjectInfo; +} + +interface AlterOperation_DropSqlObject { + operationType: 'dropSqlObject'; + oldObject: SqlObjectInfo; +} + interface AlterOperation_RenameTable { operationType: 'renameTable'; object: TableInfo; @@ -88,6 +98,8 @@ type AlterOperation = | AlterOperation_RenameTable | AlterOperation_RenameColumn | AlterOperation_RenameConstraint + | AlterOperation_CreateSqlObject + | AlterOperation_DropSqlObject | AlterOperation_RecreateTable; export class AlterPlan { @@ -108,6 +120,20 @@ export class AlterPlan { }); } + createSqlObject(obj: SqlObjectInfo) { + this.operations.push({ + operationType: 'createSqlObject', + newObject: obj, + }); + } + + dropSqlObject(obj: SqlObjectInfo) { + this.operations.push({ + operationType: 'dropSqlObject', + oldObject: obj, + }); + } + createColumn(column: ColumnInfo) { this.operations.push({ operationType: 'createColumn', @@ -419,6 +445,12 @@ export function runAlterOperation(op: AlterOperation, processor: AlterProcessor) case 'renameConstraint': processor.renameConstraint(op.object, op.newName); break; + case 'createSqlObject': + processor.createSqlObject(op.newObject); + break; + case 'dropSqlObject': + processor.dropSqlObject(op.oldObject); + break; case 'recreateTable': { const newTable = _.cloneDeep(op.table); diff --git a/packages/tools/src/database-info-alter-processor.ts b/packages/tools/src/database-info-alter-processor.ts index 350339bb..f5e1884a 100644 --- a/packages/tools/src/database-info-alter-processor.ts +++ b/packages/tools/src/database-info-alter-processor.ts @@ -1,3 +1,4 @@ +import _ from 'lodash'; import { ColumnInfo, ConstraintInfo, @@ -8,6 +9,7 @@ import { IndexInfo, CheckInfo, UniqueInfo, + SqlObjectInfo, } from '../../types'; export class DatabaseInfoAlterProcessor { @@ -18,7 +20,18 @@ export class DatabaseInfoAlterProcessor { } dropTable(table: TableInfo) { - this.db.tables = this.db.tables.filter(x => x.pureName != table.pureName && x.schemaName != table.schemaName); + _.remove(this.db.tables, x => x.pureName != table.pureName && x.schemaName != table.schemaName); + } + + createSqlObject(obj: SqlObjectInfo) { + this.db[obj.objectTypeField].push(obj); + } + + dropSqlObject(obj: SqlObjectInfo) { + _.remove( + this.db[obj.objectTypeField] as SqlObjectInfo[], + x => x.pureName != obj.pureName && x.schemaName != obj.schemaName + ); } createColumn(column: ColumnInfo) { @@ -33,7 +46,7 @@ export class DatabaseInfoAlterProcessor { dropColumn(column: ColumnInfo) { const table = this.db.tables.find(x => x.pureName == column.pureName && x.schemaName == column.schemaName); - table.columns = table.columns.filter(x => x.columnName != column.columnName); + _.remove(table.columns, x => x.columnName != column.columnName); } createConstraint(constraint: ConstraintInfo) { diff --git a/packages/tools/src/diffTools.ts b/packages/tools/src/diffTools.ts index a9b2435b..873188f4 100644 --- a/packages/tools/src/diffTools.ts +++ b/packages/tools/src/diffTools.ts @@ -309,18 +309,26 @@ export function createAlterDatabasePlan( ): AlterPlan { const plan = new AlterPlan(db, driver.dialect); - for (const objectTypeField of ['tables']) { - for (const oldobj of oldDb[objectTypeField]) { - const newobj = newDb[objectTypeField].find(x => x.pairingId == oldobj.pairingId); + for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) { + for (const oldobj of oldDb[objectTypeField] || []) { + const newobj = (newDb[objectTypeField] || []).find(x => x.pairingId == oldobj.pairingId); if (objectTypeField == 'tables') { if (newobj == null) plan.dropTable(oldobj); else planAlterTable(plan, oldobj, newobj, opts); + } else { + if (newobj == null) plan.dropSqlObject(oldobj); + else if (newobj.createSql != oldobj.createSql) { + plan.dropSqlObject(oldobj); + plan.createSqlObject(newobj); + } } } - for (const newobj of newDb[objectTypeField]) { - const oldobj = oldDb[objectTypeField].find(x => x.pairingId == newobj.pairingId); + for (const newobj of newDb[objectTypeField] || []) { + const oldobj = (oldDb[objectTypeField] || []).find(x => x.pairingId == newobj.pairingId); if (objectTypeField == 'tables') { if (newobj == null) plan.createTable(newobj); + } else { + plan.createSqlObject(newobj); } } } diff --git a/packages/types/alter-processor.d.ts b/packages/types/alter-processor.d.ts index c905b31c..4cb7aad6 100644 --- a/packages/types/alter-processor.d.ts +++ b/packages/types/alter-processor.d.ts @@ -1,4 +1,4 @@ -import { ColumnInfo, ConstraintInfo, TableInfo } from './dbinfo'; +import { ColumnInfo, ConstraintInfo, TableInfo, SqlObjectInfo } from './dbinfo'; export interface AlterProcessor { createTable(table: TableInfo); @@ -13,4 +13,6 @@ export interface AlterProcessor { renameColumn(column: ColumnInfo, newName: string); renameConstraint(constraint: ConstraintInfo, newName: string); recreateTable(oldTable: TableInfo, newTable: TableInfo); + createSqlObject(obj: SqlObjectInfo); + dropSqlObject(obj: SqlObjectInfo); } diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 173b77ad..a96c2191 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -67,6 +67,7 @@ export interface DatabaseObjectInfo extends NamedObjectInfo { export interface SqlObjectInfo extends DatabaseObjectInfo { createSql?: string; requiresFormat?: boolean; // SQL is human unreadable, requires formatting (eg. MySQL views) + objectTypeField?: string; } export interface TableInfo extends DatabaseObjectInfo {