dbgate-tools 5.5.6 → 5.5.7-alpha.25
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/DatabaseAnalyser.js +1 -1
- package/lib/ScriptWriter.js +1 -1
- package/lib/SqlDumper.d.ts +1 -0
- package/lib/SqlDumper.js +7 -2
- package/lib/alterPlan.d.ts +8 -1
- package/lib/alterPlan.js +32 -12
- package/lib/computeDiffRows.d.ts +13 -0
- package/lib/computeDiffRows.js +30 -1
- package/lib/database-info-alter-processor.d.ts +1 -0
- package/lib/database-info-alter-processor.js +4 -0
- package/lib/diffTools.d.ts +6 -1
- package/lib/diffTools.js +231 -39
- package/lib/driverBase.js +6 -0
- package/lib/getConnectionLabel.js +3 -0
- package/lib/stringTools.d.ts +2 -0
- package/lib/stringTools.js +36 -1
- package/lib/structureTools.d.ts +16 -0
- package/lib/structureTools.js +89 -1
- package/lib/yamlModelConv.d.ts +8 -0
- package/lib/yamlModelConv.js +32 -1
- package/package.json +4 -3
package/lib/DatabaseAnalyser.js
CHANGED
|
@@ -75,7 +75,7 @@ class DatabaseAnalyser {
|
|
|
75
75
|
}
|
|
76
76
|
fullAnalysis() {
|
|
77
77
|
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
-
logger.
|
|
78
|
+
logger.debug(`Performing full analysis, DB=${(0, schemaInfoTools_1.dbNameLogCategory)(this.dbhan.database)}, engine=${this.driver.engine}`);
|
|
79
79
|
const res = this.addEngineField(yield this._runAnalysis());
|
|
80
80
|
// console.log('FULL ANALYSIS', res);
|
|
81
81
|
return res;
|
package/lib/ScriptWriter.js
CHANGED
|
@@ -52,7 +52,7 @@ class ScriptWriter {
|
|
|
52
52
|
this._put(`await dbgateApi.importDatabase(${JSON.stringify(options)});`);
|
|
53
53
|
}
|
|
54
54
|
dataDuplicator(options) {
|
|
55
|
-
this._put(`await dbgateApi.dataDuplicator(${JSON.stringify(options)});`);
|
|
55
|
+
this._put(`await dbgateApi.dataDuplicator(${JSON.stringify(options, null, 2)});`);
|
|
56
56
|
}
|
|
57
57
|
comment(s) {
|
|
58
58
|
this._put(`// ${s}`);
|
package/lib/SqlDumper.d.ts
CHANGED
|
@@ -102,6 +102,7 @@ export declare class SqlDumper implements AlterProcessor {
|
|
|
102
102
|
}): void;
|
|
103
103
|
changeTableSchema(obj: TableInfo, schema: string): void;
|
|
104
104
|
renameTable(obj: TableInfo, newname: string): void;
|
|
105
|
+
renameSqlObject(obj: SqlObjectInfo, newname: string): void;
|
|
105
106
|
beginTransaction(): void;
|
|
106
107
|
commitTransaction(): void;
|
|
107
108
|
rollbackTransaction(): void;
|
package/lib/SqlDumper.js
CHANGED
|
@@ -299,7 +299,7 @@ class SqlDumper {
|
|
|
299
299
|
createTablePrimaryKeyCore(table) {
|
|
300
300
|
if (table.primaryKey) {
|
|
301
301
|
this.put(',&n');
|
|
302
|
-
if (table.primaryKey.constraintName) {
|
|
302
|
+
if (table.primaryKey.constraintName && !this.dialect.anonymousPrimaryKey) {
|
|
303
303
|
this.put('^constraint %i', table.primaryKey.constraintName);
|
|
304
304
|
}
|
|
305
305
|
this.put(' ^primary ^key (%,i)', table.primaryKey.columns.map(x => x.columnName));
|
|
@@ -473,6 +473,9 @@ class SqlDumper {
|
|
|
473
473
|
this.put('%i %k', col.columnName, col.isDescending == true ? 'DESC' : 'ASC');
|
|
474
474
|
});
|
|
475
475
|
this.put('&<&n)');
|
|
476
|
+
if (ix.filterDefinition && this.dialect.filteredIndexes) {
|
|
477
|
+
this.put('&n^where %s', ix.filterDefinition);
|
|
478
|
+
}
|
|
476
479
|
this.endCommand();
|
|
477
480
|
}
|
|
478
481
|
dropUnique(uq) {
|
|
@@ -529,6 +532,7 @@ class SqlDumper {
|
|
|
529
532
|
}
|
|
530
533
|
changeTableSchema(obj, schema) { }
|
|
531
534
|
renameTable(obj, newname) { }
|
|
535
|
+
renameSqlObject(obj, newname) { }
|
|
532
536
|
beginTransaction() {
|
|
533
537
|
this.putCmd('^begin ^transaction');
|
|
534
538
|
}
|
|
@@ -597,7 +601,8 @@ class SqlDumper {
|
|
|
597
601
|
}
|
|
598
602
|
}
|
|
599
603
|
createSqlObject(obj) {
|
|
600
|
-
this.
|
|
604
|
+
this.putRaw(obj.createSql);
|
|
605
|
+
this.endCommand();
|
|
601
606
|
}
|
|
602
607
|
getSqlObjectSqlName(ojectTypeField) {
|
|
603
608
|
switch (ojectTypeField) {
|
package/lib/alterPlan.d.ts
CHANGED
|
@@ -21,6 +21,11 @@ interface AlterOperation_RenameTable {
|
|
|
21
21
|
object: TableInfo;
|
|
22
22
|
newName: string;
|
|
23
23
|
}
|
|
24
|
+
interface AlterOperation_RenameSqlObject {
|
|
25
|
+
operationType: 'renameSqlObject';
|
|
26
|
+
object: SqlObjectInfo;
|
|
27
|
+
newName: string;
|
|
28
|
+
}
|
|
24
29
|
interface AlterOperation_CreateColumn {
|
|
25
30
|
operationType: 'createColumn';
|
|
26
31
|
newObject: ColumnInfo;
|
|
@@ -51,6 +56,7 @@ interface AlterOperation_ChangeConstraint {
|
|
|
51
56
|
interface AlterOperation_DropConstraint {
|
|
52
57
|
operationType: 'dropConstraint';
|
|
53
58
|
oldObject: ConstraintInfo;
|
|
59
|
+
isRecreate?: boolean;
|
|
54
60
|
}
|
|
55
61
|
interface AlterOperation_RenameConstraint {
|
|
56
62
|
operationType: 'renameConstraint';
|
|
@@ -77,7 +83,7 @@ interface AlterOperation_SetTableOption {
|
|
|
77
83
|
optionName: string;
|
|
78
84
|
optionValue: string;
|
|
79
85
|
}
|
|
80
|
-
type AlterOperation = AlterOperation_CreateColumn | AlterOperation_ChangeColumn | AlterOperation_DropColumn | AlterOperation_CreateConstraint | AlterOperation_ChangeConstraint | AlterOperation_DropConstraint | AlterOperation_CreateTable | AlterOperation_DropTable | AlterOperation_RenameTable | AlterOperation_RenameColumn | AlterOperation_RenameConstraint | AlterOperation_CreateSqlObject | AlterOperation_DropSqlObject | AlterOperation_RecreateTable | AlterOperation_FillPreloadedRows | AlterOperation_SetTableOption;
|
|
86
|
+
export type AlterOperation = AlterOperation_CreateColumn | AlterOperation_ChangeColumn | AlterOperation_DropColumn | AlterOperation_CreateConstraint | AlterOperation_ChangeConstraint | AlterOperation_DropConstraint | AlterOperation_CreateTable | AlterOperation_DropTable | AlterOperation_RenameTable | AlterOperation_RenameColumn | AlterOperation_RenameConstraint | AlterOperation_CreateSqlObject | AlterOperation_DropSqlObject | AlterOperation_RecreateTable | AlterOperation_FillPreloadedRows | AlterOperation_SetTableOption | AlterOperation_RenameSqlObject;
|
|
81
87
|
export declare class AlterPlan {
|
|
82
88
|
wholeOldDb: DatabaseInfo;
|
|
83
89
|
wholeNewDb: DatabaseInfo;
|
|
@@ -101,6 +107,7 @@ export declare class AlterPlan {
|
|
|
101
107
|
changeConstraint(oldConstraint: ConstraintInfo, newConstraint: ConstraintInfo): void;
|
|
102
108
|
dropConstraint(constraint: ConstraintInfo): void;
|
|
103
109
|
renameTable(table: TableInfo, newName: string): void;
|
|
110
|
+
renameSqlObject(table: TableInfo, newName: string): void;
|
|
104
111
|
renameColumn(column: ColumnInfo, newName: string): void;
|
|
105
112
|
renameConstraint(constraint: ConstraintInfo, newName: string): void;
|
|
106
113
|
recreateTable(table: TableInfo, operations: AlterOperation[]): void;
|
package/lib/alterPlan.js
CHANGED
|
@@ -90,6 +90,13 @@ class AlterPlan {
|
|
|
90
90
|
newName,
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
|
+
renameSqlObject(table, newName) {
|
|
94
|
+
this.operations.push({
|
|
95
|
+
operationType: 'renameSqlObject',
|
|
96
|
+
object: table,
|
|
97
|
+
newName,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
93
100
|
renameColumn(column, newName) {
|
|
94
101
|
this.operations.push({
|
|
95
102
|
operationType: 'renameColumn',
|
|
@@ -177,14 +184,15 @@ class AlterPlan {
|
|
|
177
184
|
]) {
|
|
178
185
|
if (op.operationType == testedOperationType) {
|
|
179
186
|
const constraints = this._getDependendColumnConstraints(testedObject, testedDependencies);
|
|
180
|
-
if (constraints.length > 0 && this.opts.noDropConstraint) {
|
|
181
|
-
|
|
182
|
-
}
|
|
187
|
+
// if (constraints.length > 0 && this.opts.noDropConstraint) {
|
|
188
|
+
// return [];
|
|
189
|
+
// }
|
|
183
190
|
const res = [
|
|
184
191
|
...constraints.map(oldObject => {
|
|
185
192
|
const opRes = {
|
|
186
193
|
operationType: 'dropConstraint',
|
|
187
194
|
oldObject,
|
|
195
|
+
isRecreate: true,
|
|
188
196
|
};
|
|
189
197
|
return opRes;
|
|
190
198
|
}),
|
|
@@ -218,14 +226,15 @@ class AlterPlan {
|
|
|
218
226
|
];
|
|
219
227
|
}
|
|
220
228
|
if (op.operationType == 'changeConstraint') {
|
|
221
|
-
if (this.opts.noDropConstraint) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
229
|
+
// if (this.opts.noDropConstraint) {
|
|
230
|
+
// // skip constraint recreate
|
|
231
|
+
// return [];
|
|
232
|
+
// }
|
|
225
233
|
this.recreates.constraints += 1;
|
|
226
234
|
const opDrop = {
|
|
227
235
|
operationType: 'dropConstraint',
|
|
228
236
|
oldObject: op.oldObject,
|
|
237
|
+
isRecreate: true,
|
|
229
238
|
};
|
|
230
239
|
const opCreate = {
|
|
231
240
|
operationType: 'createConstraint',
|
|
@@ -290,7 +299,7 @@ class AlterPlan {
|
|
|
290
299
|
}
|
|
291
300
|
// console.log('*****************RECREATED NEEDED', op, operationType, isAllowed);
|
|
292
301
|
// console.log(this.dialect);
|
|
293
|
-
if (this.opts.noDropTable) {
|
|
302
|
+
if (this.opts.noDropTable && !this.opts.allowTableRecreateWhenNoDrop) {
|
|
294
303
|
// skip this operation, as it cannot be achieved
|
|
295
304
|
return [];
|
|
296
305
|
}
|
|
@@ -341,7 +350,9 @@ class AlterPlan {
|
|
|
341
350
|
return this.operations;
|
|
342
351
|
}
|
|
343
352
|
const fks = [];
|
|
344
|
-
const res = this.operations
|
|
353
|
+
const res = this.operations
|
|
354
|
+
.filter(op => op.operationType != 'createConstraint')
|
|
355
|
+
.map(op => {
|
|
345
356
|
if (op.operationType == 'createTable') {
|
|
346
357
|
fks.push(...(op.newObject.foreignKeys || []));
|
|
347
358
|
return Object.assign(Object.assign({}, op), { newObject: Object.assign(Object.assign({}, op.newObject), { foreignKeys: [] }) });
|
|
@@ -350,6 +361,7 @@ class AlterPlan {
|
|
|
350
361
|
});
|
|
351
362
|
return [
|
|
352
363
|
...res,
|
|
364
|
+
...this.operations.filter(op => op.operationType == 'createConstraint'),
|
|
353
365
|
...fks.map(fk => ({
|
|
354
366
|
operationType: 'createConstraint',
|
|
355
367
|
newObject: fk,
|
|
@@ -364,10 +376,15 @@ class AlterPlan {
|
|
|
364
376
|
return false;
|
|
365
377
|
if (this.opts.noDropTable && op.operationType == 'recreateTable')
|
|
366
378
|
return false;
|
|
367
|
-
if (this.opts.noDropConstraint && op.operationType == 'dropConstraint')
|
|
368
|
-
return false;
|
|
369
|
-
if (this.opts.noDropSqlObject && op.operationType == 'dropSqlObject')
|
|
379
|
+
if (this.opts.noDropConstraint && op.operationType == 'dropConstraint' && !op.isRecreate)
|
|
370
380
|
return false;
|
|
381
|
+
// if (
|
|
382
|
+
// this.opts.noDropSqlObject &&
|
|
383
|
+
// op.operationType == 'dropSqlObject' &&
|
|
384
|
+
// // allow to drop previously deleted SQL objects
|
|
385
|
+
// !hasDeletedPrefix(op.oldObject.pureName, this.opts, this.opts.deletedSqlObjectPrefix)
|
|
386
|
+
// )
|
|
387
|
+
// return false;
|
|
371
388
|
return true;
|
|
372
389
|
});
|
|
373
390
|
}
|
|
@@ -418,6 +435,9 @@ function runAlterOperation(op, processor) {
|
|
|
418
435
|
case 'renameTable':
|
|
419
436
|
processor.renameTable(op.object, op.newName);
|
|
420
437
|
break;
|
|
438
|
+
case 'renameSqlObject':
|
|
439
|
+
processor.renameSqlObject(op.object, op.newName);
|
|
440
|
+
break;
|
|
421
441
|
case 'renameConstraint':
|
|
422
442
|
processor.renameConstraint(op.object, op.newName);
|
|
423
443
|
break;
|
package/lib/computeDiffRows.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DbDiffOptions, testEqualTables, testEqualSqlObjects } from './diffTools';
|
|
2
2
|
import type { DatabaseInfo, EngineDriver, SqlObjectInfo, TableInfo } from 'dbgate-types';
|
|
3
|
+
import { AlterOperation } from './alterPlan';
|
|
3
4
|
export declare function computeDiffRowsCore(sourceList: any, targetList: any, testEqual: any): any[];
|
|
4
5
|
export declare const DbDiffCompareDefs: {
|
|
5
6
|
tables: {
|
|
@@ -35,4 +36,16 @@ export declare const DbDiffCompareDefs: {
|
|
|
35
36
|
};
|
|
36
37
|
export declare function computeDbDiffRows(sourceDb: DatabaseInfo, targetDb: DatabaseInfo, opts: DbDiffOptions, driver: EngineDriver): any[];
|
|
37
38
|
export declare function computeTableDiffColumns(sourceTable: TableInfo, targetTable: TableInfo, opts: DbDiffOptions, driver: EngineDriver): any[];
|
|
39
|
+
export interface DiffOperationItemDisplay {
|
|
40
|
+
operationType: string;
|
|
41
|
+
name: string;
|
|
42
|
+
sqlScript: string;
|
|
43
|
+
identifier?: string;
|
|
44
|
+
}
|
|
45
|
+
export declare function getOperationDisplay(operation: AlterOperation, driver: EngineDriver): DiffOperationItemDisplay;
|
|
46
|
+
export declare function computeObjectDiffOperations(sourceObject: {
|
|
47
|
+
objectTypeField: string;
|
|
48
|
+
}, targetObject: {
|
|
49
|
+
objectTypeField: string;
|
|
50
|
+
}, sourceDb: DatabaseInfo, targetDb: DatabaseInfo, opts: DbDiffOptions, driver: EngineDriver): DiffOperationItemDisplay[];
|
|
38
51
|
export declare function getCreateObjectScript(obj: TableInfo | SqlObjectInfo, driver: EngineDriver): string;
|
package/lib/computeDiffRows.js
CHANGED
|
@@ -3,9 +3,11 @@ 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.getCreateObjectScript = exports.computeTableDiffColumns = exports.computeDbDiffRows = exports.DbDiffCompareDefs = exports.computeDiffRowsCore = void 0;
|
|
6
|
+
exports.getCreateObjectScript = exports.computeObjectDiffOperations = exports.getOperationDisplay = exports.computeTableDiffColumns = exports.computeDbDiffRows = exports.DbDiffCompareDefs = exports.computeDiffRowsCore = void 0;
|
|
7
7
|
const diffTools_1 = require("./diffTools");
|
|
8
8
|
const lodash_1 = __importDefault(require("lodash"));
|
|
9
|
+
const structureTools_1 = require("./structureTools");
|
|
10
|
+
const alterPlan_1 = require("./alterPlan");
|
|
9
11
|
function computeDiffRowsCore(sourceList, targetList, testEqual) {
|
|
10
12
|
const res = [];
|
|
11
13
|
for (const obj of sourceList) {
|
|
@@ -95,6 +97,33 @@ function computeTableDiffColumns(sourceTable, targetTable, opts, driver) {
|
|
|
95
97
|
});
|
|
96
98
|
}
|
|
97
99
|
exports.computeTableDiffColumns = computeTableDiffColumns;
|
|
100
|
+
function getOperationDisplay(operation, driver) {
|
|
101
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
102
|
+
const op = operation;
|
|
103
|
+
const name = (_u = (_s = (_q = (_o = (_l = (_j = (_g = (_e = (_c = (_a = op === null || op === void 0 ? void 0 : op.newName) !== null && _a !== void 0 ? _a : (_b = op === null || op === void 0 ? void 0 : op.newObject) === null || _b === void 0 ? void 0 : _b.columnName) !== null && _c !== void 0 ? _c : (_d = op === null || op === void 0 ? void 0 : op.newObject) === null || _d === void 0 ? void 0 : _d.constraintName) !== null && _e !== void 0 ? _e : (_f = op === null || op === void 0 ? void 0 : op.newObject) === null || _f === void 0 ? void 0 : _f.pureName) !== null && _g !== void 0 ? _g : (_h = op === null || op === void 0 ? void 0 : op.oldObject) === null || _h === void 0 ? void 0 : _h.columnName) !== null && _j !== void 0 ? _j : (_k = op === null || op === void 0 ? void 0 : op.oldObject) === null || _k === void 0 ? void 0 : _k.constraintName) !== null && _l !== void 0 ? _l : (_m = op === null || op === void 0 ? void 0 : op.oldObject) === null || _m === void 0 ? void 0 : _m.pureName) !== null && _o !== void 0 ? _o : (_p = op === null || op === void 0 ? void 0 : op.table) === null || _p === void 0 ? void 0 : _p.pureName) !== null && _q !== void 0 ? _q : (_r = op === null || op === void 0 ? void 0 : op.object) === null || _r === void 0 ? void 0 : _r.columnName) !== null && _s !== void 0 ? _s : (_t = op === null || op === void 0 ? void 0 : op.object) === null || _t === void 0 ? void 0 : _t.constraintName) !== null && _u !== void 0 ? _u : (_v = op === null || op === void 0 ? void 0 : op.object) === null || _v === void 0 ? void 0 : _v.pureName;
|
|
104
|
+
const dmp = driver.createDumper();
|
|
105
|
+
(0, alterPlan_1.runAlterOperation)(operation, dmp);
|
|
106
|
+
return {
|
|
107
|
+
operationType: operation.operationType,
|
|
108
|
+
name,
|
|
109
|
+
sqlScript: dmp.s,
|
|
110
|
+
identifier: dmp.s,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
exports.getOperationDisplay = getOperationDisplay;
|
|
114
|
+
function computeObjectDiffOperations(sourceObject, targetObject, sourceDb, targetDb, opts, driver) {
|
|
115
|
+
if (!driver)
|
|
116
|
+
return [];
|
|
117
|
+
const srcdb = sourceObject
|
|
118
|
+
? (0, structureTools_1.extendDatabaseInfo)({ [sourceObject.objectTypeField]: [sourceObject] })
|
|
119
|
+
: (0, structureTools_1.extendDatabaseInfo)({});
|
|
120
|
+
const dstdb = targetObject
|
|
121
|
+
? (0, structureTools_1.extendDatabaseInfo)({ [targetObject.objectTypeField]: [targetObject] })
|
|
122
|
+
: (0, structureTools_1.extendDatabaseInfo)({});
|
|
123
|
+
const plan = (0, diffTools_1.createAlterDatabasePlan)(dstdb, srcdb, opts, targetDb, sourceDb, driver);
|
|
124
|
+
return plan.operations.map(item => getOperationDisplay(item, driver));
|
|
125
|
+
}
|
|
126
|
+
exports.computeObjectDiffOperations = computeObjectDiffOperations;
|
|
98
127
|
function getCreateObjectScript(obj, driver) {
|
|
99
128
|
if (!obj || !driver)
|
|
100
129
|
return '';
|
|
@@ -13,6 +13,7 @@ export declare class DatabaseInfoAlterProcessor {
|
|
|
13
13
|
changeConstraint(oldConstraint: ConstraintInfo, newConstraint: ConstraintInfo): void;
|
|
14
14
|
dropConstraint(constraint: ConstraintInfo): void;
|
|
15
15
|
renameTable(table: TableInfo, newName: string): void;
|
|
16
|
+
renameSqlObject(obj: SqlObjectInfo, newName: string): void;
|
|
16
17
|
renameColumn(column: ColumnInfo, newName: string): void;
|
|
17
18
|
renameConstraint(constraint: ConstraintInfo, newName: string): void;
|
|
18
19
|
recreateTable(oldTable: TableInfo, newTable: TableInfo): void;
|
|
@@ -91,6 +91,10 @@ class DatabaseInfoAlterProcessor {
|
|
|
91
91
|
renameTable(table, newName) {
|
|
92
92
|
this.db.tables.find(x => x.pureName == table.pureName && x.schemaName == table.schemaName).pureName = newName;
|
|
93
93
|
}
|
|
94
|
+
renameSqlObject(obj, newName) {
|
|
95
|
+
this.db[obj.objectTypeField].find(x => x.pureName == obj.pureName && x.schemaName == obj.schemaName).pureName =
|
|
96
|
+
newName;
|
|
97
|
+
}
|
|
94
98
|
renameColumn(column, newName) {
|
|
95
99
|
const table = this.db.tables.find(x => x.pureName == column.pureName && x.schemaName == column.schemaName);
|
|
96
100
|
table.columns.find(x => x.columnName == column.columnName).columnName = newName;
|
package/lib/diffTools.d.ts
CHANGED
|
@@ -8,9 +8,13 @@ export interface DbDiffOptions {
|
|
|
8
8
|
rightImplicitSchema?: string;
|
|
9
9
|
ignoreConstraintNames?: boolean;
|
|
10
10
|
noDropTable?: boolean;
|
|
11
|
+
allowTableRecreateWhenNoDrop?: boolean;
|
|
12
|
+
deletedTablePrefix?: string;
|
|
11
13
|
noDropColumn?: boolean;
|
|
14
|
+
deletedColumnPrefix?: string;
|
|
12
15
|
noDropConstraint?: boolean;
|
|
13
16
|
noDropSqlObject?: boolean;
|
|
17
|
+
deletedSqlObjectPrefix?: string;
|
|
14
18
|
noRenameTable?: boolean;
|
|
15
19
|
noRenameColumn?: boolean;
|
|
16
20
|
ignoreForeignKeyActions?: boolean;
|
|
@@ -19,6 +23,7 @@ export interface DbDiffOptions {
|
|
|
19
23
|
export declare function generateTablePairingId(table: TableInfo): TableInfo;
|
|
20
24
|
export declare function removeTablePairingId(table: TableInfo): TableInfo;
|
|
21
25
|
export declare function generateDbPairingId(db: DatabaseInfo): DatabaseInfo;
|
|
26
|
+
export declare function hasDeletedPrefix(name: string, opts: DbDiffOptions, deletedPrefix?: string): boolean;
|
|
22
27
|
export declare function testEqualColumns(a: ColumnInfo, b: ColumnInfo, checkName: boolean, checkDefault: boolean, opts?: DbDiffOptions): boolean;
|
|
23
28
|
export declare function testEqualTypes(a: ColumnInfo, b: ColumnInfo, opts?: DbDiffOptions): boolean;
|
|
24
29
|
export declare function testEqualTables(a: TableInfo, b: TableInfo, opts: DbDiffOptions, wholeOldDb: DatabaseInfo, wholeNewDb: DatabaseInfo, driver: EngineDriver): boolean;
|
|
@@ -36,7 +41,7 @@ export declare function getAlterTableScript(oldTable: TableInfo, newTable: Table
|
|
|
36
41
|
sqlObjects: number;
|
|
37
42
|
};
|
|
38
43
|
};
|
|
39
|
-
export declare function getAlterDatabaseScript(oldDb: DatabaseInfo, newDb: DatabaseInfo, opts: DbDiffOptions, wholeOldDb: DatabaseInfo, wholeNewDb: DatabaseInfo, driver: EngineDriver): {
|
|
44
|
+
export declare function getAlterDatabaseScript(oldDb: DatabaseInfo, newDb: DatabaseInfo, opts: DbDiffOptions, wholeOldDb: DatabaseInfo, wholeNewDb: DatabaseInfo, driver: EngineDriver, transformPlan?: (plan: AlterPlan) => void): {
|
|
40
45
|
sql: string;
|
|
41
46
|
recreates: {
|
|
42
47
|
tables: number;
|
package/lib/diffTools.js
CHANGED
|
@@ -3,14 +3,16 @@ 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.modelCompareDbDiffOptions = exports.matchPairedObjects = exports.getAlterDatabaseScript = exports.getAlterTableScript = exports.createAlterDatabasePlan = exports.createAlterTablePlan = exports.testEqualSqlObjects = exports.testEqualTables = exports.testEqualTypes = exports.testEqualColumns = exports.generateDbPairingId = exports.removeTablePairingId = 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.hasDeletedPrefix = exports.generateDbPairingId = exports.removeTablePairingId = exports.generateTablePairingId = void 0;
|
|
7
7
|
const v1_1 = __importDefault(require("uuid/v1"));
|
|
8
8
|
const alterPlan_1 = require("./alterPlan");
|
|
9
|
-
const
|
|
10
|
-
const omit_1 = __importDefault(require("lodash/omit"));
|
|
9
|
+
const toposort_1 = __importDefault(require("toposort"));
|
|
11
10
|
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
12
11
|
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
|
13
12
|
const pick_1 = __importDefault(require("lodash/pick"));
|
|
13
|
+
const compact_1 = __importDefault(require("lodash/compact"));
|
|
14
|
+
const isString_1 = __importDefault(require("lodash/isString"));
|
|
15
|
+
const structureTools_1 = require("./structureTools");
|
|
14
16
|
function generateTablePairingId(table) {
|
|
15
17
|
var _a, _b, _c, _d, _e;
|
|
16
18
|
if (!table)
|
|
@@ -28,6 +30,12 @@ function removeTablePairingId(table) {
|
|
|
28
30
|
return Object.assign(Object.assign({}, table), { columns: (_a = table.columns) === null || _a === void 0 ? void 0 : _a.map(col => (Object.assign(Object.assign({}, col), { pairingId: undefined }))), foreignKeys: (_b = table.foreignKeys) === null || _b === void 0 ? void 0 : _b.map(cnt => (Object.assign(Object.assign({}, cnt), { pairingId: undefined }))), checks: (_c = table.checks) === null || _c === void 0 ? void 0 : _c.map(cnt => (Object.assign(Object.assign({}, cnt), { pairingId: undefined }))), indexes: (_d = table.indexes) === null || _d === void 0 ? void 0 : _d.map(cnt => (Object.assign(Object.assign({}, cnt), { pairingId: undefined }))), uniques: (_e = table.uniques) === null || _e === void 0 ? void 0 : _e.map(cnt => (Object.assign(Object.assign({}, cnt), { pairingId: undefined }))), pairingId: undefined });
|
|
29
31
|
}
|
|
30
32
|
exports.removeTablePairingId = removeTablePairingId;
|
|
33
|
+
function simplifySqlExpression(sql) {
|
|
34
|
+
return (sql || '')
|
|
35
|
+
.replace(/[\s\(\)\[\]\"]/g, '')
|
|
36
|
+
.toLowerCase()
|
|
37
|
+
.trim();
|
|
38
|
+
}
|
|
31
39
|
function generateObjectPairingId(obj) {
|
|
32
40
|
if (obj.objectTypeField)
|
|
33
41
|
return Object.assign(Object.assign({}, obj), { pairingId: obj.pairingId || (0, v1_1.default)() });
|
|
@@ -42,7 +50,36 @@ function generateDbPairingId(db) {
|
|
|
42
50
|
tables: (_a = db.tables) === null || _a === void 0 ? void 0 : _a.map(generateTablePairingId), views: (_b = db.views) === null || _b === void 0 ? void 0 : _b.map(generateObjectPairingId), procedures: (_c = db.procedures) === null || _c === void 0 ? void 0 : _c.map(generateObjectPairingId), functions: (_d = db.functions) === null || _d === void 0 ? void 0 : _d.map(generateObjectPairingId), triggers: (_e = db.triggers) === null || _e === void 0 ? void 0 : _e.map(generateObjectPairingId), matviews: (_f = db.matviews) === null || _f === void 0 ? void 0 : _f.map(generateObjectPairingId) });
|
|
43
51
|
}
|
|
44
52
|
exports.generateDbPairingId = generateDbPairingId;
|
|
45
|
-
function
|
|
53
|
+
function getNameWithoutDeletedPrefix(name, opts, deletedPrefix) {
|
|
54
|
+
if (deletedPrefix) {
|
|
55
|
+
if (opts.ignoreCase) {
|
|
56
|
+
if ((name || '').toLowerCase().startsWith(deletedPrefix.toLowerCase())) {
|
|
57
|
+
return name.slice(deletedPrefix.length);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if ((name || '').startsWith(deletedPrefix)) {
|
|
62
|
+
return name.slice(deletedPrefix.length);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return name;
|
|
67
|
+
}
|
|
68
|
+
function hasDeletedPrefix(name, opts, deletedPrefix) {
|
|
69
|
+
if (deletedPrefix) {
|
|
70
|
+
if (opts.ignoreCase) {
|
|
71
|
+
return (name || '').toLowerCase().startsWith(deletedPrefix.toLowerCase());
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
return (name || '').startsWith(deletedPrefix);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
exports.hasDeletedPrefix = hasDeletedPrefix;
|
|
80
|
+
function testEqualNames(a, b, opts, deletedPrefix) {
|
|
81
|
+
a = getNameWithoutDeletedPrefix(a, opts, deletedPrefix);
|
|
82
|
+
b = getNameWithoutDeletedPrefix(b, opts, deletedPrefix);
|
|
46
83
|
if (opts.ignoreCase)
|
|
47
84
|
return (a || '').toLowerCase() == (b || '').toLowerCase();
|
|
48
85
|
return a == b;
|
|
@@ -58,16 +95,25 @@ function testEqualSchemas(lschema, rschema, opts) {
|
|
|
58
95
|
rschema = null;
|
|
59
96
|
return testEqualNames(lschema, rschema, opts);
|
|
60
97
|
}
|
|
61
|
-
function testEqualFullNames(lft, rgt, opts) {
|
|
98
|
+
function testEqualFullNames(lft, rgt, opts, deletedPrefix) {
|
|
62
99
|
if (lft == null || rgt == null)
|
|
63
100
|
return lft == rgt;
|
|
64
|
-
return testEqualSchemas(lft.schemaName, rgt.schemaName, opts) &&
|
|
101
|
+
return (testEqualSchemas(lft.schemaName, rgt.schemaName, opts) &&
|
|
102
|
+
testEqualNames(lft.pureName, rgt.pureName, opts, deletedPrefix));
|
|
65
103
|
}
|
|
66
104
|
function testEqualDefaultValues(value1, value2) {
|
|
67
105
|
if (value1 == null)
|
|
68
106
|
return value2 == null || value2 == 'NULL';
|
|
69
107
|
if (value2 == null)
|
|
70
108
|
return value1 == null || value1 == 'NULL';
|
|
109
|
+
if ((0, isString_1.default)(value1) && (0, isString_1.default)(value2)) {
|
|
110
|
+
value1 = value1.trim();
|
|
111
|
+
value2 = value2.trim();
|
|
112
|
+
if (value1.startsWith("'") && value1.endsWith("'") && value2.startsWith("'") && value2.endsWith("'")) {
|
|
113
|
+
return value1 == value2;
|
|
114
|
+
}
|
|
115
|
+
return value1.toLowerCase() == value2.toLowerCase();
|
|
116
|
+
}
|
|
71
117
|
return value1 == value2;
|
|
72
118
|
}
|
|
73
119
|
function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
@@ -175,19 +221,86 @@ function testEqualColumns(a, b, checkName, checkDefault, opts = {}) {
|
|
|
175
221
|
return true;
|
|
176
222
|
}
|
|
177
223
|
exports.testEqualColumns = testEqualColumns;
|
|
178
|
-
function
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
224
|
+
function testEqualColumnRefs(a, b, opts) {
|
|
225
|
+
if (a.length != b.length)
|
|
226
|
+
return false;
|
|
227
|
+
for (let i = 0; i < a.length; i++) {
|
|
228
|
+
if (!testEqualNames(a[i].columnName, b[i].columnName, opts))
|
|
229
|
+
return false;
|
|
230
|
+
if (!testEqualNames(a[i].refColumnName, b[i].refColumnName, opts))
|
|
231
|
+
return false;
|
|
183
232
|
}
|
|
184
|
-
|
|
185
|
-
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
function testEqualPrimaryKeys(a, b, opts) {
|
|
236
|
+
if (!testEqualColumnRefs(a.columns, b.columns, opts))
|
|
237
|
+
return false;
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
function testEqualForeignKeys(a, b, opts) {
|
|
241
|
+
if (!testEqualColumnRefs(a.columns, b.columns, opts))
|
|
242
|
+
return false;
|
|
243
|
+
if (!opts.ignoreConstraintNames && !testEqualNames(a.constraintName, b.constraintName, opts))
|
|
244
|
+
return false;
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
function testEqualIndex(a, b, opts) {
|
|
248
|
+
if (!testEqualColumnRefs(a.columns, b.columns, opts))
|
|
249
|
+
return false;
|
|
250
|
+
if (!!a.isUnique != !!b.isUnique)
|
|
251
|
+
return false;
|
|
252
|
+
if (simplifySqlExpression(a.filterDefinition) != simplifySqlExpression(b.filterDefinition))
|
|
253
|
+
return false;
|
|
254
|
+
if (!opts.ignoreConstraintNames && !testEqualNames(a.constraintName, b.constraintName, opts))
|
|
255
|
+
return false;
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
function testEqualUnique(a, b, opts) {
|
|
259
|
+
if (!testEqualColumnRefs(a.columns, b.columns, opts))
|
|
260
|
+
return false;
|
|
261
|
+
if (!opts.ignoreConstraintNames && !testEqualNames(a.constraintName, b.constraintName, opts))
|
|
262
|
+
return false;
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
function testEqualCheck(a, b, opts) {
|
|
266
|
+
if (a.definition != b.definition)
|
|
267
|
+
return false;
|
|
268
|
+
if (!opts.ignoreConstraintNames && !testEqualNames(a.constraintName, b.constraintName, opts))
|
|
269
|
+
return false;
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
function testEqualConstraints(a, b, opts = {}) {
|
|
273
|
+
if (a.constraintType != b.constraintType) {
|
|
274
|
+
console.debug(`Constraint ${a.pureName}: different constraint type: ${a.constraintType}, ${b.constraintType}`);
|
|
275
|
+
return false;
|
|
186
276
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
277
|
+
switch (a.constraintType) {
|
|
278
|
+
case 'primaryKey':
|
|
279
|
+
case 'sortingKey':
|
|
280
|
+
return testEqualPrimaryKeys(a, b, opts);
|
|
281
|
+
case 'foreignKey':
|
|
282
|
+
return testEqualForeignKeys(a, b, opts);
|
|
283
|
+
case 'index':
|
|
284
|
+
return testEqualIndex(a, b, opts);
|
|
285
|
+
case 'unique':
|
|
286
|
+
return testEqualUnique(a, b, opts);
|
|
287
|
+
case 'check':
|
|
288
|
+
return testEqualCheck(a, b, opts);
|
|
190
289
|
}
|
|
290
|
+
console.debug(`Unknown constraint type: ${a.pureName}`);
|
|
291
|
+
return false;
|
|
292
|
+
// const omitList = ['pairingId'];
|
|
293
|
+
// if (opts.ignoreForeignKeyActions) {
|
|
294
|
+
// omitList.push('updateAction');
|
|
295
|
+
// omitList.push('deleteAction');
|
|
296
|
+
// }
|
|
297
|
+
// if (opts.ignoreConstraintNames) {
|
|
298
|
+
// omitList.push('constraintName');
|
|
299
|
+
// }
|
|
300
|
+
// if (opts.schemaMode == 'ignore') {
|
|
301
|
+
// omitList.push('schemaName');
|
|
302
|
+
// omitList.push('refSchemaName');
|
|
303
|
+
// }
|
|
191
304
|
// if (a.constraintType == 'primaryKey' && b.constraintType == 'primaryKey') {
|
|
192
305
|
// console.log('PK1', stableStringify(_.omit(a, omitList)));
|
|
193
306
|
// console.log('PK2', stableStringify(_.omit(b, omitList)));
|
|
@@ -200,13 +313,15 @@ function testEqualConstraints(a, b, opts = {}) {
|
|
|
200
313
|
// console.log('IX1', stableStringify(_omit(a, omitList)));
|
|
201
314
|
// console.log('IX2', stableStringify(_omit(b, omitList)));
|
|
202
315
|
// }
|
|
203
|
-
|
|
316
|
+
// const aStringified = stableStringify(_omit(a, omitList));
|
|
317
|
+
// const bStringified = stableStringify(_omit(b, omitList));
|
|
318
|
+
// return aStringified == bStringified;
|
|
204
319
|
}
|
|
205
320
|
function testEqualTypes(a, b, opts = {}) {
|
|
206
321
|
if (opts.ignoreDataTypes) {
|
|
207
322
|
return true;
|
|
208
323
|
}
|
|
209
|
-
if ((a.dataType
|
|
324
|
+
if (simplifySqlExpression(a.dataType) != simplifySqlExpression(b.dataType)) {
|
|
210
325
|
console.debug(`Column ${a.pureName}.${a.columnName}, ${b.pureName}.${b.columnName}: different data type: ${a.dataType}, ${b.dataType}`);
|
|
211
326
|
return false;
|
|
212
327
|
}
|
|
@@ -250,7 +365,7 @@ function createPairs(oldList, newList, additionalCondition = null) {
|
|
|
250
365
|
function planTablePreload(plan, oldTable, newTable) {
|
|
251
366
|
var _a, _b, _c, _d;
|
|
252
367
|
const key = newTable.preloadedRowsKey || ((_b = (_a = newTable.primaryKey) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.map(x => x.columnName));
|
|
253
|
-
if (((_c = newTable.preloadedRows) === null || _c === void 0 ? void 0 : _c.length) > 0 && (key === null || key === void 0 ? void 0 : key.length) > 0) {
|
|
368
|
+
if (((_c = newTable.preloadedRows) === null || _c === void 0 ? void 0 : _c.length) > 0 && (key === null || key === void 0 ? void 0 : key.length) > 0 && (0, structureTools_1.detectChangesInPreloadedRows)(oldTable, newTable)) {
|
|
254
369
|
plan.fillPreloadedRows(newTable, oldTable === null || oldTable === void 0 ? void 0 : oldTable.preloadedRows, newTable.preloadedRows, key, newTable.preloadedRowsInsertOnly, (_d = newTable.columns.find(x => x.autoIncrement)) === null || _d === void 0 ? void 0 : _d.columnName);
|
|
255
370
|
}
|
|
256
371
|
}
|
|
@@ -267,24 +382,43 @@ function planAlterTable(plan, oldTable, newTable, opts) {
|
|
|
267
382
|
if (!opts.noDropConstraint) {
|
|
268
383
|
constraintPairs.filter(x => x[1] == null).forEach(x => plan.dropConstraint(x[0]));
|
|
269
384
|
}
|
|
270
|
-
if (
|
|
385
|
+
if (opts.deletedColumnPrefix) {
|
|
386
|
+
columnPairs
|
|
387
|
+
.filter(x => x[1] == null)
|
|
388
|
+
.forEach(x => {
|
|
389
|
+
if (!hasDeletedPrefix(x[0].columnName, opts, opts.deletedColumnPrefix)) {
|
|
390
|
+
plan.renameColumn(x[0], opts.deletedColumnPrefix + x[0].columnName);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
else if (!opts.noDropColumn) {
|
|
271
395
|
columnPairs.filter(x => x[1] == null).forEach(x => plan.dropColumn(x[0]));
|
|
272
396
|
}
|
|
273
397
|
if (!testEqualFullNames(oldTable, newTable, opts) && !opts.noRenameTable) {
|
|
274
398
|
plan.renameTable(oldTable, newTable.pureName);
|
|
275
399
|
}
|
|
400
|
+
if (hasDeletedPrefix(oldTable.pureName, opts, opts.deletedTablePrefix)) {
|
|
401
|
+
plan.renameTable(oldTable, newTable.pureName);
|
|
402
|
+
}
|
|
276
403
|
columnPairs.filter(x => x[0] == null).forEach(x => plan.createColumn(x[1]));
|
|
277
404
|
columnPairs
|
|
278
405
|
.filter(x => x[0] && x[1])
|
|
279
406
|
.forEach(x => {
|
|
280
|
-
|
|
281
|
-
|
|
407
|
+
let srccol = x[0];
|
|
408
|
+
let dstcol = x[1];
|
|
409
|
+
if (hasDeletedPrefix(srccol.columnName, opts, opts.deletedColumnPrefix)) {
|
|
410
|
+
plan.renameColumn(srccol, dstcol.columnName);
|
|
411
|
+
// rename is already done
|
|
412
|
+
srccol = Object.assign(Object.assign({}, srccol), { columnName: dstcol.columnName });
|
|
413
|
+
}
|
|
414
|
+
if (!testEqualColumns(srccol, dstcol, true, true, opts)) {
|
|
415
|
+
if (testEqualColumns(srccol, dstcol, false, true, opts) && !opts.noRenameColumn) {
|
|
282
416
|
// console.log('PLAN RENAME COLUMN')
|
|
283
|
-
plan.renameColumn(
|
|
417
|
+
plan.renameColumn(srccol, dstcol.columnName);
|
|
284
418
|
}
|
|
285
419
|
else {
|
|
286
420
|
// console.log('PLAN CHANGE COLUMN', x[0], x[1]);
|
|
287
|
-
plan.changeColumn(
|
|
421
|
+
plan.changeColumn(srccol, dstcol);
|
|
288
422
|
}
|
|
289
423
|
}
|
|
290
424
|
});
|
|
@@ -297,7 +431,6 @@ function planAlterTable(plan, oldTable, newTable, opts) {
|
|
|
297
431
|
}
|
|
298
432
|
});
|
|
299
433
|
constraintPairs.filter(x => x[0] == null).forEach(x => plan.createConstraint(x[1]));
|
|
300
|
-
planTablePreload(plan, oldTable, newTable);
|
|
301
434
|
planChangeTableOptions(plan, oldTable, newTable, opts);
|
|
302
435
|
// console.log('oldTable', oldTable);
|
|
303
436
|
// console.log('newTable', newTable);
|
|
@@ -320,12 +453,21 @@ function planChangeTableOptions(plan, oldTable, newTable, opts) {
|
|
|
320
453
|
function testEqualTables(a, b, opts, wholeOldDb, wholeNewDb, driver) {
|
|
321
454
|
const plan = new alterPlan_1.AlterPlan(wholeOldDb, wholeNewDb, driver.dialect, opts);
|
|
322
455
|
planAlterTable(plan, a, b, opts);
|
|
323
|
-
//
|
|
324
|
-
|
|
456
|
+
// if (plan.operations.length > 0) {
|
|
457
|
+
// console.log('************** plan.operations', a, b, plan.operations);
|
|
458
|
+
// }
|
|
459
|
+
if (plan.operations.length > 0) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
if ((0, structureTools_1.detectChangesInPreloadedRows)(a, b)) {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
return true;
|
|
325
466
|
}
|
|
326
467
|
exports.testEqualTables = testEqualTables;
|
|
327
468
|
function testEqualSqlObjects(a, b, opts) {
|
|
328
|
-
|
|
469
|
+
var _a, _b;
|
|
470
|
+
return ((_a = a.createSql) === null || _a === void 0 ? void 0 : _a.trim()) == ((_b = b.createSql) === null || _b === void 0 ? void 0 : _b.trim());
|
|
329
471
|
}
|
|
330
472
|
exports.testEqualSqlObjects = testEqualSqlObjects;
|
|
331
473
|
function createAlterTablePlan(oldTable, newTable, opts, wholeOldDb, wholeNewDb, driver) {
|
|
@@ -339,11 +481,42 @@ function createAlterTablePlan(oldTable, newTable, opts, wholeOldDb, wholeNewDb,
|
|
|
339
481
|
}
|
|
340
482
|
else {
|
|
341
483
|
planAlterTable(plan, oldTable, newTable, opts);
|
|
484
|
+
planTablePreload(plan, oldTable, newTable);
|
|
342
485
|
}
|
|
343
486
|
plan.transformPlan();
|
|
344
487
|
return plan;
|
|
345
488
|
}
|
|
346
489
|
exports.createAlterTablePlan = createAlterTablePlan;
|
|
490
|
+
function sortViewsByDependency(views) {
|
|
491
|
+
const viewNames = [];
|
|
492
|
+
const viewDict = {};
|
|
493
|
+
for (const view of views) {
|
|
494
|
+
if (!viewNames.includes(view.pureName)) {
|
|
495
|
+
viewNames.push(view.pureName);
|
|
496
|
+
}
|
|
497
|
+
viewDict[view.pureName] = viewDict[view.pureName]
|
|
498
|
+
? `${viewDict[view.pureName]} ${view.createSql}}`
|
|
499
|
+
: view.createSql;
|
|
500
|
+
}
|
|
501
|
+
const edges = [];
|
|
502
|
+
for (const viewName of viewNames) {
|
|
503
|
+
edges.push([viewName, null]);
|
|
504
|
+
const viewText = viewDict[viewName];
|
|
505
|
+
for (const otherView of viewNames) {
|
|
506
|
+
if (otherView === viewName)
|
|
507
|
+
continue;
|
|
508
|
+
if ((' ' + viewText + ' ').match('[\\W]' + otherView + '[\\W]')) {
|
|
509
|
+
edges.push([otherView, viewName]);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const ordered = (0, compact_1.default)((0, toposort_1.default)(edges));
|
|
514
|
+
const res = [];
|
|
515
|
+
for (const viewName of ordered) {
|
|
516
|
+
res.push(...views.filter(x => x.pureName == viewName));
|
|
517
|
+
}
|
|
518
|
+
return res;
|
|
519
|
+
}
|
|
347
520
|
function createAlterDatabasePlan(oldDb, newDb, opts, wholeOldDb, wholeNewDb, driver) {
|
|
348
521
|
const plan = new alterPlan_1.AlterPlan(wholeOldDb, wholeNewDb, driver.dialect, opts);
|
|
349
522
|
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
|
|
@@ -351,30 +524,47 @@ function createAlterDatabasePlan(oldDb, newDb, opts, wholeOldDb, wholeNewDb, dri
|
|
|
351
524
|
const newobj = (newDb[objectTypeField] || []).find(x => x.pairingId == oldobj.pairingId);
|
|
352
525
|
if (objectTypeField == 'tables') {
|
|
353
526
|
if (newobj == null) {
|
|
354
|
-
if (!opts.
|
|
527
|
+
if (opts.deletedTablePrefix && !hasDeletedPrefix(oldobj.pureName, opts, opts.deletedTablePrefix)) {
|
|
528
|
+
plan.renameTable(oldobj, opts.deletedTablePrefix + oldobj.pureName);
|
|
529
|
+
}
|
|
530
|
+
else if (!opts.noDropTable) {
|
|
355
531
|
plan.dropTable(oldobj);
|
|
356
532
|
}
|
|
357
533
|
}
|
|
358
534
|
else {
|
|
359
535
|
planAlterTable(plan, oldobj, newobj, opts);
|
|
536
|
+
planTablePreload(plan, oldobj, newobj);
|
|
360
537
|
}
|
|
361
538
|
}
|
|
362
539
|
else {
|
|
363
540
|
if (newobj == null) {
|
|
364
|
-
if (
|
|
541
|
+
if (opts.deletedSqlObjectPrefix &&
|
|
542
|
+
driver.dialect.renameSqlObject &&
|
|
543
|
+
!hasDeletedPrefix(oldobj.pureName, opts, opts.deletedSqlObjectPrefix)) {
|
|
544
|
+
plan.renameSqlObject(oldobj, opts.deletedSqlObjectPrefix + oldobj.pureName);
|
|
545
|
+
}
|
|
546
|
+
else if (!opts.noDropSqlObject) {
|
|
365
547
|
plan.dropSqlObject(oldobj);
|
|
366
548
|
}
|
|
367
549
|
}
|
|
368
|
-
else
|
|
369
|
-
|
|
370
|
-
if (!opts.noDropSqlObject) {
|
|
550
|
+
else {
|
|
551
|
+
if (opts.deletedSqlObjectPrefix && hasDeletedPrefix(oldobj.pureName, opts, opts.deletedSqlObjectPrefix)) {
|
|
371
552
|
plan.dropSqlObject(oldobj);
|
|
553
|
+
plan.createSqlObject(newobj);
|
|
554
|
+
}
|
|
555
|
+
else if (!testEqualSqlObjects(oldobj, newobj, opts)) {
|
|
556
|
+
plan.recreates.sqlObjects += 1;
|
|
557
|
+
plan.dropSqlObject(oldobj);
|
|
558
|
+
plan.createSqlObject(newobj);
|
|
372
559
|
}
|
|
373
|
-
plan.createSqlObject(newobj);
|
|
374
560
|
}
|
|
375
561
|
}
|
|
376
562
|
}
|
|
377
|
-
|
|
563
|
+
let newList = newDb[objectTypeField] || [];
|
|
564
|
+
if (objectTypeField == 'views') {
|
|
565
|
+
newList = sortViewsByDependency(newList);
|
|
566
|
+
}
|
|
567
|
+
for (const newobj of newList) {
|
|
378
568
|
const oldobj = (oldDb[objectTypeField] || []).find(x => x.pairingId == newobj.pairingId);
|
|
379
569
|
if (objectTypeField == 'tables') {
|
|
380
570
|
if (oldobj == null) {
|
|
@@ -405,8 +595,11 @@ function getAlterTableScript(oldTable, newTable, opts, wholeOldDb, wholeNewDb, d
|
|
|
405
595
|
};
|
|
406
596
|
}
|
|
407
597
|
exports.getAlterTableScript = getAlterTableScript;
|
|
408
|
-
function getAlterDatabaseScript(oldDb, newDb, opts, wholeOldDb, wholeNewDb, driver) {
|
|
598
|
+
function getAlterDatabaseScript(oldDb, newDb, opts, wholeOldDb, wholeNewDb, driver, transformPlan = null) {
|
|
409
599
|
const plan = createAlterDatabasePlan(oldDb, newDb, opts, wholeOldDb, wholeNewDb, driver);
|
|
600
|
+
if (transformPlan) {
|
|
601
|
+
transformPlan(plan);
|
|
602
|
+
}
|
|
410
603
|
const dmp = driver.createDumper({ useHardSeparator: true });
|
|
411
604
|
plan.run(dmp);
|
|
412
605
|
return {
|
|
@@ -422,12 +615,12 @@ function matchPairedObjects(db1, db2, opts) {
|
|
|
422
615
|
const res = (0, cloneDeep_1.default)(db2);
|
|
423
616
|
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
|
|
424
617
|
for (const obj2 of res[objectTypeField] || []) {
|
|
425
|
-
const obj1 = db1[objectTypeField].find(x => testEqualFullNames(x, obj2, opts));
|
|
618
|
+
const obj1 = db1[objectTypeField].find(x => testEqualFullNames(x, obj2, opts, objectTypeField == 'tables' ? opts.deletedTablePrefix : opts.deletedSqlObjectPrefix));
|
|
426
619
|
if (obj1) {
|
|
427
620
|
obj2.pairingId = obj1.pairingId;
|
|
428
621
|
if (objectTypeField == 'tables') {
|
|
429
622
|
for (const col2 of obj2.columns) {
|
|
430
|
-
const col1 = obj1.columns.find(x => testEqualNames(x.columnName, col2.columnName, opts));
|
|
623
|
+
const col1 = obj1.columns.find(x => testEqualNames(x.columnName, col2.columnName, opts, opts.deletedColumnPrefix));
|
|
431
624
|
if (col1)
|
|
432
625
|
col2.pairingId = col1.pairingId;
|
|
433
626
|
}
|
|
@@ -456,7 +649,6 @@ function matchPairedObjects(db1, db2, opts) {
|
|
|
456
649
|
exports.matchPairedObjects = matchPairedObjects;
|
|
457
650
|
exports.modelCompareDbDiffOptions = {
|
|
458
651
|
ignoreCase: true,
|
|
459
|
-
schemaMode: 'ignore',
|
|
460
652
|
ignoreConstraintNames: true,
|
|
461
653
|
ignoreForeignKeyActions: true,
|
|
462
654
|
ignoreDataTypes: true,
|
package/lib/driverBase.js
CHANGED
|
@@ -18,6 +18,9 @@ const SqlDumper_1 = require("./SqlDumper");
|
|
|
18
18
|
const dbgate_query_splitter_1 = require("dbgate-query-splitter");
|
|
19
19
|
const dbgate_sqltree_1 = require("dbgate-sqltree");
|
|
20
20
|
const detectSqlFilterBehaviour_1 = require("./detectSqlFilterBehaviour");
|
|
21
|
+
const getLogger_1 = require("./getLogger");
|
|
22
|
+
const stringTools_1 = require("./stringTools");
|
|
23
|
+
const logger = (0, getLogger_1.getLogger)('driverBase');
|
|
21
24
|
const dialect = {
|
|
22
25
|
limitSelect: true,
|
|
23
26
|
rangeSelect: true,
|
|
@@ -89,6 +92,9 @@ exports.driverBase = {
|
|
|
89
92
|
}
|
|
90
93
|
for (const sqlItem of (0, dbgate_query_splitter_1.splitQuery)(sql, this.getQuerySplitterOptions('script'))) {
|
|
91
94
|
try {
|
|
95
|
+
if (options === null || options === void 0 ? void 0 : options.logScriptItems) {
|
|
96
|
+
logger.info({ sql: (0, stringTools_1.getLimitedQuery)(sqlItem) }, 'Execute script item');
|
|
97
|
+
}
|
|
92
98
|
yield this.query(pool, sqlItem, Object.assign({ discardResult: true }, options === null || options === void 0 ? void 0 : options.queryOptions));
|
|
93
99
|
}
|
|
94
100
|
catch (err) {
|
|
@@ -26,6 +26,9 @@ function getConnectionLabelCore(connection, { allowExplicitDatabase = true } = {
|
|
|
26
26
|
if (connection.databaseFile) {
|
|
27
27
|
return getDatabaseFileLabel(connection.databaseFile);
|
|
28
28
|
}
|
|
29
|
+
if (connection.useSshTunnel && connection.server == 'localhost') {
|
|
30
|
+
return `${connection.sshHost} - SSH`;
|
|
31
|
+
}
|
|
29
32
|
if (connection.server) {
|
|
30
33
|
return connection.server;
|
|
31
34
|
}
|
package/lib/stringTools.d.ts
CHANGED
|
@@ -32,3 +32,5 @@ export declare function extractErrorLogData(err: any, additionalFields?: {}): {
|
|
|
32
32
|
errorStack: string;
|
|
33
33
|
};
|
|
34
34
|
export declare function safeFormatDate(date: any): any;
|
|
35
|
+
export declare function getLimitedQuery(sql: string): string;
|
|
36
|
+
export declare function pinoLogRecordToMessageRecord(logRecord: any, defaultSeverity?: string): any;
|
package/lib/stringTools.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
15
|
};
|
|
5
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.safeFormatDate = exports.extractErrorLogData = exports.extractErrorStackTrace = exports.extractErrorMessage = exports.getConvertValueMenu = exports.detectTypeIcon = exports.detectCellDataType = exports.parseSqlDefaultValue = exports.getAsImageSrc = exports.arrayBufferToBase64 = exports.isWktGeometry = exports.getIconForRedisType = exports.isJsonLikeLongString = exports.shouldOpenMultilineDialog = exports.safeJsonParse = exports.stringifyCellValue = exports.parseCellValue = exports.hexStringToArray = exports.arrayToHexString = void 0;
|
|
17
|
+
exports.pinoLogRecordToMessageRecord = exports.getLimitedQuery = exports.safeFormatDate = exports.extractErrorLogData = exports.extractErrorStackTrace = exports.extractErrorMessage = exports.getConvertValueMenu = exports.detectTypeIcon = exports.detectCellDataType = exports.parseSqlDefaultValue = exports.getAsImageSrc = exports.arrayBufferToBase64 = exports.isWktGeometry = exports.getIconForRedisType = exports.isJsonLikeLongString = exports.shouldOpenMultilineDialog = exports.safeJsonParse = exports.stringifyCellValue = exports.parseCellValue = exports.hexStringToArray = exports.arrayToHexString = void 0;
|
|
7
18
|
const isString_1 = __importDefault(require("lodash/isString"));
|
|
8
19
|
const isArray_1 = __importDefault(require("lodash/isArray"));
|
|
9
20
|
const isDate_1 = __importDefault(require("lodash/isDate"));
|
|
@@ -489,3 +500,27 @@ function safeFormatDate(date) {
|
|
|
489
500
|
}
|
|
490
501
|
}
|
|
491
502
|
exports.safeFormatDate = safeFormatDate;
|
|
503
|
+
function getLimitedQuery(sql) {
|
|
504
|
+
if (!sql) {
|
|
505
|
+
return sql;
|
|
506
|
+
}
|
|
507
|
+
if (sql.length > 1000) {
|
|
508
|
+
return sql.substring(0, 1000) + '...';
|
|
509
|
+
}
|
|
510
|
+
return sql;
|
|
511
|
+
}
|
|
512
|
+
exports.getLimitedQuery = getLimitedQuery;
|
|
513
|
+
function pinoLogRecordToMessageRecord(logRecord, defaultSeverity = 'info') {
|
|
514
|
+
var _a;
|
|
515
|
+
const { level, time, msg } = logRecord, rest = __rest(logRecord, ["level", "time", "msg"]);
|
|
516
|
+
const levelToSeverity = {
|
|
517
|
+
10: 'debug',
|
|
518
|
+
20: 'debug',
|
|
519
|
+
30: 'info',
|
|
520
|
+
40: 'info',
|
|
521
|
+
50: 'error',
|
|
522
|
+
60: 'error',
|
|
523
|
+
};
|
|
524
|
+
return Object.assign(Object.assign({}, rest), { time, message: msg, severity: (_a = levelToSeverity[level]) !== null && _a !== void 0 ? _a : defaultSeverity });
|
|
525
|
+
}
|
|
526
|
+
exports.pinoLogRecordToMessageRecord = pinoLogRecordToMessageRecord;
|
package/lib/structureTools.d.ts
CHANGED
|
@@ -13,3 +13,19 @@ export declare function isViewInfo(obj: {
|
|
|
13
13
|
export declare function isCollectionInfo(obj: {
|
|
14
14
|
objectTypeField?: string;
|
|
15
15
|
}): obj is CollectionInfo;
|
|
16
|
+
export declare function filterStructureBySchema(db: DatabaseInfo, schema: string): DatabaseInfo;
|
|
17
|
+
export declare function getSchemasUsedByStructure(db: DatabaseInfo): string[] | DatabaseInfo;
|
|
18
|
+
export declare function replaceSchemaInStructure(db: DatabaseInfo, schema: string): DatabaseInfo;
|
|
19
|
+
export declare function skipNamesInStructureByRegex(db: DatabaseInfo, regex: RegExp): DatabaseInfo;
|
|
20
|
+
export declare function detectChangesInPreloadedRows(oldTable: TableInfo, newTable: TableInfo): boolean;
|
|
21
|
+
export declare function removePreloadedRowsFromStructure(db: DatabaseInfo): DatabaseInfo;
|
|
22
|
+
export declare function skipDbGateInternalObjects(db: DatabaseInfo): {
|
|
23
|
+
tables: TableInfo[];
|
|
24
|
+
engine?: string;
|
|
25
|
+
collections: CollectionInfo[];
|
|
26
|
+
views: ViewInfo[];
|
|
27
|
+
matviews: ViewInfo[];
|
|
28
|
+
procedures: import("dbgate-types").ProcedureInfo[];
|
|
29
|
+
functions: import("dbgate-types").FunctionInfo[];
|
|
30
|
+
triggers: import("dbgate-types").TriggerInfo[];
|
|
31
|
+
};
|
package/lib/structureTools.js
CHANGED
|
@@ -3,8 +3,10 @@ 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.isCollectionInfo = exports.isViewInfo = exports.isTableInfo = exports.isTableColumnUnique = exports.extendDatabaseInfoFromApps = exports.extendDatabaseInfo = exports.extendTableInfo = exports.addTableDependencies = void 0;
|
|
6
|
+
exports.skipDbGateInternalObjects = exports.removePreloadedRowsFromStructure = exports.detectChangesInPreloadedRows = exports.skipNamesInStructureByRegex = exports.replaceSchemaInStructure = exports.getSchemasUsedByStructure = exports.filterStructureBySchema = exports.isCollectionInfo = exports.isViewInfo = exports.isTableInfo = exports.isTableColumnUnique = exports.extendDatabaseInfoFromApps = exports.extendDatabaseInfo = exports.extendTableInfo = exports.addTableDependencies = void 0;
|
|
7
7
|
const flatten_1 = __importDefault(require("lodash/flatten"));
|
|
8
|
+
const uniq_1 = __importDefault(require("lodash/uniq"));
|
|
9
|
+
const keys_1 = __importDefault(require("lodash/keys"));
|
|
8
10
|
function addTableDependencies(db) {
|
|
9
11
|
if (!db.tables) {
|
|
10
12
|
return db;
|
|
@@ -61,3 +63,89 @@ function isCollectionInfo(obj) {
|
|
|
61
63
|
return obj.objectTypeField == 'collections';
|
|
62
64
|
}
|
|
63
65
|
exports.isCollectionInfo = isCollectionInfo;
|
|
66
|
+
function filterStructureBySchema(db, schema) {
|
|
67
|
+
if (!db) {
|
|
68
|
+
return db;
|
|
69
|
+
}
|
|
70
|
+
return Object.assign(Object.assign({}, db), { tables: (db.tables || []).filter(x => x.schemaName == schema), views: (db.views || []).filter(x => x.schemaName == schema), collections: (db.collections || []).filter(x => x.schemaName == schema), matviews: (db.matviews || []).filter(x => x.schemaName == schema), procedures: (db.procedures || []).filter(x => x.schemaName == schema), functions: (db.functions || []).filter(x => x.schemaName == schema), triggers: (db.triggers || []).filter(x => x.schemaName == schema) });
|
|
71
|
+
}
|
|
72
|
+
exports.filterStructureBySchema = filterStructureBySchema;
|
|
73
|
+
function getSchemasUsedByStructure(db) {
|
|
74
|
+
if (!db) {
|
|
75
|
+
return db;
|
|
76
|
+
}
|
|
77
|
+
return (0, uniq_1.default)([
|
|
78
|
+
...(db.tables || []).map(x => x.schemaName),
|
|
79
|
+
...(db.views || []).map(x => x.schemaName),
|
|
80
|
+
...(db.collections || []).map(x => x.schemaName),
|
|
81
|
+
...(db.matviews || []).map(x => x.schemaName),
|
|
82
|
+
...(db.procedures || []).map(x => x.schemaName),
|
|
83
|
+
...(db.functions || []).map(x => x.schemaName),
|
|
84
|
+
...(db.triggers || []).map(x => x.schemaName),
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
exports.getSchemasUsedByStructure = getSchemasUsedByStructure;
|
|
88
|
+
function replaceSchemaInStructure(db, schema) {
|
|
89
|
+
if (!db) {
|
|
90
|
+
return db;
|
|
91
|
+
}
|
|
92
|
+
return Object.assign(Object.assign({}, db), { tables: (db.tables || []).map(tbl => (Object.assign(Object.assign({}, tbl), { schemaName: schema, columns: (tbl.columns || []).map(column => (Object.assign(Object.assign({}, column), { schemaName: schema }))), primaryKey: tbl.primaryKey ? Object.assign(Object.assign({}, tbl.primaryKey), { schemaName: schema }) : undefined, sortingKey: tbl.sortingKey ? Object.assign(Object.assign({}, tbl.sortingKey), { schemaName: schema }) : undefined, foreignKeys: (tbl.foreignKeys || []).map(fk => (Object.assign(Object.assign({}, fk), { refSchemaName: schema, schemaName: schema }))), indexes: (tbl.indexes || []).map(idx => (Object.assign(Object.assign({}, idx), { schemaName: schema }))), uniques: (tbl.uniques || []).map(idx => (Object.assign(Object.assign({}, idx), { schemaName: schema }))), checks: (tbl.checks || []).map(idx => (Object.assign(Object.assign({}, idx), { schemaName: schema }))) }))), views: (db.views || []).map(x => (Object.assign(Object.assign({}, x), { schemaName: schema }))), collections: (db.collections || []).map(x => (Object.assign(Object.assign({}, x), { schemaName: schema }))), matviews: (db.matviews || []).map(x => (Object.assign(Object.assign({}, x), { schemaName: schema }))), procedures: (db.procedures || []).map(x => (Object.assign(Object.assign({}, x), { schemaName: schema }))), functions: (db.functions || []).map(x => (Object.assign(Object.assign({}, x), { schemaName: schema }))), triggers: (db.triggers || []).map(x => (Object.assign(Object.assign({}, x), { schemaName: schema }))) });
|
|
93
|
+
}
|
|
94
|
+
exports.replaceSchemaInStructure = replaceSchemaInStructure;
|
|
95
|
+
function skipNamesInStructureByRegex(db, regex) {
|
|
96
|
+
if (!db) {
|
|
97
|
+
return db;
|
|
98
|
+
}
|
|
99
|
+
return Object.assign(Object.assign({}, db), { tables: (db.tables || []).filter(tbl => !regex.test(tbl.pureName)), views: (db.views || []).filter(tbl => !regex.test(tbl.pureName)), collections: (db.collections || []).filter(tbl => !regex.test(tbl.pureName)), matviews: (db.matviews || []).filter(tbl => !regex.test(tbl.pureName)), procedures: (db.procedures || []).filter(tbl => !regex.test(tbl.pureName)), functions: (db.functions || []).filter(tbl => !regex.test(tbl.pureName)), triggers: (db.triggers || []).filter(tbl => !regex.test(tbl.pureName)) });
|
|
100
|
+
}
|
|
101
|
+
exports.skipNamesInStructureByRegex = skipNamesInStructureByRegex;
|
|
102
|
+
function detectChangesInPreloadedRows(oldTable, newTable) {
|
|
103
|
+
var _a, _b, _c, _d;
|
|
104
|
+
const key = (newTable === null || newTable === void 0 ? void 0 : newTable.preloadedRowsKey) ||
|
|
105
|
+
(oldTable === null || oldTable === void 0 ? void 0 : oldTable.preloadedRowsKey) ||
|
|
106
|
+
((_b = (_a = newTable === null || newTable === void 0 ? void 0 : newTable.primaryKey) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.map(x => x.columnName)) ||
|
|
107
|
+
((_d = (_c = oldTable === null || oldTable === void 0 ? void 0 : oldTable.primaryKey) === null || _c === void 0 ? void 0 : _c.columns) === null || _d === void 0 ? void 0 : _d.map(x => x.columnName));
|
|
108
|
+
const oldRows = (oldTable === null || oldTable === void 0 ? void 0 : oldTable.preloadedRows) || [];
|
|
109
|
+
const newRows = (newTable === null || newTable === void 0 ? void 0 : newTable.preloadedRows) || [];
|
|
110
|
+
const insertOnly = (newTable === null || newTable === void 0 ? void 0 : newTable.preloadedRowsInsertOnly) || (oldTable === null || oldTable === void 0 ? void 0 : oldTable.preloadedRowsInsertOnly);
|
|
111
|
+
if (newRows.length != oldRows.length) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
for (const row of newRows) {
|
|
115
|
+
const old = oldRows === null || oldRows === void 0 ? void 0 : oldRows.find(r => key.every(col => r[col] == row[col]));
|
|
116
|
+
const rowKeys = (0, keys_1.default)(row);
|
|
117
|
+
if (old) {
|
|
118
|
+
const updated = [];
|
|
119
|
+
for (const col of rowKeys) {
|
|
120
|
+
if (row[col] != old[col] && !(insertOnly === null || insertOnly === void 0 ? void 0 : insertOnly.includes(col))) {
|
|
121
|
+
updated.push(col);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (updated.length > 0) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
for (const row of oldRows || []) {
|
|
133
|
+
const newr = oldRows === null || oldRows === void 0 ? void 0 : oldRows.find(r => key.every(col => r[col] == row[col]));
|
|
134
|
+
if (!newr) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
exports.detectChangesInPreloadedRows = detectChangesInPreloadedRows;
|
|
141
|
+
function removePreloadedRowsFromStructure(db) {
|
|
142
|
+
if (!db) {
|
|
143
|
+
return db;
|
|
144
|
+
}
|
|
145
|
+
return Object.assign(Object.assign({}, db), { tables: (db.tables || []).map(tbl => (Object.assign(Object.assign({}, tbl), { preloadedRows: undefined, preloadedRowsKey: undefined, preloadedRowsInsertOnly: undefined }))) });
|
|
146
|
+
}
|
|
147
|
+
exports.removePreloadedRowsFromStructure = removePreloadedRowsFromStructure;
|
|
148
|
+
function skipDbGateInternalObjects(db) {
|
|
149
|
+
return Object.assign(Object.assign({}, db), { tables: (db.tables || []).filter(tbl => tbl.pureName != 'dbgate_deploy_journal') });
|
|
150
|
+
}
|
|
151
|
+
exports.skipDbGateInternalObjects = skipDbGateInternalObjects;
|
package/lib/yamlModelConv.d.ts
CHANGED
|
@@ -16,11 +16,19 @@ export interface DatabaseModelFile {
|
|
|
16
16
|
text: string;
|
|
17
17
|
json: {};
|
|
18
18
|
}
|
|
19
|
+
export interface IndexInfoYaml {
|
|
20
|
+
name: string;
|
|
21
|
+
unique?: boolean;
|
|
22
|
+
filter?: string;
|
|
23
|
+
columns: string[];
|
|
24
|
+
included?: string[];
|
|
25
|
+
}
|
|
19
26
|
export interface TableInfoYaml {
|
|
20
27
|
name: string;
|
|
21
28
|
columns: ColumnInfoYaml[];
|
|
22
29
|
primaryKey?: string[];
|
|
23
30
|
sortingKey?: string[];
|
|
31
|
+
indexes?: IndexInfoYaml[];
|
|
24
32
|
insertKey?: string[];
|
|
25
33
|
insertOnly?: string[];
|
|
26
34
|
data?: any[];
|
package/lib/yamlModelConv.js
CHANGED
|
@@ -37,14 +37,16 @@ function columnInfoFromYaml(column, table) {
|
|
|
37
37
|
const res = {
|
|
38
38
|
pureName: table.name,
|
|
39
39
|
columnName: column.name,
|
|
40
|
-
dataType: column.length ? `${column.type}(${column.length})` : column.type,
|
|
40
|
+
dataType: column.length ? `${column.type}(${column.length < 0 ? 'max' : column.length})` : column.type,
|
|
41
41
|
autoIncrement: column.autoIncrement,
|
|
42
42
|
notNull: column.notNull || (table.primaryKey && table.primaryKey.includes(column.name)),
|
|
43
43
|
defaultValue: column.default,
|
|
44
|
+
defaultConstraint: column.default != null ? `DF_${table.name}_${column.name}` : undefined,
|
|
44
45
|
};
|
|
45
46
|
return res;
|
|
46
47
|
}
|
|
47
48
|
function tableInfoToYaml(table) {
|
|
49
|
+
var _a;
|
|
48
50
|
const tableCopy = (0, cloneDeep_1.default)(table);
|
|
49
51
|
const res = {
|
|
50
52
|
name: tableCopy.pureName,
|
|
@@ -58,6 +60,20 @@ function tableInfoToYaml(table) {
|
|
|
58
60
|
res.sortingKey = tableCopy.sortingKey.columns.map(x => x.columnName);
|
|
59
61
|
}
|
|
60
62
|
// const foreignKeys = (tableCopy.foreignKeys || []).filter(x => !x['_dumped']).map(foreignKeyInfoToYaml);
|
|
63
|
+
if (((_a = tableCopy.indexes) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
64
|
+
res.indexes = tableCopy.indexes.map(index => {
|
|
65
|
+
const idx = {
|
|
66
|
+
name: index.constraintName,
|
|
67
|
+
unique: index.isUnique,
|
|
68
|
+
filter: index.filterDefinition,
|
|
69
|
+
columns: index.columns.filter(x => !x.isIncludedColumn).map(x => x.columnName),
|
|
70
|
+
};
|
|
71
|
+
if (index.columns.some(x => x.isIncludedColumn)) {
|
|
72
|
+
idx.included = index.columns.filter(x => x.isIncludedColumn).map(x => x.columnName);
|
|
73
|
+
}
|
|
74
|
+
return idx;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
61
77
|
return res;
|
|
62
78
|
}
|
|
63
79
|
exports.tableInfoToYaml = tableInfoToYaml;
|
|
@@ -67,6 +83,7 @@ function convertForeignKeyFromYaml(col, table, allTables) {
|
|
|
67
83
|
return null;
|
|
68
84
|
return {
|
|
69
85
|
constraintType: 'foreignKey',
|
|
86
|
+
constraintName: `FK_${table.name}_${col.name}`,
|
|
70
87
|
pureName: table.name,
|
|
71
88
|
refTableName: col.references,
|
|
72
89
|
deleteAction: col.refDeleteAction,
|
|
@@ -80,15 +97,28 @@ function convertForeignKeyFromYaml(col, table, allTables) {
|
|
|
80
97
|
};
|
|
81
98
|
}
|
|
82
99
|
function tableInfoFromYaml(table, allTables) {
|
|
100
|
+
var _a;
|
|
83
101
|
const res = {
|
|
84
102
|
pureName: table.name,
|
|
85
103
|
columns: table.columns.map(c => columnInfoFromYaml(c, table)),
|
|
86
104
|
foreignKeys: (0, compact_1.default)(table.columns.filter(x => x.references).map(col => convertForeignKeyFromYaml(col, table, allTables))),
|
|
105
|
+
indexes: (_a = table.indexes) === null || _a === void 0 ? void 0 : _a.map(index => ({
|
|
106
|
+
constraintName: index.name,
|
|
107
|
+
pureName: table.name,
|
|
108
|
+
isUnique: index.unique,
|
|
109
|
+
constraintType: 'index',
|
|
110
|
+
filterDefinition: index.filter,
|
|
111
|
+
columns: [
|
|
112
|
+
...index.columns.map(columnName => ({ columnName })),
|
|
113
|
+
...(index.included || []).map(columnName => ({ columnName, isIncludedColumn: true })),
|
|
114
|
+
],
|
|
115
|
+
})),
|
|
87
116
|
};
|
|
88
117
|
if (table.primaryKey) {
|
|
89
118
|
res.primaryKey = {
|
|
90
119
|
pureName: table.name,
|
|
91
120
|
constraintType: 'primaryKey',
|
|
121
|
+
constraintName: `PK_${table.name}`,
|
|
92
122
|
columns: table.primaryKey.map(columnName => ({ columnName })),
|
|
93
123
|
};
|
|
94
124
|
}
|
|
@@ -96,6 +126,7 @@ function tableInfoFromYaml(table, allTables) {
|
|
|
96
126
|
res.sortingKey = {
|
|
97
127
|
pureName: table.name,
|
|
98
128
|
constraintType: 'sortingKey',
|
|
129
|
+
constraintName: `SK_${table.name}`,
|
|
99
130
|
columns: table.sortingKey.map(columnName => ({ columnName })),
|
|
100
131
|
};
|
|
101
132
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "5.5.
|
|
2
|
+
"version": "5.5.7-alpha.25",
|
|
3
3
|
"name": "dbgate-tools",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"typings": "lib/index.d.ts",
|
|
@@ -25,18 +25,19 @@
|
|
|
25
25
|
],
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^13.7.0",
|
|
28
|
-
"dbgate-types": "^5.5.
|
|
28
|
+
"dbgate-types": "^5.5.7-alpha.25",
|
|
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
|
"dbgate-query-splitter": "^4.11.2",
|
|
35
|
-
"dbgate-sqltree": "^5.5.
|
|
35
|
+
"dbgate-sqltree": "^5.5.7-alpha.25",
|
|
36
36
|
"debug": "^4.3.4",
|
|
37
37
|
"json-stable-stringify": "^1.0.1",
|
|
38
38
|
"lodash": "^4.17.21",
|
|
39
39
|
"pinomin": "^1.0.4",
|
|
40
|
+
"toposort": "^2.0.2",
|
|
40
41
|
"uuid": "^3.4.0"
|
|
41
42
|
}
|
|
42
43
|
}
|