Skip to content

Commit

Permalink
feat: Add disableTransactions option to Migrator (#1335)
Browse files Browse the repository at this point in the history
Co-authored-by: Igal Klebanov <[email protected]>
  • Loading branch information
reidswan and igalklebanov committed Feb 8, 2025
1 parent fe4ca0d commit 9f72fbe
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/migration/migrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ export class Migrator {
}
}

if (adapter.supportsTransactionalDdl) {
if (adapter.supportsTransactionalDdl && !this.#props.disableTransactions) {
return this.#props.db.transaction().execute(run)
} else {
return this.#props.db.connection().execute(run)
Expand Down Expand Up @@ -822,6 +822,15 @@ export interface MigratorProps {
* Default is `name0.localeCompare(name1)`.
*/
readonly nameComparator?: (name0: string, name1: string) => number

/**
* When `true`, don't run migrations in transactions even if the dialect supports transactional DDL.
*
* Default is `false`.
*
* This is useful when some migrations include queries that would fail otherwise.
*/
readonly disableTransactions?: boolean
}

/**
Expand Down
54 changes: 54 additions & 0 deletions test/node/src/migration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
Migrator,
NO_MIGRATIONS,
MigratorProps,
type QueryExecutor,
type Kysely,
} from '../../../'

import {
Expand All @@ -19,7 +21,9 @@ import {
initTest,
TestContext,
DIALECTS,
type Database,
} from './test-setup.js'
import { createSandbox, type SinonSpy } from 'sinon'

const CUSTOM_MIGRATION_SCHEMA = 'migrate'
const CUSTOM_MIGRATION_TABLE = 'custom_migrations'
Expand Down Expand Up @@ -652,6 +656,20 @@ for (const dialect of DIALECTS) {
})

describe('migrateUp', () => {
const sandbox = createSandbox()
let transactionSpy: SinonSpy<
Parameters<Kysely<Database>['transaction']>,
ReturnType<Kysely<Database>['transaction']>
>

beforeEach(() => {
transactionSpy = sandbox.spy(ctx.db, 'transaction')
})

afterEach(() => {
sandbox.restore()
})

it('should migrate up one step', async () => {
const [migrator, executedUpMethods] = createMigrations([
'migration1',
Expand Down Expand Up @@ -738,6 +756,42 @@ for (const dialect of DIALECTS) {
expect(executedUpMethods1).to.eql(['migration1', 'migration3'])
expect(executedUpMethods2).to.eql(['migration2', 'migration4'])
})

it('should not execute in transaction if disableTransactions is true', async () => {
const [migrator, executedUpMethods] = createMigrations(['migration1'], {
disableTransactions: true,
})

const { results } = await migrator.migrateUp()

expect(results).to.eql([
{ migrationName: 'migration1', direction: 'Up', status: 'Success' },
])

expect(executedUpMethods).to.eql(['migration1'])

expect(transactionSpy.called).to.be.false
})

it('should execute in transaction if disableTransactions is false and transactionDdl supported', async () => {
const [migrator, executedUpMethods] = createMigrations(['migration1'], {
disableTransactions: false,
})

const { results } = await migrator.migrateUp()

expect(results).to.eql([
{ migrationName: 'migration1', direction: 'Up', status: 'Success' },
])

expect(executedUpMethods).to.eql(['migration1'])

if (ctx.db.getExecutor().adapter.supportsTransactionalDdl) {
expect(transactionSpy.called).to.be.true
} else {
expect(transactionSpy.called).to.be.false
}
})
})

describe('migrateDown', () => {
Expand Down

0 comments on commit 9f72fbe

Please sign in to comment.