@mikro-orm/migrations 7.3.0-dev.16 → 7.3.0-dev.18
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/MigrationRunner.d.ts +5 -0
- package/MigrationRunner.js +47 -4
- package/Migrator.d.ts +1 -0
- package/Migrator.js +10 -2
- package/package.json +4 -4
package/MigrationRunner.d.ts
CHANGED
|
@@ -9,6 +9,11 @@ export declare class MigrationRunner {
|
|
|
9
9
|
protected readonly config: Configuration;
|
|
10
10
|
constructor(driver: AbstractSqlDriver, options: MigrationsOptions, config: Configuration);
|
|
11
11
|
run(migration: Migration, method: 'up' | 'down', afterRun?: (tx?: Transaction) => Promise<void>): Promise<void>;
|
|
12
|
+
/** Runs migrations with FK checks off, for drivers that ignore the switch inside a transaction (SQLite). */
|
|
13
|
+
runWithoutForeignKeys<T>(run: () => Promise<T>): Promise<T>;
|
|
14
|
+
private runWithForeignKeys;
|
|
15
|
+
private setForeignKeys;
|
|
16
|
+
private countForeignKeyViolations;
|
|
12
17
|
private resetSessionSchema;
|
|
13
18
|
setMasterMigration(trx: Transaction): void;
|
|
14
19
|
unsetMasterMigration(): void;
|
package/MigrationRunner.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Utils } from '@mikro-orm/core';
|
|
1
|
+
import { Utils, ValidationError } from '@mikro-orm/core';
|
|
2
2
|
/** Executes individual migration files within optional transaction contexts. */
|
|
3
3
|
export class MigrationRunner {
|
|
4
4
|
driver;
|
|
@@ -8,6 +8,7 @@ export class MigrationRunner {
|
|
|
8
8
|
#helper;
|
|
9
9
|
#masterTransaction;
|
|
10
10
|
#runSchema;
|
|
11
|
+
#foreignKeysOff = false;
|
|
11
12
|
constructor(driver, options, config) {
|
|
12
13
|
this.driver = driver;
|
|
13
14
|
this.options = options;
|
|
@@ -23,16 +24,23 @@ export class MigrationRunner {
|
|
|
23
24
|
if (this.#runSchema) {
|
|
24
25
|
throw new Error('Runtime schema (migrations.schema / migrator.up({ schema })) is only supported with transactional migrations');
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
await this.runWithForeignKeys(async () => {
|
|
28
|
+
const queries = await this.getQueries(migration, method);
|
|
29
|
+
await Utils.runSerial(queries, sql => this.driver.execute(sql));
|
|
30
|
+
await afterRun?.();
|
|
31
|
+
});
|
|
29
32
|
}
|
|
30
33
|
else {
|
|
31
34
|
await this.#connection.transactional(async (tx) => {
|
|
32
35
|
migration.setTransactionContext(tx);
|
|
36
|
+
const violations = await this.countForeignKeyViolations(tx);
|
|
33
37
|
try {
|
|
34
38
|
const queries = await this.getQueries(migration, method);
|
|
35
39
|
await Utils.runSerial(queries, sql => this.driver.execute(sql, undefined, 'all', tx));
|
|
40
|
+
const added = (await this.countForeignKeyViolations(tx)) - violations;
|
|
41
|
+
if (added > 0) {
|
|
42
|
+
throw new ValidationError(`Migration ${migration.name ?? migration.constructor.name} left ${added} rows that violate foreign keys`);
|
|
43
|
+
}
|
|
36
44
|
await afterRun?.(tx);
|
|
37
45
|
}
|
|
38
46
|
finally {
|
|
@@ -41,6 +49,41 @@ export class MigrationRunner {
|
|
|
41
49
|
}, { ctx: this.#masterTransaction });
|
|
42
50
|
}
|
|
43
51
|
}
|
|
52
|
+
/** Runs migrations with FK checks off, for drivers that ignore the switch inside a transaction (SQLite). */
|
|
53
|
+
async runWithoutForeignKeys(run) {
|
|
54
|
+
await this.setForeignKeys(false);
|
|
55
|
+
try {
|
|
56
|
+
return await run();
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await this.setForeignKeys(true);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// a migration outside a transaction gets no `foreign_key_check`, so it runs with FK checks on
|
|
63
|
+
async runWithForeignKeys(run) {
|
|
64
|
+
if (!this.#foreignKeysOff) {
|
|
65
|
+
return run();
|
|
66
|
+
}
|
|
67
|
+
await this.setForeignKeys(true);
|
|
68
|
+
try {
|
|
69
|
+
await run();
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await this.setForeignKeys(false);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async setForeignKeys(enabled) {
|
|
76
|
+
await this.driver.execute(enabled ? this.#helper.enableForeignKeysSQL() : this.#helper.disableForeignKeysSQL());
|
|
77
|
+
this.#foreignKeysOff = !enabled;
|
|
78
|
+
}
|
|
79
|
+
async countForeignKeyViolations(ctx) {
|
|
80
|
+
const sql = this.#helper.getForeignKeyCheckSQL();
|
|
81
|
+
// with FK checks on (caller-supplied transaction), the database enforces them itself
|
|
82
|
+
if (!this.#foreignKeysOff || !sql) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
return (await this.driver.execute(sql, undefined, 'all', ctx)).length;
|
|
86
|
+
}
|
|
44
87
|
async resetSessionSchema(ctx) {
|
|
45
88
|
if (!this.#runSchema) {
|
|
46
89
|
return;
|
package/Migrator.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export declare class Migrator extends AbstractMigrator<AbstractSqlDriver> {
|
|
|
29
29
|
*/
|
|
30
30
|
createInitial(path?: string, name?: string, blank?: boolean): Promise<MigrationResult>;
|
|
31
31
|
protected runMigrations(method: 'up' | 'down', options?: string | string[] | MigrateOptions): Promise<MigrationInfo[]>;
|
|
32
|
+
private runWithoutForeignKeys;
|
|
32
33
|
/** Whether the introspected schema differs from the snapshot in any way the comparator turns into SQL. */
|
|
33
34
|
private snapshotDiffers;
|
|
34
35
|
getStorage(): MigrationStorage;
|
package/Migrator.js
CHANGED
|
@@ -188,9 +188,9 @@ export class Migrator extends AbstractMigrator {
|
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
190
|
async runMigrations(method, options) {
|
|
191
|
-
const
|
|
191
|
+
const ctx = Utils.isObject(options) ? options.transaction : undefined;
|
|
192
|
+
const result = await this.runLocked(() => this.runWithoutForeignKeys(ctx, () => super.runMigrations(method, options)));
|
|
192
193
|
if (result.length > 0 && this.options.snapshot && this.options.snapshotOnMigrate) {
|
|
193
|
-
const ctx = Utils.isObject(options) ? options.transaction : undefined;
|
|
194
194
|
const { skipTables, skipViews } = this.config.get('schemaGenerator');
|
|
195
195
|
const schema = await DatabaseSchema.create(this.em.getConnection(), this.em.getPlatform(), this.config, undefined, undefined, undefined, skipTables, skipViews, ctx);
|
|
196
196
|
// keep the snapshot authored by `migration:create` when the migrated DB still matches it
|
|
@@ -209,6 +209,14 @@ export class Migrator extends AbstractMigrator {
|
|
|
209
209
|
}
|
|
210
210
|
return result;
|
|
211
211
|
}
|
|
212
|
+
async runWithoutForeignKeys(ctx, run) {
|
|
213
|
+
// sqlite ignores `pragma foreign_keys` inside a transaction, so a table rebuild would run the FK actions of child rows
|
|
214
|
+
if (ctx || !this.options.transactional || !this.driver.getPlatform().getSchemaHelper().getForeignKeyCheckSQL()) {
|
|
215
|
+
return run();
|
|
216
|
+
}
|
|
217
|
+
await this.init(); // can recreate the runner, which holds the FK state
|
|
218
|
+
return this.runner.runWithoutForeignKeys(run);
|
|
219
|
+
}
|
|
212
220
|
/** Whether the introspected schema differs from the snapshot in any way the comparator turns into SQL. */
|
|
213
221
|
snapshotDiffers(snapshot, schema) {
|
|
214
222
|
const comparator = new SchemaComparator(this.driver.getPlatform());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/migrations",
|
|
3
|
-
"version": "7.3.0-dev.
|
|
3
|
+
"version": "7.3.0-dev.18",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"copy": "node ../../scripts/copy.mjs"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@mikro-orm/sql": "7.3.0-dev.
|
|
50
|
+
"@mikro-orm/sql": "7.3.0-dev.18"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@mikro-orm/core": "^7.2.
|
|
53
|
+
"@mikro-orm/core": "^7.2.6"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@mikro-orm/core": "7.3.0-dev.
|
|
56
|
+
"@mikro-orm/core": "7.3.0-dev.18"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">= 22.17.0"
|