db diff supports views, procedures, functions

This commit is contained in:
Jan Prochazka 2021-11-07 11:18:21 +01:00
parent 1765ab4118
commit 73b338d38a
3 changed files with 88 additions and 22 deletions

View File

@ -1,5 +1,5 @@
import { DbDiffOptions, testEqualColumns, testEqualTables } from './diffTools';
import { DatabaseInfo, EngineDriver, TableInfo } from 'dbgate-types';
import { DbDiffOptions, testEqualColumns, testEqualTables, testEqualSqlObjects } from './diffTools';
import { DatabaseInfo, EngineDriver, SqlObjectInfo, TableInfo } from 'dbgate-types';
export function computeDiffRowsCore(sourceList, targetList, testEqual) {
const res = [];
@ -35,6 +35,34 @@ export function computeDiffRowsCore(sourceList, targetList, testEqual) {
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(
sourceDb: DatabaseInfo,
targetDb: DatabaseInfo,
@ -42,18 +70,29 @@ export function computeDbDiffRows(
driver: EngineDriver
) {
if (!sourceDb || !targetDb || !driver) return [];
return computeDiffRowsCore(sourceDb.tables, targetDb.tables, (a, b) =>
testEqualTables(a, b, opts, targetDb, driver)
).map(row => ({
...row,
sourceSchemaName: row?.source?.schemaName,
sourcePureName: row?.source?.pureName,
targetSchemaName: row?.target?.schemaName,
targetPureName: row?.target?.pureName,
identifier: `${row?.source?.schemaName || row?.target?.schemaName}.${
row?.source?.pureName || row?.target?.pureName
}`,
}));
const res = [];
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
const defs = COMPARE_DEFS[objectTypeField];
res.push(
...computeDiffRowsCore(sourceDb[objectTypeField], targetDb[objectTypeField], (a, b) =>
defs.test(a, b, opts, targetDb, driver)
).map(row => ({
...row,
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(
@ -76,9 +115,12 @@ export function computeTableDiffColumns(
}));
}
export function getCreateObjectScript(table: TableInfo, driver: EngineDriver) {
if (!table || !driver) return '';
const dmp = driver.createDumper();
dmp.createTable(table);
return dmp.s;
export function getCreateObjectScript(obj: TableInfo | SqlObjectInfo, driver: EngineDriver) {
if (!obj || !driver) return '';
if (obj.objectTypeField == 'tables') {
const dmp = driver.createDumper();
dmp.createTable(obj as TableInfo);
return dmp.s;
}
return (obj as SqlObjectInfo).createSql || '';
}

View File

@ -5,6 +5,7 @@ import {
EngineDriver,
NamedObjectInfo,
SqlDialect,
SqlObjectInfo,
TableInfo,
} from 'dbgate-types';
import uuidv1 from 'uuid/v1';
@ -381,6 +382,10 @@ export function testEqualTables(
return plan.operations.length == 0;
}
export function testEqualSqlObjects(a: SqlObjectInfo, b: SqlObjectInfo, opts: DbDiffOptions) {
return a.createSql == b.createSql;
}
export function createAlterTablePlan(
oldTable: TableInfo,
newTable: TableInfo,
@ -425,7 +430,7 @@ export function createAlterDatabasePlan(
if (!opts.noDropSqlObject) {
plan.dropSqlObject(oldobj);
}
} else if (newobj.createSql != oldobj.createSql) {
} else if (!testEqualSqlObjects(oldobj.createSql, newobj.createSql, opts)) {
plan.recreates.sqlObjects += 1;
if (!opts.noDropSqlObject) {
plan.dropSqlObject(oldobj);

View File

@ -65,6 +65,20 @@
}
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 lang="ts">
@ -141,7 +155,8 @@
driver
);
$: sqlPreview = getAlterTableScript(
$: sqlPreview = getAlterObjectScript(
diffRows[pairIndex]?.objectTypeField,
diffRows[pairIndex]?.target,
diffRows[pairIndex]?.source,
dbDiffOptions,
@ -329,7 +344,7 @@
disableFocusOutline
columns={[
{ 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: 'sourcePureName', header: 'Name' },
{ fieldName: 'state', header: 'Action', width: '100px' },
@ -353,6 +368,10 @@
<FontIcon icon="icon check-all" />
</InlineButton>
</svelte:fragment>
<svelte:fragment slot="3" let:row>
<FontIcon icon={row.typeIcon} />
{row.typeName}
</svelte:fragment>
</ScrollableTableControl>
</div>
</div>