@mikro-orm/knex 6.0.0-dev.4 → 6.0.0-dev.5
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/{dist/AbstractSqlConnection.d.ts → AbstractSqlConnection.d.ts} +0 -0
- package/{dist/AbstractSqlConnection.js → AbstractSqlConnection.js} +5 -0
- package/AbstractSqlDriver.d.ts +66 -0
- package/{dist/AbstractSqlDriver.js → AbstractSqlDriver.js} +218 -70
- package/{dist/AbstractSqlPlatform.d.ts → AbstractSqlPlatform.d.ts} +6 -4
- package/{dist/AbstractSqlPlatform.js → AbstractSqlPlatform.js} +18 -7
- package/{dist/MonkeyPatchable.d.ts → MonkeyPatchable.d.ts} +0 -0
- package/{dist/MonkeyPatchable.js → MonkeyPatchable.js} +0 -0
- package/{dist/README.md → README.md} +2 -2
- package/{dist/SqlEntityManager.d.ts → SqlEntityManager.d.ts} +5 -5
- package/{dist/SqlEntityManager.js → SqlEntityManager.js} +0 -1
- package/{dist/SqlEntityRepository.d.ts → SqlEntityRepository.d.ts} +3 -3
- package/{dist/SqlEntityRepository.js → SqlEntityRepository.js} +1 -1
- package/{dist/index.d.ts → index.d.ts} +0 -0
- package/{dist/index.js → index.js} +5 -1
- package/{dist/index.mjs → index.mjs} +0 -0
- package/package.json +27 -22
- package/{dist/query → query}/ArrayCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ArrayCriteriaNode.js +0 -0
- package/{dist/query → query}/CriteriaNode.d.ts +0 -0
- package/{dist/query → query}/CriteriaNode.js +7 -4
- package/{dist/query → query}/CriteriaNodeFactory.d.ts +0 -0
- package/{dist/query → query}/CriteriaNodeFactory.js +0 -0
- package/{dist/query → query}/ObjectCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ObjectCriteriaNode.js +14 -1
- package/{dist/query → query}/QueryBuilder.d.ts +58 -24
- package/{dist/query → query}/QueryBuilder.js +285 -84
- package/{dist/query → query}/QueryBuilderHelper.d.ts +19 -11
- package/{dist/query → query}/QueryBuilderHelper.js +206 -108
- package/{dist/query → query}/ScalarCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ScalarCriteriaNode.js +0 -0
- package/{dist/query → query}/enums.d.ts +0 -0
- package/{dist/query → query}/enums.js +0 -0
- package/{dist/query → query}/index.d.ts +0 -0
- package/{dist/query → query}/index.js +5 -1
- package/{dist/schema → schema}/DatabaseSchema.d.ts +1 -1
- package/{dist/schema → schema}/DatabaseSchema.js +8 -16
- package/{dist/schema → schema}/DatabaseTable.d.ts +1 -1
- package/{dist/schema → schema}/DatabaseTable.js +2 -1
- package/{dist/schema → schema}/SchemaComparator.d.ts +3 -1
- package/{dist/schema → schema}/SchemaComparator.js +58 -10
- package/{dist/schema → schema}/SchemaGenerator.d.ts +10 -8
- package/{dist/schema → schema}/SchemaGenerator.js +81 -28
- package/{dist/schema → schema}/SchemaHelper.d.ts +9 -4
- package/{dist/schema → schema}/SchemaHelper.js +46 -8
- package/{dist/schema → schema}/index.d.ts +0 -0
- package/{dist/schema → schema}/index.js +5 -1
- package/{dist/typings.d.ts → typings.d.ts} +7 -3
- package/{dist/typings.js → typings.js} +0 -0
- package/CHANGELOG.md +0 -661
- package/dist/AbstractSqlDriver.d.ts +0 -55
- package/dist/LICENSE +0 -21
- package/dist/package.json +0 -99
|
@@ -30,7 +30,7 @@ class DatabaseTable {
|
|
|
30
30
|
getChecks() {
|
|
31
31
|
return this.checks;
|
|
32
32
|
}
|
|
33
|
-
init(cols, indexes, checks, pks, fks, enums) {
|
|
33
|
+
init(cols, indexes = [], checks = [], pks, fks = {}, enums = {}) {
|
|
34
34
|
this.indexes = indexes;
|
|
35
35
|
this.checks = checks;
|
|
36
36
|
this.foreignKeys = fks;
|
|
@@ -82,6 +82,7 @@ class DatabaseTable {
|
|
|
82
82
|
enumItems: prop.items?.every(core_1.Utils.isString) ? prop.items : undefined,
|
|
83
83
|
comment: prop.comment,
|
|
84
84
|
extra: prop.extra,
|
|
85
|
+
ignoreSchemaChanges: prop.ignoreSchemaChanges,
|
|
85
86
|
};
|
|
86
87
|
(_a = this.columns[field]).unsigned || (_a.unsigned = this.columns[field].autoincrement);
|
|
87
88
|
const defaultValue = this.platform.getSchemaHelper().normalizeDefaultValue(prop.defaultRaw, prop.length);
|
|
@@ -8,6 +8,7 @@ import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
|
8
8
|
export declare class SchemaComparator {
|
|
9
9
|
private readonly platform;
|
|
10
10
|
private readonly helper;
|
|
11
|
+
private readonly logger;
|
|
11
12
|
constructor(platform: AbstractSqlPlatform);
|
|
12
13
|
/**
|
|
13
14
|
* Returns a SchemaDifference object containing the differences between the schemas fromSchema and toSchema.
|
|
@@ -37,7 +38,7 @@ export declare class SchemaComparator {
|
|
|
37
38
|
* Returns the difference between the columns
|
|
38
39
|
* If there are differences this method returns field2, otherwise the boolean false.
|
|
39
40
|
*/
|
|
40
|
-
diffColumn(column1: Column, column2: Column): Set<string>;
|
|
41
|
+
diffColumn(column1: Column, column2: Column, tableName?: string): Set<string>;
|
|
41
42
|
diffEnumItems(items1?: string[], items2?: string[]): boolean;
|
|
42
43
|
diffComment(comment1?: string, comment2?: string): boolean;
|
|
43
44
|
/**
|
|
@@ -52,4 +53,5 @@ export declare class SchemaComparator {
|
|
|
52
53
|
diffCheck(check1: Check, check2: Check): boolean;
|
|
53
54
|
hasSameDefaultValue(from: Column, to: Column): boolean;
|
|
54
55
|
private mapColumnToProperty;
|
|
56
|
+
private log;
|
|
55
57
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SchemaComparator = void 0;
|
|
4
|
+
const util_1 = require("util");
|
|
4
5
|
const core_1 = require("@mikro-orm/core");
|
|
5
6
|
/**
|
|
6
7
|
* Compares two Schemas and return an instance of SchemaDifference.
|
|
@@ -9,6 +10,7 @@ class SchemaComparator {
|
|
|
9
10
|
constructor(platform) {
|
|
10
11
|
this.platform = platform;
|
|
11
12
|
this.helper = this.platform.getSchemaHelper();
|
|
13
|
+
this.logger = this.platform.getConfig().getLogger();
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Returns a SchemaDifference object containing the differences between the schemas fromSchema and toSchema.
|
|
@@ -105,18 +107,22 @@ class SchemaComparator {
|
|
|
105
107
|
renamedColumns: {},
|
|
106
108
|
renamedIndexes: {},
|
|
107
109
|
fromTable,
|
|
110
|
+
toTable,
|
|
108
111
|
};
|
|
109
112
|
if (this.diffComment(fromTable.comment, toTable.comment)) {
|
|
110
113
|
tableDifferences.changedComment = toTable.comment;
|
|
114
|
+
this.log(`table comment changed for ${tableDifferences.name}`, { fromTableComment: fromTable.comment, toTableComment: toTable.comment });
|
|
111
115
|
}
|
|
112
116
|
const fromTableColumns = fromTable.getColumns();
|
|
113
117
|
const toTableColumns = toTable.getColumns();
|
|
118
|
+
const tableName = (toTable.schema ? toTable.schema + '.' : '') + toTable.name;
|
|
114
119
|
// See if all the columns in "from" table exist in "to" table
|
|
115
120
|
for (const column of toTableColumns) {
|
|
116
121
|
if (fromTable.hasColumn(column.name)) {
|
|
117
122
|
continue;
|
|
118
123
|
}
|
|
119
124
|
tableDifferences.addedColumns[column.name] = column;
|
|
125
|
+
this.log(`column ${tableDifferences.name}.${column.name} of type ${column.type} added`);
|
|
120
126
|
changes++;
|
|
121
127
|
}
|
|
122
128
|
/* See if there are any removed columns in "to" table */
|
|
@@ -124,11 +130,12 @@ class SchemaComparator {
|
|
|
124
130
|
// See if column is removed in "to" table.
|
|
125
131
|
if (!toTable.hasColumn(column.name)) {
|
|
126
132
|
tableDifferences.removedColumns[column.name] = column;
|
|
133
|
+
this.log(`column ${tableDifferences.name}.${column.name} removed`);
|
|
127
134
|
changes++;
|
|
128
135
|
continue;
|
|
129
136
|
}
|
|
130
137
|
// See if column has changed properties in "to" table.
|
|
131
|
-
const changedProperties = this.diffColumn(column, toTable.getColumn(column.name));
|
|
138
|
+
const changedProperties = this.diffColumn(column, toTable.getColumn(column.name), tableName);
|
|
132
139
|
if (changedProperties.size === 0) {
|
|
133
140
|
continue;
|
|
134
141
|
}
|
|
@@ -138,6 +145,7 @@ class SchemaComparator {
|
|
|
138
145
|
column: toTable.getColumn(column.name),
|
|
139
146
|
changedProperties,
|
|
140
147
|
};
|
|
148
|
+
this.log(`column ${tableDifferences.name}.${column.name} changed`, { changedProperties });
|
|
141
149
|
changes++;
|
|
142
150
|
}
|
|
143
151
|
this.detectColumnRenamings(tableDifferences);
|
|
@@ -149,6 +157,7 @@ class SchemaComparator {
|
|
|
149
157
|
continue;
|
|
150
158
|
}
|
|
151
159
|
tableDifferences.addedIndexes[index.keyName] = index;
|
|
160
|
+
this.log(`index ${index.keyName} added to table ${tableDifferences.name}`, { index });
|
|
152
161
|
changes++;
|
|
153
162
|
}
|
|
154
163
|
// See if there are any removed indexes in "to" table
|
|
@@ -156,6 +165,7 @@ class SchemaComparator {
|
|
|
156
165
|
// See if index is removed in "to" table.
|
|
157
166
|
if ((index.primary && !toTable.hasPrimaryKey()) || !index.primary && !toTable.hasIndex(index.keyName)) {
|
|
158
167
|
tableDifferences.removedIndexes[index.keyName] = index;
|
|
168
|
+
this.log(`index ${index.keyName} removed from table ${tableDifferences.name}`);
|
|
159
169
|
changes++;
|
|
160
170
|
continue;
|
|
161
171
|
}
|
|
@@ -165,6 +175,7 @@ class SchemaComparator {
|
|
|
165
175
|
continue;
|
|
166
176
|
}
|
|
167
177
|
tableDifferences.changedIndexes[index.keyName] = toTableIndex;
|
|
178
|
+
this.log(`index ${index.keyName} changed in table ${tableDifferences.name}`, { fromTableIndex: index, toTableIndex });
|
|
168
179
|
changes++;
|
|
169
180
|
}
|
|
170
181
|
this.detectIndexRenamings(tableDifferences);
|
|
@@ -176,12 +187,14 @@ class SchemaComparator {
|
|
|
176
187
|
continue;
|
|
177
188
|
}
|
|
178
189
|
tableDifferences.addedChecks[check.name] = check;
|
|
190
|
+
this.log(`check constraint ${check.name} added to table ${tableDifferences.name}`, { check });
|
|
179
191
|
changes++;
|
|
180
192
|
}
|
|
181
193
|
// See if there are any removed checks in "to" table
|
|
182
194
|
for (const check of fromTableChecks) {
|
|
183
195
|
if (!toTable.hasCheck(check.name)) {
|
|
184
196
|
tableDifferences.removedChecks[check.name] = check;
|
|
197
|
+
this.log(`check constraint ${check.name} removed from table ${tableDifferences.name}`);
|
|
185
198
|
changes++;
|
|
186
199
|
continue;
|
|
187
200
|
}
|
|
@@ -190,6 +203,7 @@ class SchemaComparator {
|
|
|
190
203
|
if (!this.diffCheck(check, toTableCheck)) {
|
|
191
204
|
continue;
|
|
192
205
|
}
|
|
206
|
+
this.log(`check constraint ${check.name} changed in table ${tableDifferences.name}`, { fromTableCheck: check, toTableCheck });
|
|
193
207
|
tableDifferences.changedChecks[check.name] = toTableCheck;
|
|
194
208
|
changes++;
|
|
195
209
|
}
|
|
@@ -202,6 +216,7 @@ class SchemaComparator {
|
|
|
202
216
|
delete toForeignKeys[toConstraint.constraintName];
|
|
203
217
|
}
|
|
204
218
|
else if (fromConstraint.constraintName.toLowerCase() === toConstraint.constraintName.toLowerCase()) {
|
|
219
|
+
this.log(`FK constraint ${fromConstraint.constraintName} changed in table ${tableDifferences.name}`, { fromConstraint, toConstraint });
|
|
205
220
|
tableDifferences.changedForeignKeys[toConstraint.constraintName] = toConstraint;
|
|
206
221
|
changes++;
|
|
207
222
|
delete fromForeignKeys[fromConstraint.constraintName];
|
|
@@ -211,10 +226,12 @@ class SchemaComparator {
|
|
|
211
226
|
}
|
|
212
227
|
for (const fromConstraint of Object.values(fromForeignKeys)) {
|
|
213
228
|
tableDifferences.removedForeignKeys[fromConstraint.constraintName] = fromConstraint;
|
|
229
|
+
this.log(`FK constraint ${fromConstraint.constraintName} removed from table ${tableDifferences.name}`);
|
|
214
230
|
changes++;
|
|
215
231
|
}
|
|
216
232
|
for (const toConstraint of Object.values(toForeignKeys)) {
|
|
217
233
|
tableDifferences.addedForeignKeys[toConstraint.constraintName] = toConstraint;
|
|
234
|
+
this.log(`FK constraint ${toConstraint.constraintName} added from table ${tableDifferences.name}`, { constraint: toConstraint });
|
|
218
235
|
changes++;
|
|
219
236
|
}
|
|
220
237
|
return changes ? tableDifferences : false;
|
|
@@ -249,6 +266,7 @@ class SchemaComparator {
|
|
|
249
266
|
tableDifferences.renamedColumns[removedColumnName] = addedColumn;
|
|
250
267
|
delete tableDifferences.addedColumns[addedColumnName];
|
|
251
268
|
delete tableDifferences.removedColumns[removedColumnName];
|
|
269
|
+
this.log(`renamed column detected in table ${tableDifferences.name}`, { old: removedColumnName, new: addedColumnName });
|
|
252
270
|
}
|
|
253
271
|
}
|
|
254
272
|
/**
|
|
@@ -282,6 +300,7 @@ class SchemaComparator {
|
|
|
282
300
|
tableDifferences.renamedIndexes[removedIndexName] = addedIndex;
|
|
283
301
|
delete tableDifferences.addedIndexes[addedIndexName];
|
|
284
302
|
delete tableDifferences.removedIndexes[removedIndexName];
|
|
303
|
+
this.log(`renamed index detected in table ${tableDifferences.name}`, { old: removedIndexName, new: addedIndexName });
|
|
285
304
|
}
|
|
286
305
|
}
|
|
287
306
|
diffForeignKey(key1, key2) {
|
|
@@ -294,7 +313,10 @@ class SchemaComparator {
|
|
|
294
313
|
if (key1.referencedTableName !== key2.referencedTableName) {
|
|
295
314
|
return true;
|
|
296
315
|
}
|
|
297
|
-
const
|
|
316
|
+
const defaultRule = ['restrict', 'no action'];
|
|
317
|
+
const rule = (key, method) => {
|
|
318
|
+
return (key[method] ?? defaultRule[0]).toLowerCase().replace(defaultRule[1], defaultRule[0]);
|
|
319
|
+
};
|
|
298
320
|
const compare = (method) => rule(key1, method) === rule(key2, method);
|
|
299
321
|
return !compare('updateRule') || !compare('deleteRule');
|
|
300
322
|
}
|
|
@@ -302,34 +324,53 @@ class SchemaComparator {
|
|
|
302
324
|
* Returns the difference between the columns
|
|
303
325
|
* If there are differences this method returns field2, otherwise the boolean false.
|
|
304
326
|
*/
|
|
305
|
-
diffColumn(column1, column2) {
|
|
327
|
+
diffColumn(column1, column2, tableName) {
|
|
306
328
|
const changedProperties = new Set();
|
|
307
329
|
const prop1 = this.mapColumnToProperty({ ...column1, autoincrement: false });
|
|
308
330
|
const prop2 = this.mapColumnToProperty({ ...column2, autoincrement: false });
|
|
309
|
-
const columnType1 = column1.mappedType.getColumnType(prop1, this.platform);
|
|
310
|
-
const columnType2 = column2.mappedType.getColumnType(prop2, this.platform);
|
|
311
|
-
|
|
331
|
+
const columnType1 = column1.mappedType.getColumnType(prop1, this.platform).toLowerCase();
|
|
332
|
+
const columnType2 = column2.mappedType.getColumnType(prop2, this.platform).toLowerCase();
|
|
333
|
+
const log = (msg, params) => {
|
|
334
|
+
if (tableName) {
|
|
335
|
+
const copy = core_1.Utils.copy(params);
|
|
336
|
+
core_1.Utils.dropUndefinedProperties(copy);
|
|
337
|
+
this.log(msg, copy);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
if (columnType1 !== columnType2 &&
|
|
341
|
+
!(column1.ignoreSchemaChanges?.includes('type') ||
|
|
342
|
+
column2.ignoreSchemaChanges?.includes('type'))) {
|
|
343
|
+
log(`'type' changed for column ${tableName}.${column1.name}`, { columnType1, columnType2 });
|
|
312
344
|
changedProperties.add('type');
|
|
313
345
|
}
|
|
314
346
|
if (column1.nullable !== column2.nullable) {
|
|
347
|
+
log(`'nullable' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
315
348
|
changedProperties.add('nullable');
|
|
316
349
|
}
|
|
317
350
|
if (!!column1.autoincrement !== !!column2.autoincrement) {
|
|
351
|
+
log(`'autoincrement' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
318
352
|
changedProperties.add('autoincrement');
|
|
319
353
|
}
|
|
320
354
|
if (column1.unsigned !== column2.unsigned && this.platform.supportsUnsigned()) {
|
|
355
|
+
log(`'unsigned' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
321
356
|
changedProperties.add('unsigned');
|
|
322
357
|
}
|
|
323
358
|
if (!this.hasSameDefaultValue(column1, column2)) {
|
|
359
|
+
log(`'default' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
324
360
|
changedProperties.add('default');
|
|
325
361
|
}
|
|
326
362
|
if (this.diffComment(column1.comment, column2.comment)) {
|
|
363
|
+
log(`'comment' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
327
364
|
changedProperties.add('comment');
|
|
328
365
|
}
|
|
329
366
|
if (this.diffEnumItems(column1.enumItems, column2.enumItems)) {
|
|
367
|
+
log(`'enumItems' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
330
368
|
changedProperties.add('enumItems');
|
|
331
369
|
}
|
|
332
|
-
if ((column1.extra || '').toLowerCase() !== (column2.extra || '').toLowerCase()
|
|
370
|
+
if ((column1.extra || '').toLowerCase() !== (column2.extra || '').toLowerCase() &&
|
|
371
|
+
!(column1.ignoreSchemaChanges?.includes('extra') ||
|
|
372
|
+
column2.ignoreSchemaChanges?.includes('extra'))) {
|
|
373
|
+
log(`'extra' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
333
374
|
changedProperties.add('extra');
|
|
334
375
|
}
|
|
335
376
|
return changedProperties;
|
|
@@ -347,8 +388,8 @@ class SchemaComparator {
|
|
|
347
388
|
* Compares index1 with index2 and returns index2 if there are any differences or false in case there are no differences.
|
|
348
389
|
*/
|
|
349
390
|
diffIndex(index1, index2) {
|
|
350
|
-
// if one of them is a custom expression, compare only by name
|
|
351
|
-
if (index1.expression || index2.expression) {
|
|
391
|
+
// if one of them is a custom expression or full text index, compare only by name
|
|
392
|
+
if (index1.expression || index2.expression || index1.type === 'fulltext' || index2.type === 'fulltext') {
|
|
352
393
|
return index1.keyName !== index2.keyName;
|
|
353
394
|
}
|
|
354
395
|
return !this.isIndexFulfilledBy(index1, index2) || !this.isIndexFulfilledBy(index2, index1);
|
|
@@ -384,7 +425,8 @@ class SchemaComparator {
|
|
|
384
425
|
return index1.primary === index2.primary && index1.unique === index2.unique;
|
|
385
426
|
}
|
|
386
427
|
diffCheck(check1, check2) {
|
|
387
|
-
|
|
428
|
+
const unquote = (str) => str?.replace(/['"`]/g, '');
|
|
429
|
+
return unquote(check1.expression) !== unquote(check2.expression);
|
|
388
430
|
}
|
|
389
431
|
hasSameDefaultValue(from, to) {
|
|
390
432
|
if (from.default == null || from.default.toString().toLowerCase() === 'null' || from.default.toString().startsWith('nextval(')) {
|
|
@@ -423,5 +465,11 @@ class SchemaComparator {
|
|
|
423
465
|
scale: match ? +match[2] : column.scale,
|
|
424
466
|
};
|
|
425
467
|
}
|
|
468
|
+
log(message, params) {
|
|
469
|
+
if (params) {
|
|
470
|
+
message += ' ' + (0, util_1.inspect)(params);
|
|
471
|
+
}
|
|
472
|
+
this.logger.log('schema', message);
|
|
473
|
+
}
|
|
426
474
|
}
|
|
427
475
|
exports.SchemaComparator = SchemaComparator;
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
+
import type { MikroORM } from '@mikro-orm/core';
|
|
1
2
|
import { AbstractSchemaGenerator } from '@mikro-orm/core';
|
|
2
3
|
import type { SchemaDifference } from '../typings';
|
|
3
4
|
import { DatabaseSchema } from './DatabaseSchema';
|
|
4
5
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
5
|
-
import { SqlEntityManager } from '../SqlEntityManager';
|
|
6
6
|
/**
|
|
7
7
|
* Should be renamed to `SqlSchemaGenerator` in v6
|
|
8
8
|
*/
|
|
9
9
|
export declare class SchemaGenerator extends AbstractSchemaGenerator<AbstractSqlDriver> {
|
|
10
10
|
private readonly helper;
|
|
11
|
-
private readonly knex;
|
|
12
11
|
private readonly options;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
constructor(em: SqlEntityManager);
|
|
12
|
+
protected lastEnsuredDatabase?: string;
|
|
13
|
+
static register(orm: MikroORM): void;
|
|
14
|
+
/** @deprecated use `dropSchema` and `createSchema` commands respectively */
|
|
17
15
|
generate(): Promise<string>;
|
|
18
16
|
createSchema(options?: {
|
|
19
17
|
wrap?: boolean;
|
|
@@ -34,6 +32,10 @@ export declare class SchemaGenerator extends AbstractSchemaGenerator<AbstractSql
|
|
|
34
32
|
dropDb?: boolean;
|
|
35
33
|
schema?: string;
|
|
36
34
|
}): Promise<void>;
|
|
35
|
+
clearDatabase(options?: {
|
|
36
|
+
schema?: string;
|
|
37
|
+
truncate?: boolean;
|
|
38
|
+
}): Promise<void>;
|
|
37
39
|
getDropSchemaSQL(options?: {
|
|
38
40
|
wrap?: boolean;
|
|
39
41
|
dropMigrationsTable?: boolean;
|
|
@@ -86,7 +88,7 @@ export declare class SchemaGenerator extends AbstractSchemaGenerator<AbstractSql
|
|
|
86
88
|
dropDatabase(name: string): Promise<void>;
|
|
87
89
|
execute(sql: string, options?: {
|
|
88
90
|
wrap?: boolean;
|
|
89
|
-
}): Promise<
|
|
91
|
+
}): Promise<undefined>;
|
|
90
92
|
private wrapSchema;
|
|
91
93
|
private createSchemaBuilder;
|
|
92
94
|
private createTable;
|
|
@@ -95,7 +97,7 @@ export declare class SchemaGenerator extends AbstractSchemaGenerator<AbstractSql
|
|
|
95
97
|
private createCheck;
|
|
96
98
|
private dropCheck;
|
|
97
99
|
private dropTable;
|
|
98
|
-
private configureColumn;
|
|
99
100
|
private createForeignKeys;
|
|
100
101
|
private dump;
|
|
102
|
+
private get knex();
|
|
101
103
|
}
|
|
@@ -4,20 +4,19 @@ exports.SchemaGenerator = void 0;
|
|
|
4
4
|
const core_1 = require("@mikro-orm/core");
|
|
5
5
|
const DatabaseSchema_1 = require("./DatabaseSchema");
|
|
6
6
|
const SchemaComparator_1 = require("./SchemaComparator");
|
|
7
|
-
const SqlEntityManager_1 = require("../SqlEntityManager");
|
|
8
7
|
/**
|
|
9
8
|
* Should be renamed to `SqlSchemaGenerator` in v6
|
|
10
9
|
*/
|
|
11
10
|
class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
constructor(driver) {
|
|
16
|
-
super(driver instanceof SqlEntityManager_1.SqlEntityManager ? driver.getDriver() : driver);
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
17
13
|
this.helper = this.platform.getSchemaHelper();
|
|
18
|
-
this.knex = this.connection.getKnex();
|
|
19
14
|
this.options = this.config.get('schemaGenerator');
|
|
20
15
|
}
|
|
16
|
+
static register(orm) {
|
|
17
|
+
orm.config.registerExtension('@mikro-orm/schema-generator', new SchemaGenerator(orm.em));
|
|
18
|
+
}
|
|
19
|
+
/** @deprecated use `dropSchema` and `createSchema` commands respectively */
|
|
21
20
|
async generate() {
|
|
22
21
|
const [dropSchema, createSchema] = await Promise.all([
|
|
23
22
|
this.getDropSchemaSQL({ wrap: false }),
|
|
@@ -35,7 +34,11 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
35
34
|
*/
|
|
36
35
|
async ensureDatabase() {
|
|
37
36
|
const dbName = this.config.get('dbName');
|
|
37
|
+
if (this.lastEnsuredDatabase === dbName) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
38
40
|
const exists = await this.helper.databaseExists(this.connection, dbName);
|
|
41
|
+
this.lastEnsuredDatabase = dbName;
|
|
39
42
|
if (!exists) {
|
|
40
43
|
this.config.set('dbName', this.helper.getManagementDbName());
|
|
41
44
|
await this.driver.reconnect();
|
|
@@ -48,7 +51,8 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
48
51
|
}
|
|
49
52
|
getTargetSchema(schema) {
|
|
50
53
|
const metadata = this.getOrderedMetadata(schema);
|
|
51
|
-
|
|
54
|
+
const schemaName = schema ?? this.config.get('schema') ?? this.platform.getDefaultSchemaName();
|
|
55
|
+
return DatabaseSchema_1.DatabaseSchema.fromMetadata(metadata, this.platform, this.config, schemaName);
|
|
52
56
|
}
|
|
53
57
|
async getCreateSchemaSQL(options = {}) {
|
|
54
58
|
const wrap = options.wrap ?? this.options.disableForeignKeys;
|
|
@@ -69,7 +73,6 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
69
73
|
return this.wrapSchema(ret, { wrap });
|
|
70
74
|
}
|
|
71
75
|
async dropSchema(options = {}) {
|
|
72
|
-
options.wrap ?? (options.wrap = true);
|
|
73
76
|
if (options.dropDb) {
|
|
74
77
|
const name = this.config.get('dbName');
|
|
75
78
|
return this.dropDatabase(name);
|
|
@@ -77,10 +80,44 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
77
80
|
const sql = await this.getDropSchemaSQL(options);
|
|
78
81
|
await this.execute(sql);
|
|
79
82
|
}
|
|
83
|
+
async clearDatabase(options) {
|
|
84
|
+
// truncate by default, so no value is considered as true
|
|
85
|
+
/* istanbul ignore if */
|
|
86
|
+
if (options?.truncate === false) {
|
|
87
|
+
return super.clearDatabase(options);
|
|
88
|
+
}
|
|
89
|
+
await this.execute(this.helper.disableForeignKeysSQL());
|
|
90
|
+
for (const meta of this.getOrderedMetadata(options?.schema).reverse()) {
|
|
91
|
+
await this.driver.createQueryBuilder(meta.className, this.em?.getTransactionContext(), 'write', false)
|
|
92
|
+
.withSchema(options?.schema)
|
|
93
|
+
.truncate();
|
|
94
|
+
}
|
|
95
|
+
await this.execute(this.helper.enableForeignKeysSQL());
|
|
96
|
+
if (this.em) {
|
|
97
|
+
const allowGlobalContext = this.config.get('allowGlobalContext');
|
|
98
|
+
this.config.set('allowGlobalContext', true);
|
|
99
|
+
this.em.clear();
|
|
100
|
+
this.config.set('allowGlobalContext', allowGlobalContext);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
80
103
|
async getDropSchemaSQL(options = {}) {
|
|
104
|
+
await this.ensureDatabase();
|
|
81
105
|
const wrap = options.wrap ?? this.options.disableForeignKeys;
|
|
82
106
|
const metadata = this.getOrderedMetadata(options.schema).reverse();
|
|
107
|
+
const schema = await DatabaseSchema_1.DatabaseSchema.create(this.connection, this.platform, this.config, options.schema);
|
|
83
108
|
let ret = '';
|
|
109
|
+
// remove FKs explicitly if we can't use cascading statement and we don't disable FK checks (we need this for circular relations)
|
|
110
|
+
for (const meta of metadata) {
|
|
111
|
+
const table = schema.getTable(meta.tableName);
|
|
112
|
+
if (!this.platform.usesCascadeStatement() && table && !wrap) {
|
|
113
|
+
for (const fk of Object.values(table.getForeignKeys())) {
|
|
114
|
+
const builder = this.createSchemaBuilder(table.schema).alterTable(table.name, tbl => {
|
|
115
|
+
tbl.dropForeign(fk.columnNames, fk.constraintName);
|
|
116
|
+
});
|
|
117
|
+
ret += await this.dump(builder, '\n');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
84
121
|
for (const meta of metadata) {
|
|
85
122
|
ret += await this.dump(this.dropTable(meta.collection, this.getSchemaName(meta, options)), '\n');
|
|
86
123
|
}
|
|
@@ -90,20 +127,23 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
90
127
|
return this.wrapSchema(ret + '\n', { wrap });
|
|
91
128
|
}
|
|
92
129
|
getSchemaName(meta, options) {
|
|
130
|
+
const schemaName = options.schema ?? this.config.get('schema');
|
|
93
131
|
/* istanbul ignore next */
|
|
94
|
-
return meta.schema === '*' ?
|
|
132
|
+
return meta.schema && meta.schema === '*' ? schemaName : (meta.schema ?? schemaName);
|
|
95
133
|
}
|
|
96
134
|
async updateSchema(options = {}) {
|
|
97
135
|
const sql = await this.getUpdateSchemaSQL(options);
|
|
98
136
|
await this.execute(sql);
|
|
99
137
|
}
|
|
100
138
|
async getUpdateSchemaSQL(options = {}) {
|
|
139
|
+
await this.ensureDatabase();
|
|
101
140
|
const { fromSchema, toSchema } = await this.prepareSchemaForComparison(options);
|
|
102
141
|
const comparator = new SchemaComparator_1.SchemaComparator(this.platform);
|
|
103
142
|
const diffUp = comparator.compare(fromSchema, toSchema);
|
|
104
143
|
return this.diffToSQL(diffUp, options);
|
|
105
144
|
}
|
|
106
145
|
async getUpdateSchemaMigrationSQL(options = {}) {
|
|
146
|
+
await this.ensureDatabase();
|
|
107
147
|
const { fromSchema, toSchema } = await this.prepareSchemaForComparison(options);
|
|
108
148
|
const comparator = new SchemaComparator_1.SchemaComparator(this.platform);
|
|
109
149
|
const diffUp = comparator.compare(fromSchema, toSchema);
|
|
@@ -240,7 +280,7 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
240
280
|
}
|
|
241
281
|
for (const column of Object.values(diff.addedColumns)) {
|
|
242
282
|
const col = this.helper.createTableColumn(table, column, diff.fromTable);
|
|
243
|
-
this.configureColumn(column, col);
|
|
283
|
+
this.helper.configureColumn(column, col, this.knex);
|
|
244
284
|
const foreignKey = Object.values(diff.addedForeignKeys).find(fk => fk.columnNames.length === 1 && fk.columnNames[0] === column.name);
|
|
245
285
|
if (foreignKey && this.options.createForeignKeyConstraints) {
|
|
246
286
|
delete diff.addedForeignKeys[foreignKey.constraintName];
|
|
@@ -262,7 +302,7 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
262
302
|
continue;
|
|
263
303
|
}
|
|
264
304
|
const col = this.helper.createTableColumn(table, column, diff.fromTable, changedProperties).alter();
|
|
265
|
-
this.configureColumn(column, col, changedProperties);
|
|
305
|
+
this.helper.configureColumn(column, col, this.knex, changedProperties);
|
|
266
306
|
}
|
|
267
307
|
for (const { column } of Object.values(diff.changedColumns).filter(diff => diff.changedProperties.has('autoincrement'))) {
|
|
268
308
|
this.helper.pushTableQuery(table, this.helper.getAlterColumnAutoincrement(tableName, column));
|
|
@@ -274,7 +314,7 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
274
314
|
this.helper.pushTableQuery(table, this.helper.getChangeColumnCommentSQL(tableName, column));
|
|
275
315
|
}
|
|
276
316
|
for (const [oldColumnName, column] of Object.entries(diff.renamedColumns)) {
|
|
277
|
-
this.helper.pushTableQuery(table, this.helper.getRenameColumnSQL(tableName, oldColumnName, column));
|
|
317
|
+
this.helper.pushTableQuery(table, this.helper.getRenameColumnSQL(tableName, oldColumnName, column, schemaName));
|
|
278
318
|
}
|
|
279
319
|
for (const foreignKey of Object.values(diff.addedForeignKeys)) {
|
|
280
320
|
this.createForeignKey(table, foreignKey);
|
|
@@ -283,15 +323,15 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
283
323
|
this.createForeignKey(table, foreignKey);
|
|
284
324
|
}
|
|
285
325
|
for (const index of Object.values(diff.addedIndexes)) {
|
|
286
|
-
this.createIndex(table, index, diff.
|
|
326
|
+
this.createIndex(table, index, diff.toTable);
|
|
287
327
|
}
|
|
288
328
|
for (const index of Object.values(diff.changedIndexes)) {
|
|
289
|
-
this.createIndex(table, index, diff.
|
|
329
|
+
this.createIndex(table, index, diff.toTable, true);
|
|
290
330
|
}
|
|
291
331
|
for (const [oldIndexName, index] of Object.entries(diff.renamedIndexes)) {
|
|
292
332
|
if (index.unique) {
|
|
293
333
|
this.dropIndex(table, index, oldIndexName);
|
|
294
|
-
this.createIndex(table, index, diff.
|
|
334
|
+
this.createIndex(table, index, diff.toTable);
|
|
295
335
|
}
|
|
296
336
|
else {
|
|
297
337
|
this.helper.pushTableQuery(table, this.helper.getRenameIndexSQL(diff.name, index, oldIndexName));
|
|
@@ -304,7 +344,8 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
304
344
|
this.createCheck(table, check);
|
|
305
345
|
}
|
|
306
346
|
if ('changedComment' in diff) {
|
|
307
|
-
|
|
347
|
+
const comment = diff.changedComment ? this.platform.quoteValue(diff.changedComment).replace(/^'|'$/g, '') : '';
|
|
348
|
+
table.comment(comment);
|
|
308
349
|
}
|
|
309
350
|
}));
|
|
310
351
|
return ret;
|
|
@@ -325,9 +366,14 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
325
366
|
async execute(sql, options = {}) {
|
|
326
367
|
options.wrap ?? (options.wrap = false);
|
|
327
368
|
const lines = this.wrapSchema(sql, options).split('\n').filter(i => i.trim());
|
|
328
|
-
|
|
329
|
-
|
|
369
|
+
if (lines.length === 0) {
|
|
370
|
+
return;
|
|
330
371
|
}
|
|
372
|
+
if (this.platform.supportsMultipleStatements()) {
|
|
373
|
+
const query = lines.join('\n');
|
|
374
|
+
return void await this.driver.execute(query);
|
|
375
|
+
}
|
|
376
|
+
await core_1.Utils.runSerial(lines, line => this.driver.execute(line));
|
|
331
377
|
}
|
|
332
378
|
wrapSchema(sql, options = {}) {
|
|
333
379
|
options.wrap ?? (options.wrap = this.options.disableForeignKeys);
|
|
@@ -350,16 +396,18 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
350
396
|
return this.createSchemaBuilder(tableDef.schema).createTable(tableDef.name, table => {
|
|
351
397
|
tableDef.getColumns().forEach(column => {
|
|
352
398
|
const col = this.helper.createTableColumn(table, column, tableDef);
|
|
353
|
-
this.configureColumn(column, col);
|
|
399
|
+
this.helper.configureColumn(column, col, this.knex);
|
|
354
400
|
});
|
|
355
401
|
for (const index of tableDef.getIndexes()) {
|
|
356
|
-
|
|
402
|
+
const createPrimary = !tableDef.getColumns().some(c => c.autoincrement && c.primary) || this.helper.hasNonDefaultPrimaryKeyName(tableDef);
|
|
403
|
+
this.createIndex(table, index, tableDef, createPrimary);
|
|
357
404
|
}
|
|
358
405
|
for (const check of tableDef.getChecks()) {
|
|
359
406
|
this.createCheck(table, check);
|
|
360
407
|
}
|
|
361
408
|
if (tableDef.comment) {
|
|
362
|
-
|
|
409
|
+
const comment = this.platform.quoteValue(tableDef.comment).replace(/^'|'$/g, '');
|
|
410
|
+
table.comment(comment);
|
|
363
411
|
}
|
|
364
412
|
if (!this.helper.supportsSchemaConstraints()) {
|
|
365
413
|
for (const fk of Object.values(tableDef.getForeignKeys())) {
|
|
@@ -369,13 +417,12 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
369
417
|
this.helper.finalizeTable(table, this.config.get('charset'), this.config.get('collate'));
|
|
370
418
|
});
|
|
371
419
|
}
|
|
372
|
-
createIndex(table, index,
|
|
420
|
+
createIndex(table, index, tableDef, createPrimary = false) {
|
|
373
421
|
if (index.primary && !createPrimary) {
|
|
374
422
|
return;
|
|
375
423
|
}
|
|
376
424
|
if (index.primary) {
|
|
377
|
-
|
|
378
|
-
const keyName = tableName.includes('.') ? tableName.split('.').pop() + '_pkey' : undefined;
|
|
425
|
+
const keyName = this.helper.hasNonDefaultPrimaryKeyName(tableDef) ? index.keyName : undefined;
|
|
379
426
|
table.primary(index.columnNames, keyName);
|
|
380
427
|
}
|
|
381
428
|
else if (index.unique) {
|
|
@@ -384,6 +431,12 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
384
431
|
else if (index.expression) {
|
|
385
432
|
this.helper.pushTableQuery(table, index.expression);
|
|
386
433
|
}
|
|
434
|
+
else if (index.type === 'fulltext') {
|
|
435
|
+
const columns = index.columnNames.map(name => ({ name, type: tableDef.getColumn(name).type }));
|
|
436
|
+
if (this.platform.supportsCreatingFullTextIndex()) {
|
|
437
|
+
this.helper.pushTableQuery(table, this.platform.getFullTextIndexExpression(index.keyName, tableDef.schema, tableDef.name, columns));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
387
440
|
else {
|
|
388
441
|
table.index(index.columnNames, index.keyName, index.type);
|
|
389
442
|
}
|
|
@@ -412,9 +465,6 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
412
465
|
}
|
|
413
466
|
return builder;
|
|
414
467
|
}
|
|
415
|
-
configureColumn(column, col, changedProperties) {
|
|
416
|
-
return this.helper.configureColumn(column, col, this.knex, changedProperties);
|
|
417
|
-
}
|
|
418
468
|
createForeignKeys(table, tableDef, schema) {
|
|
419
469
|
if (!this.helper.supportsSchemaConstraints()) {
|
|
420
470
|
return;
|
|
@@ -433,5 +483,8 @@ class SchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
433
483
|
const tmp = dump.replace(/pragma table_.+/ig, '').replace(/\n\n+/g, '\n').trim();
|
|
434
484
|
return tmp ? tmp + append : '';
|
|
435
485
|
}
|
|
486
|
+
get knex() {
|
|
487
|
+
return this.connection.getKnex();
|
|
488
|
+
}
|
|
436
489
|
}
|
|
437
490
|
exports.SchemaGenerator = SchemaGenerator;
|
|
@@ -2,8 +2,9 @@ import type { Knex } from 'knex';
|
|
|
2
2
|
import type { Connection, Dictionary } from '@mikro-orm/core';
|
|
3
3
|
import type { AbstractSqlConnection } from '../AbstractSqlConnection';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
5
|
-
import type { Check, Column, Index, TableDifference } from '../typings';
|
|
5
|
+
import type { Check, Column, Index, Table, TableDifference } from '../typings';
|
|
6
6
|
import type { DatabaseTable } from './DatabaseTable';
|
|
7
|
+
import type { DatabaseSchema } from './DatabaseSchema';
|
|
7
8
|
export declare abstract class SchemaHelper {
|
|
8
9
|
protected readonly platform: AbstractSqlPlatform;
|
|
9
10
|
constructor(platform: AbstractSqlPlatform);
|
|
@@ -13,23 +14,27 @@ export declare abstract class SchemaHelper {
|
|
|
13
14
|
getSchemaEnd(): string;
|
|
14
15
|
finalizeTable(table: Knex.TableBuilder, charset: string, collate?: string): void;
|
|
15
16
|
supportsSchemaConstraints(): boolean;
|
|
16
|
-
getPrimaryKeys(connection: AbstractSqlConnection, indexes: Index[], tableName: string, schemaName?: string): Promise<string[]>;
|
|
17
|
+
getPrimaryKeys(connection: AbstractSqlConnection, indexes: Index[] | undefined, tableName: string, schemaName?: string): Promise<string[]>;
|
|
17
18
|
getForeignKeys(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<Dictionary>;
|
|
19
|
+
protected getTableKey(t: Table): string;
|
|
18
20
|
getEnumDefinitions(connection: AbstractSqlConnection, checks: Check[], tableName: string, schemaName?: string): Promise<Dictionary<string[]>>;
|
|
21
|
+
loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[]): Promise<void>;
|
|
19
22
|
getListTablesSQL(schemaName?: string): string;
|
|
20
|
-
getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column): string;
|
|
23
|
+
getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column, schemaName?: string): string;
|
|
21
24
|
getCreateIndexSQL(tableName: string, index: Index): string;
|
|
22
25
|
getDropIndexSQL(tableName: string, index: Index): string;
|
|
23
26
|
getRenameIndexSQL(tableName: string, index: Index, oldIndexName: string): string;
|
|
27
|
+
hasNonDefaultPrimaryKeyName(table: DatabaseTable): boolean;
|
|
24
28
|
createTableColumn(table: Knex.TableBuilder, column: Column, fromTable: DatabaseTable, changedProperties?: Set<string>): Knex.ColumnBuilder;
|
|
25
29
|
configureColumn(column: Column, col: Knex.ColumnBuilder, knex: Knex, changedProperties?: Set<string>): Knex.ColumnBuilder;
|
|
26
30
|
configureColumnDefault(column: Column, col: Knex.ColumnBuilder, knex: Knex, changedProperties?: Set<string>): Knex.ColumnBuilder;
|
|
27
31
|
getPreAlterTable(tableDiff: TableDifference, safe: boolean): string;
|
|
28
32
|
getAlterColumnAutoincrement(tableName: string, column: Column): string;
|
|
29
33
|
getChangeColumnCommentSQL(tableName: string, to: Column): string;
|
|
34
|
+
getNamespaces(connection: AbstractSqlConnection): Promise<string[]>;
|
|
30
35
|
getColumns(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<Column[]>;
|
|
31
36
|
getIndexes(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<Index[]>;
|
|
32
|
-
getChecks(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<Check[]>;
|
|
37
|
+
getChecks(connection: AbstractSqlConnection, tableName: string, schemaName?: string, columns?: Column[]): Promise<Check[]>;
|
|
33
38
|
protected mapIndexes(indexes: Index[]): Promise<Index[]>;
|
|
34
39
|
getForeignKeysSQL(tableName: string, schemaName?: string): string;
|
|
35
40
|
mapForeignKeys(fks: any[], tableName: string, schemaName?: string): Dictionary;
|