Skip to content

Commit

Permalink
add ControlledTransaction. (#962)
Browse files Browse the repository at this point in the history
Co-authored-by: Igal Klebanov <[email protected]>
  • Loading branch information
igalklebanov and Igal Klebanov committed Oct 24, 2024
1 parent ad196dd commit ee04272
Show file tree
Hide file tree
Showing 14 changed files with 1,369 additions and 27 deletions.
6 changes: 3 additions & 3 deletions scripts/copy-interface-documentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const OBJECT_REGEXES = [
/^(?:export )?declare (?:abstract )?class (\w+)/,
/^(?:export )?interface (\w+)/,
]
const GENERIC_ARGUMENTS_REGEX = /<[\w"'`,{}=| ]+>/g
const GENERIC_ARGUMENTS_REGEX = /<[\w"'`,{}=|\[\] ]+>/g
const JSDOC_START_REGEX = /^\s+\/\*\*/
const JSDOC_END_REGEX = /^\s+\*\//

Expand Down Expand Up @@ -123,7 +123,7 @@ function parseObjects(file) {
function parseImplements(line) {
if (!line.endsWith('{')) {
console.warn(
`skipping object declaration "${line}". Expected it to end with "{"'`
`skipping object declaration "${line}". Expected it to end with "{"'`,
)
return []
}
Expand Down Expand Up @@ -225,7 +225,7 @@ function findDocProperty(files, object, propertyName) {
}

const interfaceProperty = interfaceObject.properties.find(
(it) => it.name === propertyName
(it) => it.name === propertyName,
)

if (interfaceProperty?.doc) {
Expand Down
26 changes: 16 additions & 10 deletions src/dialect/mssql/mssql-dialect-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,30 +65,36 @@ export interface Tedious {

export interface TediousConnection {
beginTransaction(
callback: (error?: Error | null, transactionDescriptor?: any) => void,
name?: string,
isolationLevel?: number,
callback: (
err: Error | null | undefined,
transactionDescriptor?: any,
) => void,
name?: string | undefined,
isolationLevel?: number | undefined,
): void
cancel(): boolean
close(): void
commitTransaction(
callback: (error?: Error | null) => void,
name?: string,
callback: (err: Error | null | undefined) => void,
name?: string | undefined,
): void
connect(callback?: (error?: Error) => void): void
connect(connectListener: (err?: Error) => void): void
execSql(request: TediousRequest): void
off(event: 'error', listener: (error: unknown) => void): this
off(event: string, listener: (...args: any[]) => void): this
on(event: 'error', listener: (error: unknown) => void): this
on(event: string, listener: (...args: any[]) => void): this
once(event: 'end', listener: () => void): this
once(event: string, listener: (...args: any[]) => void): this
reset(callback: (error?: Error | null) => void): void
reset(callback: (err: Error | null | undefined) => void): void
rollbackTransaction(
callback: (error?: Error | null) => void,
name?: string,
callback: (err: Error | null | undefined) => void,
name?: string | undefined,
): void
saveTransaction(
callback: (err: Error | null | undefined) => void,
name: string,
): void
saveTransaction(callback: (error?: Error | null) => void, name: string): void
}

export type TediousIsolationLevel = Record<string, number>
Expand Down
27 changes: 25 additions & 2 deletions src/dialect/mssql/mssql-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ export class MssqlDriver implements Driver {
await connection.rollbackTransaction()
}

async savepoint(
connection: MssqlConnection,
savepointName: string,
): Promise<void> {
await connection.savepoint(savepointName)
}

async rollbackToSavepoint(
connection: MssqlConnection,
savepointName: string,
): Promise<void> {
await connection.rollbackTransaction(savepointName)
}

async releaseConnection(connection: MssqlConnection): Promise<void> {
await connection[PRIVATE_RELEASE_METHOD]()
this.#pool.release(connection)
Expand Down Expand Up @@ -174,12 +188,21 @@ class MssqlConnection implements DatabaseConnection {
}
}

async rollbackTransaction(): Promise<void> {
async rollbackTransaction(savepointName?: string): Promise<void> {
await new Promise((resolve, reject) =>
this.#connection.rollbackTransaction((error) => {
if (error) reject(error)
else resolve(undefined)
}),
}, savepointName),
)
}

async savepoint(savepointName: string): Promise<void> {
await new Promise((resolve, reject) =>
this.#connection.saveTransaction((error) => {
if (error) reject(error)
else resolve(undefined)
}, savepointName),
)
}

Expand Down
32 changes: 32 additions & 0 deletions src/dialect/mysql/mysql-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import {
QueryResult,
} from '../../driver/database-connection.js'
import { Driver, TransactionSettings } from '../../driver/driver.js'
import { parseSavepointCommand } from '../../parser/savepoint-parser.js'
import { CompiledQuery } from '../../query-compiler/compiled-query.js'
import { QueryCompiler } from '../../query-compiler/query-compiler.js'
import { isFunction, isObject, freeze } from '../../util/object-utils.js'
import { extendStackTrace } from '../../util/stack-trace-utils.js'
import {
Expand Down Expand Up @@ -90,6 +92,36 @@ export class MysqlDriver implements Driver {
await connection.executeQuery(CompiledQuery.raw('rollback'))
}

async savepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('savepoint', savepointName)),
)
}

async rollbackToSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('rollback to', savepointName)),
)
}

async releaseSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('release savepoint', savepointName)),
)
}

async releaseConnection(connection: MysqlConnection): Promise<void> {
connection[PRIVATE_RELEASE_METHOD]()
}
Expand Down
37 changes: 37 additions & 0 deletions src/dialect/postgres/postgres-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import {
QueryResult,
} from '../../driver/database-connection.js'
import { Driver, TransactionSettings } from '../../driver/driver.js'
import { IdentifierNode } from '../../operation-node/identifier-node.js'
import { RawNode } from '../../operation-node/raw-node.js'
import { parseSavepointCommand } from '../../parser/savepoint-parser.js'
import { CompiledQuery } from '../../query-compiler/compiled-query.js'
import {
QueryCompiler,
RootOperationNode,
} from '../../query-compiler/query-compiler.js'
import { isFunction, freeze } from '../../util/object-utils.js'
import { extendStackTrace } from '../../util/stack-trace-utils.js'
import {
Expand Down Expand Up @@ -78,6 +85,36 @@ export class PostgresDriver implements Driver {
await connection.executeQuery(CompiledQuery.raw('rollback'))
}

async savepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('savepoint', savepointName)),
)
}

async rollbackToSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('rollback to', savepointName)),
)
}

async releaseSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('release', savepointName)),
)
}

async releaseConnection(connection: PostgresConnection): Promise<void> {
connection[PRIVATE_RELEASE_METHOD]()
}
Expand Down
32 changes: 32 additions & 0 deletions src/dialect/sqlite/sqlite-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
} from '../../driver/database-connection.js'
import { Driver } from '../../driver/driver.js'
import { SelectQueryNode } from '../../operation-node/select-query-node.js'
import { parseSavepointCommand } from '../../parser/savepoint-parser.js'
import { CompiledQuery } from '../../query-compiler/compiled-query.js'
import { QueryCompiler } from '../../query-compiler/query-compiler.js'
import { freeze, isFunction } from '../../util/object-utils.js'
import { SqliteDatabase, SqliteDialectConfig } from './sqlite-dialect-config.js'

Expand Down Expand Up @@ -50,6 +52,36 @@ export class SqliteDriver implements Driver {
await connection.executeQuery(CompiledQuery.raw('rollback'))
}

async savepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('savepoint', savepointName)),
)
}

async rollbackToSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('rollback to', savepointName)),
)
}

async releaseSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
await connection.executeQuery(
compileQuery(parseSavepointCommand('release', savepointName)),
)
}

async releaseConnection(): Promise<void> {
this.#connectionMutex.unlock()
}
Expand Down
28 changes: 28 additions & 0 deletions src/driver/driver.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { QueryCompiler } from '../query-compiler/query-compiler.js'
import { ArrayItemType } from '../util/type-utils.js'
import { DatabaseConnection } from './database-connection.js'

Expand Down Expand Up @@ -37,6 +38,33 @@ export interface Driver {
*/
rollbackTransaction(connection: DatabaseConnection): Promise<void>

/**
* Establishses a new savepoint within a transaction.
*/
savepoint?(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void>

/**
* Rolls back to a savepoint within a transaction.
*/
rollbackToSavepoint?(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void>

/**
* Releases a savepoint within a transaction.
*/
releaseSavepoint?(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void>

/**
* Releases a connection back to the pool.
*/
Expand Down
12 changes: 12 additions & 0 deletions src/driver/dummy-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ export class DummyDriver implements Driver {
async destroy(): Promise<void> {
// Nothing to do here.
}

async releaseSavepoint(): Promise<void> {
// Nothing to do here.
}

async rollbackToSavepoint(): Promise<void> {
// Nothing to do here.
}

async savepoint(): Promise<void> {
// Nothing to do here.
}
}

class DummyConnection implements DatabaseConnection {
Expand Down
49 changes: 49 additions & 0 deletions src/driver/runtime-driver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CompiledQuery } from '../query-compiler/compiled-query.js'
import { QueryCompiler } from '../query-compiler/query-compiler.js'
import { Log } from '../util/log.js'
import { performanceNow } from '../util/performance-now.js'
import { DatabaseConnection, QueryResult } from './database-connection.js'
Expand Down Expand Up @@ -85,6 +86,54 @@ export class RuntimeDriver implements Driver {
return this.#driver.rollbackTransaction(connection)
}

savepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
if (this.#driver.savepoint) {
return this.#driver.savepoint(connection, savepointName, compileQuery)
}

throw new Error('The `savepoint` method is not supported by this driver')
}

rollbackToSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
if (this.#driver.rollbackToSavepoint) {
return this.#driver.rollbackToSavepoint(
connection,
savepointName,
compileQuery,
)
}

throw new Error(
'The `rollbackToSavepoint` method is not supported by this driver',
)
}

releaseSavepoint(
connection: DatabaseConnection,
savepointName: string,
compileQuery: QueryCompiler['compileQuery'],
): Promise<void> {
if (this.#driver.releaseSavepoint) {
return this.#driver.releaseSavepoint(
connection,
savepointName,
compileQuery,
)
}

throw new Error(
'The `releaseSavepoint` method is not supported by this driver',
)
}

async destroy(): Promise<void> {
if (!this.#initPromise) {
return
Expand Down
Loading

0 comments on commit ee04272

Please sign in to comment.