diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index 6829a329f82..c40aa31a4e3 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -272,12 +272,12 @@ export class Connection { * Runs all pending migrations. * Can be used only after connection to the database is established. */ - async runMigrations(options?: { transactionMode?: 'all' | 'none' | 'each' }): Promise { + async runMigrations(options?: { transactionMode?: "all" | "none" | "each" }): Promise { if (!this.isConnected) throw new CannotExecuteNotConnectedError(this.name); const migrationExecutor = new MigrationExecutor(this); - migrationExecutor.transactionMode = (options && options.transactionMode) || 'all'; + migrationExecutor.transactionMode = (options && options.transactionMode) || "all"; const successMigrations = await migrationExecutor.executePendingMigrations(); return successMigrations; @@ -287,13 +287,13 @@ export class Connection { * Reverts last executed migration. * Can be used only after connection to the database is established. */ - async undoLastMigration(options?: { transactionMode?: 'all' | 'none' | 'each' }): Promise { + async undoLastMigration(options?: { transactionMode?: "all" | "none" | "each" }): Promise { if (!this.isConnected) throw new CannotExecuteNotConnectedError(this.name); const migrationExecutor = new MigrationExecutor(this); - migrationExecutor.transactionMode = (options && options.transactionMode) || 'all'; + migrationExecutor.transactionMode = (options && options.transactionMode) || "all"; await migrationExecutor.undoLastMigration(); } diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index 569f0f62bba..61bc20abe8e 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -24,7 +24,7 @@ export class MigrationExecutor { * none: all migrations are run without a transaction * each: each migration is run in a separate transaction */ - transactionMode: 'all' | 'none' | 'each' = 'all'; + transactionMode: "all" | "none" | "each" = "all"; // ------------------------------------------------------------------------- // Private Properties @@ -101,11 +101,11 @@ export class MigrationExecutor { this.connection.logger.logSchemaBuild(`${pendingMigrations.length} migrations are new migrations that needs to be executed.`); switch (this.transactionMode) { - case 'each': + case "each": return this.runEachMigrationInSeparateTransaction(queryRunner, pendingMigrations); - case 'all': + case "all": return this.runAllMigrationsInSingleTransaction(queryRunner, pendingMigrations); - case 'none': + case "none": return this.runAllMigrationsWithoutTransaction(queryRunner, pendingMigrations); } } @@ -149,7 +149,7 @@ export class MigrationExecutor { // start transaction if its not started yet let transactionStartedByUs = false; - if ((this.transactionMode !== 'none') && !queryRunner.isTransactionActive) { + if ((this.transactionMode !== "none") && !queryRunner.isTransactionActive) { await queryRunner.startTransaction(); transactionStartedByUs = true; } @@ -315,7 +315,7 @@ export class MigrationExecutor { const successMigrations: Migration[] = []; if (queryRunner.isTransactionActive) { - throw new Error('Trying to run each migration in separate transaction, but already in one. Try changing this option and run migrations again.'); + throw new Error("Trying to run each migration in separate transaction, but already in one. Try changing this option and run migrations again."); } // run all pending migrations in a sequence diff --git a/test/github-issues/2693/issue-2693.ts b/test/github-issues/2693/issue-2693.ts new file mode 100644 index 00000000000..710fe922454 --- /dev/null +++ b/test/github-issues/2693/issue-2693.ts @@ -0,0 +1,31 @@ +import "reflect-metadata"; +import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {Migration} from "../../../src/migration/Migration"; + +describe("github issues > #2875 Option to run migrations in 1-transaction-per-migration mode", () => { + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + migrations: [__dirname + "/migration/*.js"], + enabledDrivers: ["postgres"], + schemaCreate: true, + dropSchema: true, + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should fail to run all necessary migrations when transactionMode is all", () => Promise.all(connections.map(async connection => { + const mymigr: Migration[] = await connection.runMigrations({ transactionMode: "all" }); + + mymigr.length.should.be.equal(0); + }))); + + it("should be able to run all necessary migrations when transactionMode is each", () => Promise.all(connections.map(async connection => { + const mymigr: Migration[] = await connection.runMigrations({ transactionMode: "each" }); + + mymigr.length.should.be.equal(2); + mymigr[0].name.should.be.equal("CreateUuidExtension1544044606093"); + mymigr[1].name.should.be.equal("CreateUsers1543965157399"); + }))); + }); \ No newline at end of file diff --git a/test/github-issues/2693/migration/1543844606093-CreateUuidExtension.ts b/test/github-issues/2693/migration/1543844606093-CreateUuidExtension.ts new file mode 100644 index 00000000000..fabb4bcfb0d --- /dev/null +++ b/test/github-issues/2693/migration/1543844606093-CreateUuidExtension.ts @@ -0,0 +1,12 @@ +import { MigrationInterface } from "../../../../src/migration/MigrationInterface"; +import { QueryRunner } from "../../../../src/query-runner/QueryRunner"; + +export class CreateUuidExtension1544044606093 implements MigrationInterface { + public up(queryRunner: QueryRunner): Promise { + return queryRunner.query(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp";`); + } + + public down(queryRunner: QueryRunner): Promise { + return queryRunner.query("DROP EXTENSION \"uuid-ossp\""); + } +} diff --git a/test/github-issues/2693/migration/1543965157399-CreateUsers.ts b/test/github-issues/2693/migration/1543965157399-CreateUsers.ts new file mode 100644 index 00000000000..4a21c8cdf8b --- /dev/null +++ b/test/github-issues/2693/migration/1543965157399-CreateUsers.ts @@ -0,0 +1,20 @@ +import { MigrationInterface } from "../../../../src/migration/MigrationInterface"; +import { QueryRunner } from "../../../../src/query-runner/QueryRunner"; +import { Table } from "../../../../src/schema-builder/table/Table"; + +export class CreateUsers1543965157399 implements MigrationInterface { + public up(queryRunner: QueryRunner): Promise { + return queryRunner.createTable( + new Table({ + name: "users", + columns: [ + { name: "id", type: "uuid", isPrimary: true, default: "uuid_generate_v4()" }, + ] + }) + ); + } + + public down(queryRunner: QueryRunner): Promise { + return queryRunner.dropTable("users"); + } +} \ No newline at end of file