From 185699cb51b061167067333f187fbda04a23e09d Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Thu, 16 Sep 2021 09:31:10 +0200 Subject: [PATCH] alter table WIP --- packages/tools/src/SqlDumper.ts | 5 +++- packages/tools/src/alterPlan.ts | 23 ++++++++++++------- packages/tools/src/diffTools.ts | 16 +++++++++++-- packages/tools/src/nameTools.ts | 6 ++--- packages/types/dialect.d.ts | 1 + packages/types/dumper.d.ts | 2 ++ .../web/src/tabs/TableStructureTab.svelte | 8 ++++++- .../src/frontend/driver.js | 2 ++ 8 files changed, 48 insertions(+), 15 deletions(-) diff --git a/packages/tools/src/SqlDumper.ts b/packages/tools/src/SqlDumper.ts index f24f227b..5f7dd9bd 100644 --- a/packages/tools/src/SqlDumper.ts +++ b/packages/tools/src/SqlDumper.ts @@ -538,11 +538,14 @@ export class SqlDumper implements AlterProcessor { } recreateTable(oldTable: TableInfo, newTable: TableInfo) { - if (oldTable.pairingId != newTable.pairingId) { + if (!oldTable.pairingId || !newTable.pairingId || oldTable.pairingId != newTable.pairingId) { throw new Error('Recreate is not possible: oldTable.paringId != newTable.paringId'); } const tmpTable = `temp_${uuidv1()}`; + // console.log('oldTable', oldTable); + // console.log('newTable', newTable); + const columnPairs = oldTable.columns .map(oldcol => ({ oldcol, diff --git a/packages/tools/src/alterPlan.ts b/packages/tools/src/alterPlan.ts index 0b972bc7..2bbb4d12 100644 --- a/packages/tools/src/alterPlan.ts +++ b/packages/tools/src/alterPlan.ts @@ -1,4 +1,5 @@ import _ from 'lodash'; +import { generateTablePairingId } from '.'; import { AlterProcessor, ColumnInfo, @@ -371,12 +372,17 @@ export class AlterPlan { const recreates = {}; for (const op of this.operations) { if (op.operationType == 'recreateTable') { - const recreate = { - ...op, - operations: [...op.operations], - }; - res.push(recreate); - recreates[`${op.table.schemaName}||${op.table.pureName}`] = recreate; + const existingRecreate = recreates[`${op.table.schemaName}||${op.table.pureName}`]; + if (existingRecreate) { + existingRecreate.operations.push(...op.operations); + } else { + const recreate = { + ...op, + operations: [...op.operations], + }; + res.push(recreate); + recreates[`${op.table.schemaName}||${op.table.pureName}`] = recreate; + } } else { // @ts-ignore const oldObject: TableInfo = op.oldObject; @@ -453,7 +459,8 @@ export function runAlterOperation(op: AlterOperation, processor: AlterProcessor) break; case 'recreateTable': { - const newTable = _.cloneDeep(op.table); + const oldTable = generateTablePairingId(op.table); + const newTable = _.cloneDeep(oldTable); const newDb = DatabaseAnalyser.createEmptyStructure(); newDb.tables.push(newTable); // console.log('////////////////////////////newTable1', newTable); @@ -461,7 +468,7 @@ export function runAlterOperation(op: AlterOperation, processor: AlterProcessor) // console.log('////////////////////////////op.operations', op.operations); // console.log('////////////////////////////op.table', op.table); // console.log('////////////////////////////newTable2', newTable); - processor.recreateTable(op.table, newTable); + processor.recreateTable(oldTable, newTable); } break; } diff --git a/packages/tools/src/diffTools.ts b/packages/tools/src/diffTools.ts index 55c34ddb..2d53b8c1 100644 --- a/packages/tools/src/diffTools.ts +++ b/packages/tools/src/diffTools.ts @@ -1,4 +1,12 @@ -import { ColumnInfo, ConstraintInfo, DatabaseInfo, EngineDriver, NamedObjectInfo, TableInfo } from 'dbgate-types'; +import { + ColumnInfo, + ConstraintInfo, + DatabaseInfo, + EngineDriver, + NamedObjectInfo, + SqlDialect, + TableInfo, +} from 'dbgate-types'; import _ from 'lodash'; import uuidv1 from 'uuid/v1'; import { AlterPlan } from './alterPlan'; @@ -287,7 +295,7 @@ function planAlterTable(plan: AlterPlan, oldTable: TableInfo, newTable: TableInf .filter(x => x[0] && x[1]) .forEach(x => { if (!testEqualConstraints(x[0], x[1], opts)) { - // console.log('PLAN CHANGE COLUMN') + // console.log('PLAN CHANGE CONSTRAINT', x[0], x[1]); plan.changeConstraint(x[0], x[1]); } }); @@ -357,7 +365,9 @@ export function getAlterTableScript( ): string { const plan = createAlterTablePlan(oldTable, newTable, opts, db, driver); const dmp = driver.createDumper(); + if (!driver.dialect.disableExplicitTransaction) dmp.beginTransaction(); plan.run(dmp); + if (!driver.dialect.disableExplicitTransaction) dmp.commitTransaction(); return dmp.s; } @@ -370,6 +380,8 @@ export function getAlterDatabaseScript( ): string { const plan = createAlterDatabasePlan(oldDb, newDb, opts, db, driver); const dmp = driver.createDumper(); + if (!driver.dialect.disableExplicitTransaction) dmp.beginTransaction(); plan.run(dmp); + if (!driver.dialect.disableExplicitTransaction) dmp.commitTransaction(); return dmp.s; } diff --git a/packages/tools/src/nameTools.ts b/packages/tools/src/nameTools.ts index f5b5fabd..4a0256f9 100644 --- a/packages/tools/src/nameTools.ts +++ b/packages/tools/src/nameTools.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { ColumnInfo, ColumnReference, DatabaseInfo, DatabaseInfoObjects, TableInfo } from 'dbgate-types'; +import { ColumnInfo, ColumnReference, DatabaseInfo, DatabaseInfoObjects, SqlDialect, TableInfo } from 'dbgate-types'; export function fullNameFromString(name) { const m = name.match(/\[([^\]]+)\]\.\[([^\]]+)\]/); @@ -74,10 +74,10 @@ function columnsConstraintName(prefix: string, table: TableInfo, columns: Column return `${prefix}_${table.pureName}_${columns.map(x => x.columnName.replace(' ', '_')).join('_')}`; } -export function fillConstraintNames(table: TableInfo) { +export function fillConstraintNames(table: TableInfo, dialect: SqlDialect) { if (!table) return table; const res = _.cloneDeep(table); - if (res.primaryKey && !res.primaryKey.constraintName) { + if (res.primaryKey && !res.primaryKey.constraintName && !dialect.anonymousPrimaryKey) { res.primaryKey.constraintName = `PK_${res.pureName}`; } for (const fk of res.foreignKeys) { diff --git a/packages/types/dialect.d.ts b/packages/types/dialect.d.ts index 137a14be..f05dc052 100644 --- a/packages/types/dialect.d.ts +++ b/packages/types/dialect.d.ts @@ -32,4 +32,5 @@ export interface SqlDialect { dropCheck?: boolean; dropReferencesWhenDropTable?: boolean; + disableExplicitTransaction?: boolean; } diff --git a/packages/types/dumper.d.ts b/packages/types/dumper.d.ts index a439deb4..4b53e8a2 100644 --- a/packages/types/dumper.d.ts +++ b/packages/types/dumper.d.ts @@ -17,4 +17,6 @@ export interface SqlDumper extends AlterProcessor { endCommand(); allowIdentityInsert(table: NamedObjectInfo, allow: boolean); + beginTransaction(); + commitTransaction(); } diff --git a/packages/web/src/tabs/TableStructureTab.svelte b/packages/web/src/tabs/TableStructureTab.svelte index d65667b0..edb376be 100644 --- a/packages/web/src/tabs/TableStructureTab.svelte +++ b/packages/web/src/tabs/TableStructureTab.svelte @@ -102,7 +102,13 @@ function doSave(createTableName) { const driver = findEngineDriver($connection, $extensions); - const sql = getAlterTableScript($editorValue.base, fillConstraintNames($editorValue.current), {}, $dbInfo, driver); + const sql = getAlterTableScript( + $editorValue.base, + fillConstraintNames($editorValue.current, driver.dialect), + {}, + $dbInfo, + driver + ); showModal(ConfirmSqlModal, { sql, diff --git a/plugins/dbgate-plugin-sqlite/src/frontend/driver.js b/plugins/dbgate-plugin-sqlite/src/frontend/driver.js index f51f8c92..daebbf90 100644 --- a/plugins/dbgate-plugin-sqlite/src/frontend/driver.js +++ b/plugins/dbgate-plugin-sqlite/src/frontend/driver.js @@ -21,6 +21,8 @@ const dialect = { quoteIdentifier(s) { return `[${s}]`; }, + anonymousPrimaryKey: true, + disableExplicitTransaction: true, createColumn: true, dropColumn: true,