dbgate-tools 4.3.4 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/alterPlan.d.ts +5 -1
- package/lib/alterPlan.js +60 -4
- package/lib/computeDiffRows.d.ts +38 -0
- package/lib/computeDiffRows.js +108 -0
- package/lib/database-info-alter-processor.js +6 -0
- package/lib/diffTools.d.ts +18 -5
- package/lib/diffTools.js +123 -38
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/yamlModelConv.d.ts +25 -0
- package/lib/yamlModelConv.js +136 -0
- package/package.json +3 -3
package/lib/alterPlan.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DbDiffOptions } from './diffTools';
|
|
1
2
|
import { AlterProcessor, ColumnInfo, ConstraintInfo, DatabaseInfo, SqlObjectInfo, SqlDialect, TableInfo } from '../../types';
|
|
2
3
|
interface AlterOperation_CreateTable {
|
|
3
4
|
operationType: 'createTable';
|
|
@@ -65,13 +66,14 @@ declare type AlterOperation = AlterOperation_CreateColumn | AlterOperation_Chang
|
|
|
65
66
|
export declare class AlterPlan {
|
|
66
67
|
db: DatabaseInfo;
|
|
67
68
|
dialect: SqlDialect;
|
|
69
|
+
opts: DbDiffOptions;
|
|
68
70
|
recreates: {
|
|
69
71
|
tables: number;
|
|
70
72
|
constraints: number;
|
|
71
73
|
sqlObjects: number;
|
|
72
74
|
};
|
|
73
75
|
operations: AlterOperation[];
|
|
74
|
-
constructor(db: DatabaseInfo, dialect: SqlDialect);
|
|
76
|
+
constructor(db: DatabaseInfo, dialect: SqlDialect, opts: DbDiffOptions);
|
|
75
77
|
createTable(table: TableInfo): void;
|
|
76
78
|
dropTable(table: TableInfo): void;
|
|
77
79
|
createSqlObject(obj: SqlObjectInfo): void;
|
|
@@ -94,6 +96,8 @@ export declare class AlterPlan {
|
|
|
94
96
|
_canDropConstraint(cnt: ConstraintInfo): boolean;
|
|
95
97
|
_testTableRecreate(op: AlterOperation, operationType: string, isAllowed: boolean | Function, objectField: string): AlterOperation[] | null;
|
|
96
98
|
_groupTableRecreations(): AlterOperation[];
|
|
99
|
+
_moveForeignKeysToLast(): AlterOperation[];
|
|
100
|
+
_filterAllowedOperations(): AlterOperation[];
|
|
97
101
|
transformPlan(): void;
|
|
98
102
|
}
|
|
99
103
|
export declare function runAlterOperation(op: AlterOperation, processor: AlterProcessor): void;
|
package/lib/alterPlan.js
CHANGED
|
@@ -5,13 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.runAlterOperation = exports.AlterPlan = void 0;
|
|
7
7
|
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
-
const
|
|
8
|
+
const diffTools_1 = require("./diffTools");
|
|
9
9
|
const database_info_alter_processor_1 = require("./database-info-alter-processor");
|
|
10
10
|
const DatabaseAnalyser_1 = require("./DatabaseAnalyser");
|
|
11
11
|
class AlterPlan {
|
|
12
|
-
constructor(db, dialect) {
|
|
12
|
+
constructor(db, dialect, opts) {
|
|
13
13
|
this.db = db;
|
|
14
14
|
this.dialect = dialect;
|
|
15
|
+
this.opts = opts;
|
|
15
16
|
this.recreates = {
|
|
16
17
|
tables: 0,
|
|
17
18
|
constraints: 0,
|
|
@@ -117,6 +118,8 @@ class AlterPlan {
|
|
|
117
118
|
}
|
|
118
119
|
_getDependendColumnConstraints(column, dependencyDefinition) {
|
|
119
120
|
const table = this.db.tables.find(x => x.pureName == column.pureName && x.schemaName == column.schemaName);
|
|
121
|
+
if (!table)
|
|
122
|
+
return [];
|
|
120
123
|
const fks = (dependencyDefinition === null || dependencyDefinition === void 0 ? void 0 : dependencyDefinition.includes('dependencies'))
|
|
121
124
|
? table.dependencies.filter(fk => fk.columns.find(col => col.refColumnName == column.columnName))
|
|
122
125
|
: [];
|
|
@@ -132,6 +135,9 @@ class AlterPlan {
|
|
|
132
135
|
const lists = this.operations.map(op => {
|
|
133
136
|
if (op.operationType == 'dropColumn') {
|
|
134
137
|
const constraints = this._getDependendColumnConstraints(op.oldObject, this.dialect.dropColumnDependencies);
|
|
138
|
+
if (constraints.length > 0 && this.opts.noDropConstraint) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
135
141
|
const res = [
|
|
136
142
|
...constraints.map(oldObject => {
|
|
137
143
|
const opRes = {
|
|
@@ -146,6 +152,9 @@ class AlterPlan {
|
|
|
146
152
|
}
|
|
147
153
|
if (op.operationType == 'changeColumn') {
|
|
148
154
|
const constraints = this._getDependendColumnConstraints(op.oldObject, this.dialect.changeColumnDependencies);
|
|
155
|
+
if (constraints.length > 0 && this.opts.noDropConstraint) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
149
158
|
const res = [
|
|
150
159
|
...constraints.map(oldObject => {
|
|
151
160
|
const opRes = {
|
|
@@ -183,6 +192,10 @@ class AlterPlan {
|
|
|
183
192
|
];
|
|
184
193
|
}
|
|
185
194
|
if (op.operationType == 'changeConstraint') {
|
|
195
|
+
if (this.opts.noDropConstraint) {
|
|
196
|
+
// skip constraint recreate
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
186
199
|
this.recreates.constraints += 1;
|
|
187
200
|
const opDrop = {
|
|
188
201
|
operationType: 'dropConstraint',
|
|
@@ -246,6 +259,10 @@ class AlterPlan {
|
|
|
246
259
|
}
|
|
247
260
|
// console.log('*****************RECREATED NEEDED', op, operationType, isAllowed);
|
|
248
261
|
// console.log(this.dialect);
|
|
262
|
+
if (this.opts.noDropTable) {
|
|
263
|
+
// skip this operation, as it cannot be achieved
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
249
266
|
const table = this.db.tables.find(x => x.pureName == op[objectField].pureName && x.schemaName == op[objectField].schemaName);
|
|
250
267
|
this.recreates.tables += 1;
|
|
251
268
|
return [
|
|
@@ -262,7 +279,7 @@ class AlterPlan {
|
|
|
262
279
|
const res = [];
|
|
263
280
|
const recreates = {};
|
|
264
281
|
for (const op of this.operations) {
|
|
265
|
-
if (op.operationType == 'recreateTable') {
|
|
282
|
+
if (op.operationType == 'recreateTable' && op.table) {
|
|
266
283
|
const existingRecreate = recreates[`${op.table.schemaName}||${op.table.pureName}`];
|
|
267
284
|
if (existingRecreate) {
|
|
268
285
|
existingRecreate.operations.push(...op.operations);
|
|
@@ -288,6 +305,41 @@ class AlterPlan {
|
|
|
288
305
|
}
|
|
289
306
|
return res;
|
|
290
307
|
}
|
|
308
|
+
_moveForeignKeysToLast() {
|
|
309
|
+
if (!this.dialect.createForeignKey) {
|
|
310
|
+
return this.operations;
|
|
311
|
+
}
|
|
312
|
+
const fks = [];
|
|
313
|
+
const res = this.operations.map(op => {
|
|
314
|
+
if (op.operationType == 'createTable') {
|
|
315
|
+
fks.push(...(op.newObject.foreignKeys || []));
|
|
316
|
+
return Object.assign(Object.assign({}, op), { newObject: Object.assign(Object.assign({}, op.newObject), { foreignKeys: [] }) });
|
|
317
|
+
}
|
|
318
|
+
return op;
|
|
319
|
+
});
|
|
320
|
+
return [
|
|
321
|
+
...res,
|
|
322
|
+
...fks.map(fk => ({
|
|
323
|
+
operationType: 'createConstraint',
|
|
324
|
+
newObject: fk,
|
|
325
|
+
})),
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
_filterAllowedOperations() {
|
|
329
|
+
return this.operations.filter(op => {
|
|
330
|
+
if (this.opts.noDropColumn && op.operationType == 'dropColumn')
|
|
331
|
+
return false;
|
|
332
|
+
if (this.opts.noDropTable && op.operationType == 'dropTable')
|
|
333
|
+
return false;
|
|
334
|
+
if (this.opts.noDropTable && op.operationType == 'recreateTable')
|
|
335
|
+
return false;
|
|
336
|
+
if (this.opts.noDropConstraint && op.operationType == 'dropConstraint')
|
|
337
|
+
return false;
|
|
338
|
+
if (this.opts.noDropSqlObject && op.operationType == 'dropSqlObject')
|
|
339
|
+
return false;
|
|
340
|
+
return true;
|
|
341
|
+
});
|
|
342
|
+
}
|
|
291
343
|
transformPlan() {
|
|
292
344
|
// console.log('*****************OPERATIONS0', this.operations);
|
|
293
345
|
this.operations = this._addLogicalDependencies();
|
|
@@ -296,6 +348,10 @@ class AlterPlan {
|
|
|
296
348
|
// console.log('*****************OPERATIONS2', this.operations);
|
|
297
349
|
this.operations = this._groupTableRecreations();
|
|
298
350
|
// console.log('*****************OPERATIONS3', this.operations);
|
|
351
|
+
this.operations = this._moveForeignKeysToLast();
|
|
352
|
+
// console.log('*****************OPERATIONS4', this.operations);
|
|
353
|
+
this.operations = this._filterAllowedOperations();
|
|
354
|
+
// console.log('*****************OPERATIONS5', this.operations);
|
|
299
355
|
}
|
|
300
356
|
}
|
|
301
357
|
exports.AlterPlan = AlterPlan;
|
|
@@ -342,7 +398,7 @@ function runAlterOperation(op, processor) {
|
|
|
342
398
|
break;
|
|
343
399
|
case 'recreateTable':
|
|
344
400
|
{
|
|
345
|
-
const oldTable = (0,
|
|
401
|
+
const oldTable = (0, diffTools_1.generateTablePairingId)(op.table);
|
|
346
402
|
const newTable = lodash_1.default.cloneDeep(oldTable);
|
|
347
403
|
const newDb = DatabaseAnalyser_1.DatabaseAnalyser.createEmptyStructure();
|
|
348
404
|
newDb.tables.push(newTable);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { DbDiffOptions, testEqualTables, testEqualSqlObjects } from './diffTools';
|
|
2
|
+
import { DatabaseInfo, EngineDriver, SqlObjectInfo, TableInfo } from 'dbgate-types';
|
|
3
|
+
export declare function computeDiffRowsCore(sourceList: any, targetList: any, testEqual: any): any[];
|
|
4
|
+
export declare const DbDiffCompareDefs: {
|
|
5
|
+
tables: {
|
|
6
|
+
test: typeof testEqualTables;
|
|
7
|
+
name: string;
|
|
8
|
+
plural: string;
|
|
9
|
+
icon: string;
|
|
10
|
+
};
|
|
11
|
+
views: {
|
|
12
|
+
test: typeof testEqualSqlObjects;
|
|
13
|
+
name: string;
|
|
14
|
+
plural: string;
|
|
15
|
+
icon: string;
|
|
16
|
+
};
|
|
17
|
+
matviews: {
|
|
18
|
+
test: typeof testEqualSqlObjects;
|
|
19
|
+
name: string;
|
|
20
|
+
plural: string;
|
|
21
|
+
icon: string;
|
|
22
|
+
};
|
|
23
|
+
procedures: {
|
|
24
|
+
test: typeof testEqualSqlObjects;
|
|
25
|
+
name: string;
|
|
26
|
+
plural: string;
|
|
27
|
+
icon: string;
|
|
28
|
+
};
|
|
29
|
+
functions: {
|
|
30
|
+
test: typeof testEqualSqlObjects;
|
|
31
|
+
name: string;
|
|
32
|
+
plural: string;
|
|
33
|
+
icon: string;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export declare function computeDbDiffRows(sourceDb: DatabaseInfo, targetDb: DatabaseInfo, opts: DbDiffOptions, driver: EngineDriver): any[];
|
|
37
|
+
export declare function computeTableDiffColumns(sourceTable: TableInfo, targetTable: TableInfo, opts: DbDiffOptions, driver: EngineDriver): any[];
|
|
38
|
+
export declare function getCreateObjectScript(obj: TableInfo | SqlObjectInfo, driver: EngineDriver): string;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getCreateObjectScript = exports.computeTableDiffColumns = exports.computeDbDiffRows = exports.DbDiffCompareDefs = exports.computeDiffRowsCore = void 0;
|
|
7
|
+
const diffTools_1 = require("./diffTools");
|
|
8
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
9
|
+
function computeDiffRowsCore(sourceList, targetList, testEqual) {
|
|
10
|
+
const res = [];
|
|
11
|
+
for (const obj of sourceList) {
|
|
12
|
+
const paired = targetList.find(x => x.pairingId == obj.pairingId);
|
|
13
|
+
if (paired) {
|
|
14
|
+
const isEqual = testEqual(obj, paired);
|
|
15
|
+
res.push({
|
|
16
|
+
source: obj,
|
|
17
|
+
target: paired,
|
|
18
|
+
state: isEqual ? 'equal' : 'changed',
|
|
19
|
+
__isChanged: !isEqual,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
res.push({
|
|
24
|
+
source: obj,
|
|
25
|
+
state: 'added',
|
|
26
|
+
__isAdded: true,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
for (const obj of targetList) {
|
|
31
|
+
const paired = sourceList.find(x => x.pairingId == obj.pairingId);
|
|
32
|
+
if (!paired) {
|
|
33
|
+
res.push({
|
|
34
|
+
target: obj,
|
|
35
|
+
state: 'removed',
|
|
36
|
+
__isDeleted: true,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return res;
|
|
41
|
+
}
|
|
42
|
+
exports.computeDiffRowsCore = computeDiffRowsCore;
|
|
43
|
+
exports.DbDiffCompareDefs = {
|
|
44
|
+
tables: {
|
|
45
|
+
test: diffTools_1.testEqualTables,
|
|
46
|
+
name: 'Table',
|
|
47
|
+
plural: 'Tables',
|
|
48
|
+
icon: 'img table',
|
|
49
|
+
},
|
|
50
|
+
views: {
|
|
51
|
+
test: diffTools_1.testEqualSqlObjects,
|
|
52
|
+
name: 'View',
|
|
53
|
+
plural: 'Views',
|
|
54
|
+
icon: 'img view',
|
|
55
|
+
},
|
|
56
|
+
matviews: {
|
|
57
|
+
test: diffTools_1.testEqualSqlObjects,
|
|
58
|
+
name: 'Materialized view',
|
|
59
|
+
plural: 'Materialized views',
|
|
60
|
+
icon: 'img view',
|
|
61
|
+
},
|
|
62
|
+
procedures: {
|
|
63
|
+
test: diffTools_1.testEqualSqlObjects,
|
|
64
|
+
name: 'Procedure',
|
|
65
|
+
plural: 'Procedures',
|
|
66
|
+
icon: 'img procedure',
|
|
67
|
+
},
|
|
68
|
+
functions: {
|
|
69
|
+
test: diffTools_1.testEqualSqlObjects,
|
|
70
|
+
name: 'Function',
|
|
71
|
+
plural: 'Functions',
|
|
72
|
+
icon: 'img function',
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
function computeDbDiffRows(sourceDb, targetDb, opts, driver) {
|
|
76
|
+
if (!sourceDb || !targetDb || !driver)
|
|
77
|
+
return [];
|
|
78
|
+
const res = [];
|
|
79
|
+
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
|
|
80
|
+
const defs = exports.DbDiffCompareDefs[objectTypeField];
|
|
81
|
+
res.push(...lodash_1.default.sortBy(computeDiffRowsCore(sourceDb[objectTypeField], targetDb[objectTypeField], (a, b) => defs.test(a, b, opts, targetDb, driver)).map(row => {
|
|
82
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
83
|
+
return (Object.assign(Object.assign({}, row), { sourceSchemaName: (_a = row === null || row === void 0 ? void 0 : row.source) === null || _a === void 0 ? void 0 : _a.schemaName, sourcePureName: (_b = row === null || row === void 0 ? void 0 : row.source) === null || _b === void 0 ? void 0 : _b.pureName, targetSchemaName: (_c = row === null || row === void 0 ? void 0 : row.target) === null || _c === void 0 ? void 0 : _c.schemaName, targetPureName: (_d = row === null || row === void 0 ? void 0 : row.target) === null || _d === void 0 ? void 0 : _d.pureName, typeName: defs.name, typeIcon: defs.icon, identifier: `${((_e = row === null || row === void 0 ? void 0 : row.source) === null || _e === void 0 ? void 0 : _e.schemaName) || ((_f = row === null || row === void 0 ? void 0 : row.target) === null || _f === void 0 ? void 0 : _f.schemaName)}.${((_g = row === null || row === void 0 ? void 0 : row.source) === null || _g === void 0 ? void 0 : _g.pureName) || ((_h = row === null || row === void 0 ? void 0 : row.target) === null || _h === void 0 ? void 0 : _h.pureName)}`, objectTypeField }));
|
|
84
|
+
}), 'identifier'));
|
|
85
|
+
}
|
|
86
|
+
return res;
|
|
87
|
+
}
|
|
88
|
+
exports.computeDbDiffRows = computeDbDiffRows;
|
|
89
|
+
function computeTableDiffColumns(sourceTable, targetTable, opts, driver) {
|
|
90
|
+
if (!driver)
|
|
91
|
+
return [];
|
|
92
|
+
return computeDiffRowsCore((sourceTable === null || sourceTable === void 0 ? void 0 : sourceTable.columns) || [], (targetTable === null || targetTable === void 0 ? void 0 : targetTable.columns) || [], (a, b) => (0, diffTools_1.testEqualColumns)(a, b, true, true, opts)).map(row => {
|
|
93
|
+
var _a, _b, _c, _d, _e, _f;
|
|
94
|
+
return (Object.assign(Object.assign({}, row), { sourceColumnName: (_a = row === null || row === void 0 ? void 0 : row.source) === null || _a === void 0 ? void 0 : _a.columnName, targetColumnName: (_b = row === null || row === void 0 ? void 0 : row.target) === null || _b === void 0 ? void 0 : _b.columnName, sourceDataType: (_c = row === null || row === void 0 ? void 0 : row.source) === null || _c === void 0 ? void 0 : _c.dataType, targetDataType: (_d = row === null || row === void 0 ? void 0 : row.target) === null || _d === void 0 ? void 0 : _d.dataType, sourceNotNull: (_e = row === null || row === void 0 ? void 0 : row.source) === null || _e === void 0 ? void 0 : _e.notNull, targetNotNull: (_f = row === null || row === void 0 ? void 0 : row.target) === null || _f === void 0 ? void 0 : _f.notNull }));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
exports.computeTableDiffColumns = computeTableDiffColumns;
|
|
98
|
+
function getCreateObjectScript(obj, driver) {
|
|
99
|
+
if (!obj || !driver)
|
|
100
|
+
return '';
|
|
101
|
+
if (obj.objectTypeField == 'tables') {
|
|
102
|
+
const dmp = driver.createDumper();
|
|
103
|
+
dmp.createTable(obj);
|
|
104
|
+
return dmp.s;
|
|
105
|
+
}
|
|
106
|
+
return obj.createSql || '';
|
|
107
|
+
}
|
|
108
|
+
exports.getCreateObjectScript = getCreateObjectScript;
|
|
@@ -23,14 +23,20 @@ class DatabaseInfoAlterProcessor {
|
|
|
23
23
|
}
|
|
24
24
|
createColumn(column) {
|
|
25
25
|
const table = this.db.tables.find(x => x.pureName == column.pureName && x.schemaName == column.schemaName);
|
|
26
|
+
if (!table)
|
|
27
|
+
throw new Error(`createColumn error, cannot find table: ${column.schemaName}.${column.pureName}`);
|
|
26
28
|
table.columns.push(column);
|
|
27
29
|
}
|
|
28
30
|
changeColumn(oldColumn, newColumn) {
|
|
29
31
|
const table = this.db.tables.find(x => x.pureName == oldColumn.pureName && x.schemaName == oldColumn.schemaName);
|
|
32
|
+
if (!table)
|
|
33
|
+
throw new Error(`changeColumn error, cannot find table: ${oldColumn.schemaName}.${oldColumn.pureName}`);
|
|
30
34
|
table.columns = table.columns.map(x => (x.columnName == oldColumn.columnName ? newColumn : x));
|
|
31
35
|
}
|
|
32
36
|
dropColumn(column) {
|
|
33
37
|
const table = this.db.tables.find(x => x.pureName == column.pureName && x.schemaName == column.schemaName);
|
|
38
|
+
if (!table)
|
|
39
|
+
throw new Error(`dropColumn error, cannot find table: ${column.schemaName}.${column.pureName}`);
|
|
34
40
|
lodash_1.default.remove(table.columns, x => x.columnName == column.columnName);
|
|
35
41
|
}
|
|
36
42
|
createConstraint(constraint) {
|
package/lib/diffTools.d.ts
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
|
-
import { ColumnInfo, DatabaseInfo, EngineDriver, TableInfo } from 'dbgate-types';
|
|
1
|
+
import { ColumnInfo, DatabaseInfo, EngineDriver, SqlObjectInfo, TableInfo } from 'dbgate-types';
|
|
2
2
|
import { AlterPlan } from './alterPlan';
|
|
3
3
|
declare type DbDiffSchemaMode = 'strict' | 'ignore' | 'ignoreImplicit';
|
|
4
4
|
export interface DbDiffOptions {
|
|
5
|
-
allowRecreateTable?: boolean;
|
|
6
|
-
allowRecreateConstraint?: boolean;
|
|
7
|
-
allowRecreateSpecificObject?: boolean;
|
|
8
|
-
allowPairRenamedTables?: boolean;
|
|
9
5
|
ignoreCase?: boolean;
|
|
10
6
|
schemaMode?: DbDiffSchemaMode;
|
|
11
7
|
leftImplicitSchema?: string;
|
|
12
8
|
rightImplicitSchema?: string;
|
|
9
|
+
ignoreConstraintNames?: boolean;
|
|
10
|
+
noDropTable?: boolean;
|
|
11
|
+
noDropColumn?: boolean;
|
|
12
|
+
noDropConstraint?: boolean;
|
|
13
|
+
noDropSqlObject?: boolean;
|
|
14
|
+
noRenameTable?: boolean;
|
|
15
|
+
noRenameColumn?: boolean;
|
|
16
|
+
ignoreForeignKeyActions?: boolean;
|
|
17
|
+
ignoreDataTypes?: boolean;
|
|
13
18
|
}
|
|
14
19
|
export declare function generateTablePairingId(table: TableInfo): TableInfo;
|
|
15
20
|
export declare function generateDbPairingId(db: DatabaseInfo): DatabaseInfo;
|
|
16
21
|
export declare function testEqualColumns(a: ColumnInfo, b: ColumnInfo, checkName: boolean, checkDefault: boolean, opts?: DbDiffOptions): boolean;
|
|
17
22
|
export declare function testEqualTypes(a: ColumnInfo, b: ColumnInfo, opts?: DbDiffOptions): boolean;
|
|
23
|
+
export declare function testEqualTables(a: TableInfo, b: TableInfo, opts: DbDiffOptions, db: DatabaseInfo, driver: EngineDriver): boolean;
|
|
24
|
+
export declare function testEqualSqlObjects(a: SqlObjectInfo, b: SqlObjectInfo, opts: DbDiffOptions): boolean;
|
|
18
25
|
export declare function createAlterTablePlan(oldTable: TableInfo, newTable: TableInfo, opts: DbDiffOptions, db: DatabaseInfo, driver: EngineDriver): AlterPlan;
|
|
19
26
|
export declare function createAlterDatabasePlan(oldDb: DatabaseInfo, newDb: DatabaseInfo, opts: DbDiffOptions, db: DatabaseInfo, driver: EngineDriver): AlterPlan;
|
|
20
27
|
export declare function getAlterTableScript(oldTable: TableInfo, newTable: TableInfo, opts: DbDiffOptions, db: DatabaseInfo, driver: EngineDriver): {
|
|
28
|
+
sql: string;
|
|
29
|
+
recreates: any[];
|
|
30
|
+
} | {
|
|
21
31
|
sql: string;
|
|
22
32
|
recreates: {
|
|
23
33
|
tables: number;
|
|
@@ -32,5 +42,8 @@ export declare function getAlterDatabaseScript(oldDb: DatabaseInfo, newDb: Datab
|
|
|
32
42
|
constraints: number;
|
|
33
43
|
sqlObjects: number;
|
|
34
44
|
};
|
|
45
|
+
isEmpty: boolean;
|
|
35
46
|
};
|
|
47
|
+
export declare function matchPairedObjects(db1: DatabaseInfo, db2: DatabaseInfo, opts: DbDiffOptions): DatabaseInfo;
|
|
48
|
+
export declare const modelCompareDbDiffOptions: DbDiffOptions;
|
|
36
49
|
export {};
|
package/lib/diffTools.js
CHANGED
|
@@ -3,10 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getAlterDatabaseScript = exports.getAlterTableScript = exports.createAlterDatabasePlan = exports.createAlterTablePlan = exports.testEqualTypes = exports.testEqualColumns = exports.generateDbPairingId = exports.generateTablePairingId = void 0;
|
|
6
|
+
exports.modelCompareDbDiffOptions = exports.matchPairedObjects = exports.getAlterDatabaseScript = exports.getAlterTableScript = exports.createAlterDatabasePlan = exports.createAlterTablePlan = exports.testEqualSqlObjects = exports.testEqualTables = exports.testEqualTypes = exports.testEqualColumns = exports.generateDbPairingId = exports.generateTablePairingId = void 0;
|
|
7
7
|
const v1_1 = __importDefault(require("uuid/v1"));
|
|
8
8
|
const alterPlan_1 = require("./alterPlan");
|
|
9
9
|
const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
|
|
10
|
+
const omit_1 = __importDefault(require("lodash/omit"));
|
|
11
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
12
|
+
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
|
13
|
+
const pick_1 = __importDefault(require("lodash/pick"));
|
|
10
14
|
function generateTablePairingId(table) {
|
|
11
15
|
var _a, _b, _c, _d, _e;
|
|
12
16
|
if (!table)
|
|
@@ -33,7 +37,7 @@ function generateDbPairingId(db) {
|
|
|
33
37
|
exports.generateDbPairingId = generateDbPairingId;
|
|
34
38
|
function testEqualNames(a, b, opts) {
|
|
35
39
|
if (opts.ignoreCase)
|
|
36
|
-
return a.toLowerCase() == b.toLowerCase();
|
|
40
|
+
return (a || '').toLowerCase() == (b || '').toLowerCase();
|
|
37
41
|
return a == b;
|
|
38
42
|
}
|
|
39
43
|
function testEqualSchemas(lschema, rschema, opts) {
|
|
@@ -63,6 +67,7 @@ function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
|
63
67
|
// return false;
|
|
64
68
|
//}
|
|
65
69
|
if (a.computedExpression != b.computedExpression) {
|
|
70
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different computed expression: ${a.computedExpression}, ${b.computedExpression}`);
|
|
66
71
|
// opts.DiffLogger.Trace(
|
|
67
72
|
// 'Column {0}, {1}: different computed expression: {2}; {3}',
|
|
68
73
|
// a,
|
|
@@ -78,6 +83,7 @@ function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
|
78
83
|
if (checkDefault) {
|
|
79
84
|
if (a.defaultValue == null) {
|
|
80
85
|
if (a.defaultValue != b.defaultValue) {
|
|
86
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different default value: ${a.defaultValue}, ${b.defaultValue}`);
|
|
81
87
|
// opts.DiffLogger.Trace(
|
|
82
88
|
// 'Column {0}, {1}: different default values: {2}; {3}',
|
|
83
89
|
// a,
|
|
@@ -90,6 +96,7 @@ function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
|
90
96
|
}
|
|
91
97
|
else {
|
|
92
98
|
if (a.defaultValue != b.defaultValue) {
|
|
99
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different default value: ${a.defaultValue}, ${b.defaultValue}`);
|
|
93
100
|
// opts.DiffLogger.Trace(
|
|
94
101
|
// 'Column {0}, {1}: different default values: {2}; {3}',
|
|
95
102
|
// a,
|
|
@@ -101,6 +108,7 @@ function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
110
|
if (a.defaultConstraint != b.defaultConstraint) {
|
|
111
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different default constraint: ${a.defaultConstraint}, ${b.defaultConstraint}`);
|
|
104
112
|
// opts.DiffLogger.Trace(
|
|
105
113
|
// 'Column {0}, {1}: different default constraint names: {2}; {3}',
|
|
106
114
|
// a,
|
|
@@ -111,15 +119,18 @@ function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
|
111
119
|
return false;
|
|
112
120
|
}
|
|
113
121
|
}
|
|
114
|
-
if (a.notNull != b.notNull) {
|
|
122
|
+
if ((a.notNull || false) != (b.notNull || false)) {
|
|
123
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different nullability: ${a.notNull}, ${b.notNull}`);
|
|
115
124
|
// opts.DiffLogger.Trace('Column {0}, {1}: different nullable: {2}; {3}', a, b, a.NotNull, b.NotNull);
|
|
116
125
|
return false;
|
|
117
126
|
}
|
|
118
|
-
if (a.autoIncrement != b.autoIncrement) {
|
|
127
|
+
if ((a.autoIncrement || false) != (b.autoIncrement || false)) {
|
|
128
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different autoincrement: ${a.autoIncrement}, ${b.autoIncrement}`);
|
|
119
129
|
// opts.DiffLogger.Trace('Column {0}, {1}: different autoincrement: {2}; {3}', a, b, a.AutoIncrement, b.AutoIncrement);
|
|
120
130
|
return false;
|
|
121
131
|
}
|
|
122
|
-
if (a.isSparse != b.isSparse) {
|
|
132
|
+
if ((a.isSparse || false) != (b.isSparse || false)) {
|
|
133
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different is_sparse: ${a.isSparse}, ${b.isSparse}`);
|
|
123
134
|
// opts.DiffLogger.Trace('Column {0}, {1}: different is_sparse: {2}; {3}', a, b, a.IsSparse, b.IsSparse);
|
|
124
135
|
return false;
|
|
125
136
|
}
|
|
@@ -154,28 +165,36 @@ function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
|
154
165
|
}
|
|
155
166
|
exports.testEqualColumns = testEqualColumns;
|
|
156
167
|
function testEqualConstraints(a, b, opts = {}) {
|
|
157
|
-
|
|
168
|
+
const omitList = [];
|
|
169
|
+
if (opts.ignoreForeignKeyActions) {
|
|
170
|
+
omitList.push('updateAction');
|
|
171
|
+
omitList.push('deleteAction');
|
|
172
|
+
}
|
|
173
|
+
if (opts.ignoreConstraintNames) {
|
|
174
|
+
omitList.push('constraintName');
|
|
175
|
+
}
|
|
176
|
+
if (opts.schemaMode == 'ignore') {
|
|
177
|
+
omitList.push('schemaName');
|
|
178
|
+
omitList.push('refSchemaName');
|
|
179
|
+
}
|
|
180
|
+
// if (a.constraintType == 'primaryKey' && b.constraintType == 'primaryKey') {
|
|
181
|
+
// console.log('PK1', stableStringify(_.omit(a, omitList)));
|
|
182
|
+
// console.log('PK2', stableStringify(_.omit(b, omitList)));
|
|
183
|
+
// }
|
|
184
|
+
// if (a.constraintType == 'foreignKey' && b.constraintType == 'foreignKey') {
|
|
185
|
+
// console.log('FK1', stableStringify(_omit(a, omitList)));
|
|
186
|
+
// console.log('FK2', stableStringify(_omit(b, omitList)));
|
|
187
|
+
// }
|
|
188
|
+
return (0, json_stable_stringify_1.default)((0, omit_1.default)(a, omitList)) == (0, json_stable_stringify_1.default)((0, omit_1.default)(b, omitList));
|
|
158
189
|
}
|
|
159
190
|
function testEqualTypes(a, b, opts = {}) {
|
|
160
|
-
if (
|
|
161
|
-
|
|
191
|
+
if (opts.ignoreDataTypes) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
if ((a.dataType || '').toLowerCase() != (b.dataType || '').toLowerCase()) {
|
|
195
|
+
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different data type: ${a.dataType}, ${b.dataType}`);
|
|
162
196
|
return false;
|
|
163
197
|
}
|
|
164
|
-
//if (a.Length != b.Length)
|
|
165
|
-
//{
|
|
166
|
-
// opts.DiffLogger.Trace("Column {0}, {1}: different lengths: {2}; {3}", a, b, a.Length, b.Length);
|
|
167
|
-
// return false;
|
|
168
|
-
//}
|
|
169
|
-
//if (a.Precision != b.Precision)
|
|
170
|
-
//{
|
|
171
|
-
// opts.DiffLogger.Trace("Column {0}, {1}: different lengths: {2}; {3}", a, b, a.Precision, b.Precision);
|
|
172
|
-
// return false;
|
|
173
|
-
//}
|
|
174
|
-
//if (a.Scale != b.Scale)
|
|
175
|
-
//{
|
|
176
|
-
// opts.DiffLogger.Trace("Column {0}, {1}: different scale: {2}; {3}", a, b, a.Scale, b.Scale);
|
|
177
|
-
// return false;
|
|
178
|
-
//}
|
|
179
198
|
return true;
|
|
180
199
|
}
|
|
181
200
|
exports.testEqualTypes = testEqualTypes;
|
|
@@ -215,9 +234,13 @@ function planAlterTable(plan, oldTable, newTable, opts) {
|
|
|
215
234
|
// if (oldTable.primaryKey)
|
|
216
235
|
const columnPairs = createPairs(oldTable.columns, newTable.columns);
|
|
217
236
|
const constraintPairs = createPairs(getTableConstraints(oldTable), getTableConstraints(newTable), (a, b) => a.constraintType == 'primaryKey' && b.constraintType == 'primaryKey');
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
237
|
+
if (!opts.noDropConstraint) {
|
|
238
|
+
constraintPairs.filter(x => x[1] == null).forEach(x => plan.dropConstraint(x[0]));
|
|
239
|
+
}
|
|
240
|
+
if (!opts.noDropColumn) {
|
|
241
|
+
columnPairs.filter(x => x[1] == null).forEach(x => plan.dropColumn(x[0]));
|
|
242
|
+
}
|
|
243
|
+
if (!testEqualFullNames(oldTable, newTable, opts) && !opts.noRenameTable) {
|
|
221
244
|
plan.renameTable(oldTable, newTable.pureName);
|
|
222
245
|
}
|
|
223
246
|
columnPairs.filter(x => x[0] == null).forEach(x => plan.createColumn(x[1]));
|
|
@@ -225,7 +248,7 @@ function planAlterTable(plan, oldTable, newTable, opts) {
|
|
|
225
248
|
.filter(x => x[0] && x[1])
|
|
226
249
|
.forEach(x => {
|
|
227
250
|
if (!testEqualColumns(x[0], x[1], true, true, opts)) {
|
|
228
|
-
if (testEqualColumns(x[0], x[1], false, true, opts)) {
|
|
251
|
+
if (testEqualColumns(x[0], x[1], false, true, opts) && !opts.noRenameColumn) {
|
|
229
252
|
// console.log('PLAN RENAME COLUMN')
|
|
230
253
|
plan.renameColumn(x[0], x[1].columnName);
|
|
231
254
|
}
|
|
@@ -245,11 +268,25 @@ function planAlterTable(plan, oldTable, newTable, opts) {
|
|
|
245
268
|
});
|
|
246
269
|
constraintPairs.filter(x => x[0] == null).forEach(x => plan.createConstraint(x[1]));
|
|
247
270
|
}
|
|
271
|
+
function testEqualTables(a, b, opts, db, driver) {
|
|
272
|
+
const plan = new alterPlan_1.AlterPlan(db, driver.dialect, opts);
|
|
273
|
+
planAlterTable(plan, a, b, opts);
|
|
274
|
+
// console.log('plan.operations', a, b, plan.operations);
|
|
275
|
+
return plan.operations.length == 0;
|
|
276
|
+
}
|
|
277
|
+
exports.testEqualTables = testEqualTables;
|
|
278
|
+
function testEqualSqlObjects(a, b, opts) {
|
|
279
|
+
return a.createSql == b.createSql;
|
|
280
|
+
}
|
|
281
|
+
exports.testEqualSqlObjects = testEqualSqlObjects;
|
|
248
282
|
function createAlterTablePlan(oldTable, newTable, opts, db, driver) {
|
|
249
|
-
const plan = new alterPlan_1.AlterPlan(db, driver.dialect);
|
|
283
|
+
const plan = new alterPlan_1.AlterPlan(db, driver.dialect, opts);
|
|
250
284
|
if (oldTable == null) {
|
|
251
285
|
plan.createTable(newTable);
|
|
252
286
|
}
|
|
287
|
+
else if (newTable == null) {
|
|
288
|
+
plan.dropTable(oldTable);
|
|
289
|
+
}
|
|
253
290
|
else {
|
|
254
291
|
planAlterTable(plan, oldTable, newTable, opts);
|
|
255
292
|
}
|
|
@@ -258,22 +295,31 @@ function createAlterTablePlan(oldTable, newTable, opts, db, driver) {
|
|
|
258
295
|
}
|
|
259
296
|
exports.createAlterTablePlan = createAlterTablePlan;
|
|
260
297
|
function createAlterDatabasePlan(oldDb, newDb, opts, db, driver) {
|
|
261
|
-
const plan = new alterPlan_1.AlterPlan(db, driver.dialect);
|
|
298
|
+
const plan = new alterPlan_1.AlterPlan(db, driver.dialect, opts);
|
|
262
299
|
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
|
|
263
300
|
for (const oldobj of oldDb[objectTypeField] || []) {
|
|
264
301
|
const newobj = (newDb[objectTypeField] || []).find(x => x.pairingId == oldobj.pairingId);
|
|
265
302
|
if (objectTypeField == 'tables') {
|
|
266
|
-
if (newobj == null)
|
|
267
|
-
|
|
268
|
-
|
|
303
|
+
if (newobj == null) {
|
|
304
|
+
if (!opts.noDropTable) {
|
|
305
|
+
plan.dropTable(oldobj);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
269
309
|
planAlterTable(plan, oldobj, newobj, opts);
|
|
310
|
+
}
|
|
270
311
|
}
|
|
271
312
|
else {
|
|
272
|
-
if (newobj == null)
|
|
273
|
-
|
|
274
|
-
|
|
313
|
+
if (newobj == null) {
|
|
314
|
+
if (!opts.noDropSqlObject) {
|
|
315
|
+
plan.dropSqlObject(oldobj);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else if (!testEqualSqlObjects(oldobj.createSql, newobj.createSql, opts)) {
|
|
275
319
|
plan.recreates.sqlObjects += 1;
|
|
276
|
-
|
|
320
|
+
if (!opts.noDropSqlObject) {
|
|
321
|
+
plan.dropSqlObject(oldobj);
|
|
322
|
+
}
|
|
277
323
|
plan.createSqlObject(newobj);
|
|
278
324
|
}
|
|
279
325
|
}
|
|
@@ -281,11 +327,11 @@ function createAlterDatabasePlan(oldDb, newDb, opts, db, driver) {
|
|
|
281
327
|
for (const newobj of newDb[objectTypeField] || []) {
|
|
282
328
|
const oldobj = (oldDb[objectTypeField] || []).find(x => x.pairingId == newobj.pairingId);
|
|
283
329
|
if (objectTypeField == 'tables') {
|
|
284
|
-
if (
|
|
330
|
+
if (oldobj == null)
|
|
285
331
|
plan.createTable(newobj);
|
|
286
332
|
}
|
|
287
333
|
else {
|
|
288
|
-
if (
|
|
334
|
+
if (oldobj == null)
|
|
289
335
|
plan.createSqlObject(newobj);
|
|
290
336
|
}
|
|
291
337
|
}
|
|
@@ -295,6 +341,9 @@ function createAlterDatabasePlan(oldDb, newDb, opts, db, driver) {
|
|
|
295
341
|
}
|
|
296
342
|
exports.createAlterDatabasePlan = createAlterDatabasePlan;
|
|
297
343
|
function getAlterTableScript(oldTable, newTable, opts, db, driver) {
|
|
344
|
+
if ((!oldTable && !newTable) || !driver) {
|
|
345
|
+
return { sql: '', recreates: [] };
|
|
346
|
+
}
|
|
298
347
|
const plan = createAlterTablePlan(oldTable, newTable, opts, db, driver);
|
|
299
348
|
const dmp = driver.createDumper();
|
|
300
349
|
if (!driver.dialect.disableExplicitTransaction)
|
|
@@ -319,6 +368,42 @@ function getAlterDatabaseScript(oldDb, newDb, opts, db, driver) {
|
|
|
319
368
|
return {
|
|
320
369
|
sql: dmp.s,
|
|
321
370
|
recreates: plan.recreates,
|
|
371
|
+
isEmpty: plan.operations.length == 0,
|
|
322
372
|
};
|
|
323
373
|
}
|
|
324
374
|
exports.getAlterDatabaseScript = getAlterDatabaseScript;
|
|
375
|
+
function matchPairedObjects(db1, db2, opts) {
|
|
376
|
+
if (!db1 || !db2)
|
|
377
|
+
return null;
|
|
378
|
+
const res = (0, cloneDeep_1.default)(db2);
|
|
379
|
+
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
|
|
380
|
+
for (const obj2 of res[objectTypeField] || []) {
|
|
381
|
+
const obj1 = db1[objectTypeField].find(x => testEqualFullNames(x, obj2, opts));
|
|
382
|
+
if (obj1) {
|
|
383
|
+
obj2.pairingId = obj1.pairingId;
|
|
384
|
+
if (objectTypeField == 'tables') {
|
|
385
|
+
for (const col2 of obj2.columns) {
|
|
386
|
+
const col1 = obj1.columns.find(x => testEqualNames(x.columnName, col2.columnName, opts));
|
|
387
|
+
if (col1)
|
|
388
|
+
col2.pairingId = col1.pairingId;
|
|
389
|
+
}
|
|
390
|
+
for (const fk2 of obj2.foreignKeys) {
|
|
391
|
+
const fk1 = obj1.foreignKeys.find(x => testEqualNames(x.refTableName, fk2.refTableName, opts) &&
|
|
392
|
+
(0, isEqual_1.default)(x.columns.map(y => (0, pick_1.default)(y, ['columnName', 'refColumnName'])), fk2.columns.map(y => (0, pick_1.default)(y, ['columnName', 'refColumnName']))));
|
|
393
|
+
if (fk1)
|
|
394
|
+
fk2.pairingId = fk1.pairingId;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return res;
|
|
401
|
+
}
|
|
402
|
+
exports.matchPairedObjects = matchPairedObjects;
|
|
403
|
+
exports.modelCompareDbDiffOptions = {
|
|
404
|
+
ignoreCase: true,
|
|
405
|
+
schemaMode: 'ignore',
|
|
406
|
+
ignoreConstraintNames: true,
|
|
407
|
+
ignoreForeignKeyActions: true,
|
|
408
|
+
ignoreDataTypes: true,
|
|
409
|
+
};
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -25,4 +25,6 @@ __exportStar(require("./settingsExtractors"), exports);
|
|
|
25
25
|
__exportStar(require("./filterName"), exports);
|
|
26
26
|
__exportStar(require("./diffTools"), exports);
|
|
27
27
|
__exportStar(require("./schemaEditorTools"), exports);
|
|
28
|
+
__exportStar(require("./yamlModelConv"), exports);
|
|
28
29
|
__exportStar(require("./stringTools"), exports);
|
|
30
|
+
__exportStar(require("./computeDiffRows"), exports);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TableInfo, DatabaseInfo } from 'dbgate-types';
|
|
2
|
+
export interface ColumnInfoYaml {
|
|
3
|
+
name: string;
|
|
4
|
+
type: string;
|
|
5
|
+
notNull?: boolean;
|
|
6
|
+
autoIncrement?: boolean;
|
|
7
|
+
references?: string;
|
|
8
|
+
primaryKey?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface DatabaseModelFile {
|
|
11
|
+
name: string;
|
|
12
|
+
text: string;
|
|
13
|
+
json: {};
|
|
14
|
+
}
|
|
15
|
+
export interface TableInfoYaml {
|
|
16
|
+
name: string;
|
|
17
|
+
columns: ColumnInfoYaml[];
|
|
18
|
+
primaryKey?: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface ForeignKeyInfoYaml {
|
|
21
|
+
deleteAction?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function tableInfoToYaml(table: TableInfo): TableInfoYaml;
|
|
24
|
+
export declare function tableInfoFromYaml(table: TableInfoYaml, allTables: TableInfoYaml[]): TableInfo;
|
|
25
|
+
export declare function databaseInfoFromYamlModel(files: DatabaseModelFile[]): DatabaseInfo;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.databaseInfoFromYamlModel = exports.tableInfoFromYaml = exports.tableInfoToYaml = void 0;
|
|
7
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
8
|
+
const compact_1 = __importDefault(require("lodash/compact"));
|
|
9
|
+
const DatabaseAnalyser_1 = require("./DatabaseAnalyser");
|
|
10
|
+
// function foreignKeyInfoToYaml() {}
|
|
11
|
+
function columnInfoToYaml(column, table) {
|
|
12
|
+
const res = {
|
|
13
|
+
name: column.columnName,
|
|
14
|
+
type: column.dataType,
|
|
15
|
+
};
|
|
16
|
+
if (column.autoIncrement)
|
|
17
|
+
res.autoIncrement = true;
|
|
18
|
+
if (column.notNull)
|
|
19
|
+
res.notNull = true;
|
|
20
|
+
const fk = table.foreignKeys &&
|
|
21
|
+
table.foreignKeys.find(fk => fk.columns.length == 1 && fk.columns[0].columnName == column.columnName);
|
|
22
|
+
if (fk &&
|
|
23
|
+
// fk.refSchemaName == table.schemaName &&
|
|
24
|
+
(!fk.deleteAction || fk.deleteAction == 'NO ACTION') &&
|
|
25
|
+
(!fk.updateAction || fk.updateAction == 'NO ACTION')) {
|
|
26
|
+
res.references = fk.refTableName;
|
|
27
|
+
fk['_dumped'] = true;
|
|
28
|
+
}
|
|
29
|
+
// if (table.primaryKey && table.primaryKey.columns.length == 1) {
|
|
30
|
+
// table.primaryKey['_dumped'] = true;
|
|
31
|
+
// res.primaryKey = true;
|
|
32
|
+
// }
|
|
33
|
+
return res;
|
|
34
|
+
}
|
|
35
|
+
function columnInfoFromYaml(column, table) {
|
|
36
|
+
const res = {
|
|
37
|
+
pureName: table.name,
|
|
38
|
+
columnName: column.name,
|
|
39
|
+
dataType: column.type,
|
|
40
|
+
autoIncrement: column.autoIncrement,
|
|
41
|
+
notNull: column.notNull || (table.primaryKey && table.primaryKey.includes(column.name)),
|
|
42
|
+
};
|
|
43
|
+
return res;
|
|
44
|
+
}
|
|
45
|
+
function tableInfoToYaml(table) {
|
|
46
|
+
const tableCopy = (0, cloneDeep_1.default)(table);
|
|
47
|
+
const res = {
|
|
48
|
+
name: tableCopy.pureName,
|
|
49
|
+
// schema: tableCopy.schemaName,
|
|
50
|
+
columns: tableCopy.columns.map(c => columnInfoToYaml(c, tableCopy)),
|
|
51
|
+
};
|
|
52
|
+
if (tableCopy.primaryKey && !tableCopy.primaryKey['_dumped']) {
|
|
53
|
+
res.primaryKey = tableCopy.primaryKey.columns.map(x => x.columnName);
|
|
54
|
+
}
|
|
55
|
+
// const foreignKeys = (tableCopy.foreignKeys || []).filter(x => !x['_dumped']).map(foreignKeyInfoToYaml);
|
|
56
|
+
return res;
|
|
57
|
+
}
|
|
58
|
+
exports.tableInfoToYaml = tableInfoToYaml;
|
|
59
|
+
function convertForeignKeyFromYaml(col, table, allTables) {
|
|
60
|
+
const refTable = allTables.find(x => x.name == col.references);
|
|
61
|
+
if (!refTable || !refTable.primaryKey)
|
|
62
|
+
return null;
|
|
63
|
+
return {
|
|
64
|
+
constraintType: 'foreignKey',
|
|
65
|
+
pureName: table.name,
|
|
66
|
+
refTableName: col.references,
|
|
67
|
+
columns: [
|
|
68
|
+
{
|
|
69
|
+
columnName: col.name,
|
|
70
|
+
refColumnName: refTable.primaryKey[0],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function tableInfoFromYaml(table, allTables) {
|
|
76
|
+
const res = {
|
|
77
|
+
pureName: table.name,
|
|
78
|
+
columns: table.columns.map(c => columnInfoFromYaml(c, table)),
|
|
79
|
+
foreignKeys: (0, compact_1.default)(table.columns.filter(x => x.references).map(col => convertForeignKeyFromYaml(col, table, allTables))),
|
|
80
|
+
};
|
|
81
|
+
if (table.primaryKey) {
|
|
82
|
+
res.primaryKey = {
|
|
83
|
+
pureName: table.name,
|
|
84
|
+
constraintType: 'primaryKey',
|
|
85
|
+
columns: table.primaryKey.map(columnName => ({ columnName })),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return res;
|
|
89
|
+
}
|
|
90
|
+
exports.tableInfoFromYaml = tableInfoFromYaml;
|
|
91
|
+
function databaseInfoFromYamlModel(files) {
|
|
92
|
+
const model = DatabaseAnalyser_1.DatabaseAnalyser.createEmptyStructure();
|
|
93
|
+
const tablesYaml = [];
|
|
94
|
+
for (const file of files) {
|
|
95
|
+
if (file.name.endsWith('.table.yaml') || file.name.endsWith('.sql')) {
|
|
96
|
+
if (file.name.endsWith('.table.yaml')) {
|
|
97
|
+
tablesYaml.push(file.json);
|
|
98
|
+
}
|
|
99
|
+
if (file.name.endsWith('.view.sql')) {
|
|
100
|
+
model.views.push({
|
|
101
|
+
pureName: file.name.slice(0, -'.view.sql'.length),
|
|
102
|
+
createSql: file.text,
|
|
103
|
+
columns: [],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (file.name.endsWith('.matview.sql')) {
|
|
107
|
+
model.matviews.push({
|
|
108
|
+
pureName: file.name.slice(0, -'.matview.sql'.length),
|
|
109
|
+
createSql: file.text,
|
|
110
|
+
columns: [],
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (file.name.endsWith('.proc.sql')) {
|
|
114
|
+
model.procedures.push({
|
|
115
|
+
pureName: file.name.slice(0, -'.proc.sql'.length),
|
|
116
|
+
createSql: file.text,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (file.name.endsWith('.func.sql')) {
|
|
120
|
+
model.functions.push({
|
|
121
|
+
pureName: file.name.slice(0, -'.func.sql'.length),
|
|
122
|
+
createSql: file.text,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (file.name.endsWith('.trigger.sql')) {
|
|
126
|
+
model.triggers.push({
|
|
127
|
+
pureName: file.name.slice(0, -'.trigger.sql'.length),
|
|
128
|
+
createSql: file.text,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
model.tables = tablesYaml.map(table => tableInfoFromYaml(table, tablesYaml));
|
|
134
|
+
return model;
|
|
135
|
+
}
|
|
136
|
+
exports.databaseInfoFromYamlModel = databaseInfoFromYamlModel;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.
|
|
2
|
+
"version": "4.4.1",
|
|
3
3
|
"name": "dbgate-tools",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"typings": "lib/index.d.ts",
|
|
@@ -25,14 +25,14 @@
|
|
|
25
25
|
],
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^13.7.0",
|
|
28
|
-
"dbgate-types": "^4.
|
|
28
|
+
"dbgate-types": "^4.4.1",
|
|
29
29
|
"jest": "^24.9.0",
|
|
30
30
|
"ts-jest": "^25.2.1",
|
|
31
31
|
"typescript": "^4.4.3"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"lodash": "^4.17.21",
|
|
35
|
-
"dbgate-query-splitter": "^4.
|
|
35
|
+
"dbgate-query-splitter": "^4.4.1",
|
|
36
36
|
"uuid": "^3.4.0"
|
|
37
37
|
}
|
|
38
38
|
}
|