mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-26 00:45:58 +00:00
db diff supports views, procedures, functions
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { DbDiffOptions, testEqualColumns, testEqualTables } from './diffTools';
|
import { DbDiffOptions, testEqualColumns, testEqualTables, testEqualSqlObjects } from './diffTools';
|
||||||
import { DatabaseInfo, EngineDriver, TableInfo } from 'dbgate-types';
|
import { DatabaseInfo, EngineDriver, SqlObjectInfo, TableInfo } from 'dbgate-types';
|
||||||
|
|
||||||
export function computeDiffRowsCore(sourceList, targetList, testEqual) {
|
export function computeDiffRowsCore(sourceList, targetList, testEqual) {
|
||||||
const res = [];
|
const res = [];
|
||||||
@@ -35,6 +35,34 @@ export function computeDiffRowsCore(sourceList, targetList, testEqual) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const COMPARE_DEFS = {
|
||||||
|
tables: {
|
||||||
|
test: testEqualTables,
|
||||||
|
name: 'Table',
|
||||||
|
icon: 'img table',
|
||||||
|
},
|
||||||
|
views: {
|
||||||
|
test: testEqualSqlObjects,
|
||||||
|
name: 'View',
|
||||||
|
icon: 'img view',
|
||||||
|
},
|
||||||
|
matviews: {
|
||||||
|
test: testEqualSqlObjects,
|
||||||
|
name: 'Materialized view',
|
||||||
|
icon: 'img view',
|
||||||
|
},
|
||||||
|
procedures: {
|
||||||
|
test: testEqualSqlObjects,
|
||||||
|
name: 'Procedure',
|
||||||
|
icon: 'img procedure',
|
||||||
|
},
|
||||||
|
functions: {
|
||||||
|
test: testEqualSqlObjects,
|
||||||
|
name: 'Function',
|
||||||
|
icon: 'img function',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export function computeDbDiffRows(
|
export function computeDbDiffRows(
|
||||||
sourceDb: DatabaseInfo,
|
sourceDb: DatabaseInfo,
|
||||||
targetDb: DatabaseInfo,
|
targetDb: DatabaseInfo,
|
||||||
@@ -42,18 +70,29 @@ export function computeDbDiffRows(
|
|||||||
driver: EngineDriver
|
driver: EngineDriver
|
||||||
) {
|
) {
|
||||||
if (!sourceDb || !targetDb || !driver) return [];
|
if (!sourceDb || !targetDb || !driver) return [];
|
||||||
return computeDiffRowsCore(sourceDb.tables, targetDb.tables, (a, b) =>
|
|
||||||
testEqualTables(a, b, opts, targetDb, driver)
|
const res = [];
|
||||||
).map(row => ({
|
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
|
||||||
...row,
|
const defs = COMPARE_DEFS[objectTypeField];
|
||||||
sourceSchemaName: row?.source?.schemaName,
|
res.push(
|
||||||
sourcePureName: row?.source?.pureName,
|
...computeDiffRowsCore(sourceDb[objectTypeField], targetDb[objectTypeField], (a, b) =>
|
||||||
targetSchemaName: row?.target?.schemaName,
|
defs.test(a, b, opts, targetDb, driver)
|
||||||
targetPureName: row?.target?.pureName,
|
).map(row => ({
|
||||||
identifier: `${row?.source?.schemaName || row?.target?.schemaName}.${
|
...row,
|
||||||
row?.source?.pureName || row?.target?.pureName
|
sourceSchemaName: row?.source?.schemaName,
|
||||||
}`,
|
sourcePureName: row?.source?.pureName,
|
||||||
}));
|
targetSchemaName: row?.target?.schemaName,
|
||||||
|
targetPureName: row?.target?.pureName,
|
||||||
|
typeName: defs.name,
|
||||||
|
typeIcon: defs.icon,
|
||||||
|
identifier: `${row?.source?.schemaName || row?.target?.schemaName}.${
|
||||||
|
row?.source?.pureName || row?.target?.pureName
|
||||||
|
}`,
|
||||||
|
objectTypeField,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computeTableDiffColumns(
|
export function computeTableDiffColumns(
|
||||||
@@ -76,9 +115,12 @@ export function computeTableDiffColumns(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCreateObjectScript(table: TableInfo, driver: EngineDriver) {
|
export function getCreateObjectScript(obj: TableInfo | SqlObjectInfo, driver: EngineDriver) {
|
||||||
if (!table || !driver) return '';
|
if (!obj || !driver) return '';
|
||||||
const dmp = driver.createDumper();
|
if (obj.objectTypeField == 'tables') {
|
||||||
dmp.createTable(table);
|
const dmp = driver.createDumper();
|
||||||
return dmp.s;
|
dmp.createTable(obj as TableInfo);
|
||||||
|
return dmp.s;
|
||||||
|
}
|
||||||
|
return (obj as SqlObjectInfo).createSql || '';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
EngineDriver,
|
EngineDriver,
|
||||||
NamedObjectInfo,
|
NamedObjectInfo,
|
||||||
SqlDialect,
|
SqlDialect,
|
||||||
|
SqlObjectInfo,
|
||||||
TableInfo,
|
TableInfo,
|
||||||
} from 'dbgate-types';
|
} from 'dbgate-types';
|
||||||
import uuidv1 from 'uuid/v1';
|
import uuidv1 from 'uuid/v1';
|
||||||
@@ -381,6 +382,10 @@ export function testEqualTables(
|
|||||||
return plan.operations.length == 0;
|
return plan.operations.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function testEqualSqlObjects(a: SqlObjectInfo, b: SqlObjectInfo, opts: DbDiffOptions) {
|
||||||
|
return a.createSql == b.createSql;
|
||||||
|
}
|
||||||
|
|
||||||
export function createAlterTablePlan(
|
export function createAlterTablePlan(
|
||||||
oldTable: TableInfo,
|
oldTable: TableInfo,
|
||||||
newTable: TableInfo,
|
newTable: TableInfo,
|
||||||
@@ -425,7 +430,7 @@ export function createAlterDatabasePlan(
|
|||||||
if (!opts.noDropSqlObject) {
|
if (!opts.noDropSqlObject) {
|
||||||
plan.dropSqlObject(oldobj);
|
plan.dropSqlObject(oldobj);
|
||||||
}
|
}
|
||||||
} else if (newobj.createSql != oldobj.createSql) {
|
} else if (!testEqualSqlObjects(oldobj.createSql, newobj.createSql, opts)) {
|
||||||
plan.recreates.sqlObjects += 1;
|
plan.recreates.sqlObjects += 1;
|
||||||
if (!opts.noDropSqlObject) {
|
if (!opts.noDropSqlObject) {
|
||||||
plan.dropSqlObject(oldobj);
|
plan.dropSqlObject(oldobj);
|
||||||
|
|||||||
@@ -65,6 +65,20 @@
|
|||||||
}
|
}
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAlterObjectScript(objectTypeField, oldObject, newObject, opts, db, driver) {
|
||||||
|
if ((!oldObject && !newObject) || !driver) {
|
||||||
|
return { sql: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objectTypeField == 'tables') {
|
||||||
|
return getAlterTableScript(oldObject, newObject, opts, db, driver);
|
||||||
|
}
|
||||||
|
const dmp = driver.createDumper();
|
||||||
|
if (oldObject) dmp.dropSqlObject(oldObject);
|
||||||
|
if (newObject) dmp.createSqlObject(newObject);
|
||||||
|
return { sql: dmp.s };
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -141,7 +155,8 @@
|
|||||||
driver
|
driver
|
||||||
);
|
);
|
||||||
|
|
||||||
$: sqlPreview = getAlterTableScript(
|
$: sqlPreview = getAlterObjectScript(
|
||||||
|
diffRows[pairIndex]?.objectTypeField,
|
||||||
diffRows[pairIndex]?.target,
|
diffRows[pairIndex]?.target,
|
||||||
diffRows[pairIndex]?.source,
|
diffRows[pairIndex]?.source,
|
||||||
dbDiffOptions,
|
dbDiffOptions,
|
||||||
@@ -329,7 +344,7 @@
|
|||||||
disableFocusOutline
|
disableFocusOutline
|
||||||
columns={[
|
columns={[
|
||||||
{ fieldName: 'isChecked', header: '', width: '50px', slot: 1, headerSlot: 2 },
|
{ fieldName: 'isChecked', header: '', width: '50px', slot: 1, headerSlot: 2 },
|
||||||
{ fieldName: 'type', header: 'Type', width: '100px' },
|
{ fieldName: 'type', header: 'Type', width: '100px', slot: 3 },
|
||||||
{ fieldName: 'sourceSchemaName', header: 'Schema' },
|
{ fieldName: 'sourceSchemaName', header: 'Schema' },
|
||||||
{ fieldName: 'sourcePureName', header: 'Name' },
|
{ fieldName: 'sourcePureName', header: 'Name' },
|
||||||
{ fieldName: 'state', header: 'Action', width: '100px' },
|
{ fieldName: 'state', header: 'Action', width: '100px' },
|
||||||
@@ -353,6 +368,10 @@
|
|||||||
<FontIcon icon="icon check-all" />
|
<FontIcon icon="icon check-all" />
|
||||||
</InlineButton>
|
</InlineButton>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="3" let:row>
|
||||||
|
<FontIcon icon={row.typeIcon} />
|
||||||
|
{row.typeName}
|
||||||
|
</svelte:fragment>
|
||||||
</ScrollableTableControl>
|
</ScrollableTableControl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user