Skip to content

Commit

Permalink
Pass options to dialect adapter lock methods
Browse files Browse the repository at this point in the history
  • Loading branch information
koskimas committed Jan 15, 2023
1 parent c6598a9 commit fbcf3e3
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kysely",
"version": "0.23.3",
"version": "0.23.4",
"description": "Type safe SQL query builder",
"repository": {
"type": "git",
Expand Down
67 changes: 59 additions & 8 deletions src/dialect/dialect-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,48 @@ export interface DialectAdapter {
* Most dialects have explicit locks that can be used, like advisory locks
* in PostgreSQL and the get_lock function in MySQL.
*
* If the dialect doesn't have explicit locks the {@link MIGRATION_LOCK_TABLE}
* created by Kysely can be used instead. {@link MIGRATION_LOCK_TABLE}
* has two columns `id` and `is_locked` and there's only one row in the
* table whose id is {@link MIGRATION_LOCK_ID}. `is_locked` is an integer.
* Kysely takes care of creating the lock table and inserting the one single
* row to it before this method is executed.
* If the dialect doesn't have explicit locks the {@link MigrationLockOptions.lockTable}
* created by Kysely can be used instead. You can access it through the `options` object.
* The lock table has two columns `id` and `is_locked` and there's only one row in the table
* whose id is {@link MigrationLockOptions.lockRowId}. `is_locked` is an integer. Kysely
* takes care of creating the lock table and inserting the one single row to it before this
* method is executed. If the dialect supports schemas and the user has specified a custom
* schema in their migration settings, the options object also contains the schema name in
* {@link MigrationLockOptions.lockTableSchema}.
*
* Here's an example of how you might implement this method for a dialect that doesn't
* have explicit locks but supports `FOR UPDATE` row locks and transactional DDL:
*
* ```ts
* {
* async acquireMigrationLock(db, options): Promise<void> {
* const queryDb = options.lockTableSchema
* ? db.withSchema(options.lockTableSchema)
* : db
*
* // Since our imaginary dialect supports transactional DDL and has
* // row locks, we can simply take a row lock here and it will guarantee
* // all subsequent calls to this method from other transactions will
* // wait until this transaction finishes.
* await queryDb
* .selectFrom(options.lockTable)
* .selectAll()
* .where('id', '=', options.lockRowId)
* .forUpdate()
* .execute()
* }
* }
* ```
*
* If `supportsTransactionalDdl` is `true` then the `db` passed to this method
* is a transaction inside which the migrations will be executed. Otherwise
* `db` is a single connection (session) that will be used to execute the
* migrations.
*/
acquireMigrationLock(db: Kysely<any>): Promise<void>
acquireMigrationLock(
db: Kysely<any>,
options: MigrationLockOptions
): Promise<void>

/**
* Releases the migration lock. See {@link acquireMigrationLock}.
Expand All @@ -51,5 +80,27 @@ export interface DialectAdapter {
* is a single connection (session) that was used to execute the migrations
* and the `acquireMigrationLock` call.
*/
releaseMigrationLock(db: Kysely<any>): Promise<void>
releaseMigrationLock(
db: Kysely<any>,
options: MigrationLockOptions
): Promise<void>
}

export interface MigrationLockOptions {
/**
* The name of the migration lock table.
*/
readonly lockTable: string

/**
* The id of the only row in the migration lock table.
*/
readonly lockRowId: string

/**
* The schema in which the migration lock table lives. This is only
* defined if the user has specified a custom schema in the migration
* settings.
*/
readonly lockTableSchema?: string
}
12 changes: 10 additions & 2 deletions src/migration/migrator.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MigrationLockOptions } from '../dialect/dialect-adapter.js'
import { Kysely } from '../kysely.js'
import { KyselyPlugin } from '../plugin/kysely-plugin.js'
import { NoopPlugin } from '../plugin/noop-plugin.js'
Expand Down Expand Up @@ -384,9 +385,16 @@ export class Migrator {
): Promise<MigrationResultSet> {
const adapter = this.#props.db.getExecutor().adapter

const lockOptions: MigrationLockOptions = freeze({
lockTable:
this.#props.migrationLockTableName ?? DEFAULT_MIGRATION_LOCK_TABLE,
lockRowId: MIGRATION_LOCK_ID,
lockTableSchema: this.#props.migrationTableSchema,
})

const run = async (db: Kysely<any>): Promise<MigrationResultSet> => {
try {
await adapter.acquireMigrationLock(db)
await adapter.acquireMigrationLock(db, lockOptions)

const state = await this.#getState(db)

Expand All @@ -408,7 +416,7 @@ export class Migrator {

return { results: [] }
} finally {
await adapter.releaseMigrationLock(db)
await adapter.releaseMigrationLock(db, lockOptions)
}
}

Expand Down
1 change: 0 additions & 1 deletion src/query-compiler/default-query-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import { WhereNode } from '../operation-node/where-node.js'
import { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js'
import { WithNode } from '../operation-node/with-node.js'
import {
getLast,
freeze,
isString,
isNumber,
Expand Down
1 change: 0 additions & 1 deletion test/node/src/schema.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ColumnMetadata, sql } from '../../../'

import {
BuiltInDialect,
BUILT_IN_DIALECTS,
clearDatabase,
destroyTest,
Expand Down

0 comments on commit fbcf3e3

Please sign in to comment.