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.
@@ -75,7 +75,7 @@ class DatabaseAnalyser {
75
75
  }
76
76
  fullAnalysis() {
77
77
  return __awaiter(this, void 0, void 0, function* () {
78
- logger.info(`Performing full analysis, DB=${(0, schemaInfoTools_1.dbNameLogCategory)(this.dbhan.database)}, engine=${this.driver.engine}`);
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;
@@ -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}`);
@@ -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.putCmd(obj.createSql);
604
+ this.putRaw(obj.createSql);
605
+ this.endCommand();
601
606
  }
602
607
  getSqlObjectSqlName(ojectTypeField) {
603
608
  switch (ojectTypeField) {
@@ -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
- return [];
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
- // skip constraint recreate
223
- return [];
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.map(op => {
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;
@@ -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;
@@ -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;
@@ -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 json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
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 testEqualNames(a, b, opts) {
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) && testEqualNames(lft.pureName, rgt.pureName, 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 testEqualConstraints(a, b, opts = {}) {
179
- const omitList = [];
180
- if (opts.ignoreForeignKeyActions) {
181
- omitList.push('updateAction');
182
- omitList.push('deleteAction');
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
- if (opts.ignoreConstraintNames) {
185
- omitList.push('constraintName');
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
- if (opts.schemaMode == 'ignore') {
188
- omitList.push('schemaName');
189
- omitList.push('refSchemaName');
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
- 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));
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 || '').toLowerCase() != (b.dataType || '').toLowerCase()) {
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 (!opts.noDropColumn) {
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
- if (!testEqualColumns(x[0], x[1], true, true, opts)) {
281
- if (testEqualColumns(x[0], x[1], false, true, opts) && !opts.noRenameColumn) {
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(x[0], x[1].columnName);
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(x[0], x[1]);
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
- // console.log('plan.operations', a, b, plan.operations);
324
- return plan.operations.length == 0;
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
- return a.createSql == b.createSql;
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.noDropTable) {
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 (!opts.noDropSqlObject) {
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 if (!testEqualSqlObjects(oldobj.createSql, newobj.createSql, opts)) {
369
- plan.recreates.sqlObjects += 1;
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
- for (const newobj of newDb[objectTypeField] || []) {
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
  }
@@ -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;
@@ -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;
@@ -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
+ };
@@ -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;
@@ -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[];
@@ -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.6",
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.6",
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.6",
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
  }