Skip to content

Commit

Permalink
feat(migrations): allow using knex in migrations
Browse files Browse the repository at this point in the history
This adds a `Migration.getKnex()` shortcut as well as allows
using knex in `Migration.addSql()` and `Migration.execute()`.

Related: #799
  • Loading branch information
B4nan committed Sep 2, 2020
1 parent 22bc2a9 commit fc2fbaa
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 16 deletions.
14 changes: 10 additions & 4 deletions packages/migrations/src/Migration.ts
@@ -1,9 +1,11 @@
import { Configuration, Transaction } from '@mikro-orm/core';
import { AbstractSqlDriver, Knex } from '@mikro-orm/knex';

export type Query = string | Knex.QueryBuilder | Knex.Raw;

export abstract class Migration {

private readonly queries: string[] = [];
private readonly queries: Query[] = [];
protected ctx?: Transaction<Knex.Transaction>;

constructor(protected readonly driver: AbstractSqlDriver,
Expand All @@ -19,7 +21,7 @@ export abstract class Migration {
return true;
}

addSql(sql: string): void {
addSql(sql: Query): void {
this.queries.push(sql);
}

Expand All @@ -32,11 +34,15 @@ export abstract class Migration {
this.ctx = ctx;
}

async execute(sql: string) {
async execute(sql: Query) {
return this.driver.execute(sql, undefined, 'all', this.ctx);
}

getQueries(): string[] {
getKnex() {
return this.driver.getConnection('write').getKnex();
}

getQueries(): Query[] {
return this.queries;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/migrations/src/MigrationRunner.ts
Expand Up @@ -22,7 +22,7 @@ export class MigrationRunner {
await this.connection.transactional(async tx => {
migration.setTransactionContext(tx);
const queries = await this.getQueries(migration, method);
await Utils.runSerial(queries, sql => this.driver.execute(tx.raw(sql)));
await Utils.runSerial(queries, sql => this.driver.execute(sql, undefined, 'all', tx));
}, this.masterTransaction);
}
}
Expand All @@ -45,7 +45,7 @@ export class MigrationRunner {
queries.push(...this.helper.getSchemaEnd().split('\n'));
}

queries = queries.filter(sql => sql.trim().length > 0);
queries = queries.filter(sql => !Utils.isString(sql) || sql.trim().length > 0);
return queries;
}

Expand Down
25 changes: 15 additions & 10 deletions tests/Migrator.test.ts
Expand Up @@ -18,8 +18,11 @@ class MigrationTest2 extends Migration {

async up(): Promise<void> {
this.addSql('select 1 + 1');
const res = await this.execute('select 1 + 1 as count');
expect(res).toEqual([{ count: 2 }]);
const knex = this.getKnex();
this.addSql(knex.raw('select 1 + 1'));
this.addSql(knex.select(knex.raw('2 + 2 as count2')));
const res = await this.execute('select 1 + 1 as count1');
expect(res).toEqual([{ count1: 2 }]);
}

isTransactional(): boolean {
Expand Down Expand Up @@ -97,7 +100,7 @@ describe('Migrator', () => {
});

test('ensureTable and list executed migrations', async () => {
await orm.em.getConnection().getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
await orm.em.getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
const migrator = new Migrator(orm.em);
// @ts-ignore
const storage = migrator.storage;
Expand All @@ -115,7 +118,7 @@ describe('Migrator', () => {
});

test('runner', async () => {
await orm.em.getConnection().getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
await orm.em.getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
const migrator = new Migrator(orm.em);
// @ts-ignore
await migrator.storage.ensureTable();
Expand Down Expand Up @@ -149,13 +152,15 @@ describe('Migrator', () => {
migrator.options.disableForeignKeys = false;
const migration2 = new MigrationTest2(orm.em.getDriver(), orm.config);
await runner.run(migration2, 'up');
expect(mock.mock.calls.length).toBe(2);
expect(mock.mock.calls[0][0]).toMatch('select 1 + 1');
expect(mock.mock.calls[0][0]).toMatch('select 1 + 1 as count');
expect(mock.mock.calls.length).toBe(4);
expect(mock.mock.calls[0][0]).toMatch('select 1 + 1 as count1');
expect(mock.mock.calls[1][0]).toMatch('select 1 + 1');
expect(mock.mock.calls[2][0]).toMatch('select 1 + 1');
expect(mock.mock.calls[3][0]).toMatch('select 2 + 2 as count2');
});

test('up/down params [all or nothing enabled]', async () => {
await orm.em.getConnection().getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
await orm.em.getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
const migrator = new Migrator(orm.em);
// @ts-ignore
migrator.options.disableForeignKeys = false;
Expand Down Expand Up @@ -189,7 +194,7 @@ describe('Migrator', () => {
});

test('up/down params [all or nothing disabled]', async () => {
await orm.em.getConnection().getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
await orm.em.getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
const migrator = new Migrator(orm.em);
// @ts-ignore
migrator.options.disableForeignKeys = false;
Expand Down Expand Up @@ -245,7 +250,7 @@ describe('Migrator - with explicit migrations', () => {
afterAll(async () => orm.close(true));

test('runner', async () => {
await orm.em.getConnection().getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
await orm.em.getKnex().schema.dropTableIfExists(orm.config.get('migrations').tableName!);
const migrator = new Migrator(orm.em);
// @ts-ignore
await migrator.storage.ensureTable();
Expand Down

0 comments on commit fc2fbaa

Please sign in to comment.