Skip to content

Commit 477f8c5

Browse files
igalklebanovIgal Klebanov
and
Igal Klebanov
committed
add ControlledTransaction. (#962)
Co-authored-by: Igal Klebanov <[email protected]>
1 parent ae349bc commit 477f8c5

14 files changed

+1369
-27
lines changed

scripts/copy-interface-documentation.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const OBJECT_REGEXES = [
2222
/^(?:export )?declare (?:abstract )?class (\w+)/,
2323
/^(?:export )?interface (\w+)/,
2424
]
25-
const GENERIC_ARGUMENTS_REGEX = /<[\w"'`,{}=| ]+>/g
25+
const GENERIC_ARGUMENTS_REGEX = /<[\w"'`,{}=|\[\] ]+>/g
2626
const JSDOC_START_REGEX = /^\s+\/\*\*/
2727
const JSDOC_END_REGEX = /^\s+\*\//
2828

@@ -123,7 +123,7 @@ function parseObjects(file) {
123123
function parseImplements(line) {
124124
if (!line.endsWith('{')) {
125125
console.warn(
126-
`skipping object declaration "${line}". Expected it to end with "{"'`
126+
`skipping object declaration "${line}". Expected it to end with "{"'`,
127127
)
128128
return []
129129
}
@@ -225,7 +225,7 @@ function findDocProperty(files, object, propertyName) {
225225
}
226226

227227
const interfaceProperty = interfaceObject.properties.find(
228-
(it) => it.name === propertyName
228+
(it) => it.name === propertyName,
229229
)
230230

231231
if (interfaceProperty?.doc) {

src/dialect/mssql/mssql-dialect-config.ts

+16-10
Original file line numberDiff line numberDiff line change
@@ -65,30 +65,36 @@ export interface Tedious {
6565

6666
export interface TediousConnection {
6767
beginTransaction(
68-
callback: (error?: Error | null, transactionDescriptor?: any) => void,
69-
name?: string,
70-
isolationLevel?: number,
68+
callback: (
69+
err: Error | null | undefined,
70+
transactionDescriptor?: any,
71+
) => void,
72+
name?: string | undefined,
73+
isolationLevel?: number | undefined,
7174
): void
7275
cancel(): boolean
7376
close(): void
7477
commitTransaction(
75-
callback: (error?: Error | null) => void,
76-
name?: string,
78+
callback: (err: Error | null | undefined) => void,
79+
name?: string | undefined,
7780
): void
78-
connect(callback?: (error?: Error) => void): void
81+
connect(connectListener: (err?: Error) => void): void
7982
execSql(request: TediousRequest): void
8083
off(event: 'error', listener: (error: unknown) => void): this
8184
off(event: string, listener: (...args: any[]) => void): this
8285
on(event: 'error', listener: (error: unknown) => void): this
8386
on(event: string, listener: (...args: any[]) => void): this
8487
once(event: 'end', listener: () => void): this
8588
once(event: string, listener: (...args: any[]) => void): this
86-
reset(callback: (error?: Error | null) => void): void
89+
reset(callback: (err: Error | null | undefined) => void): void
8790
rollbackTransaction(
88-
callback: (error?: Error | null) => void,
89-
name?: string,
91+
callback: (err: Error | null | undefined) => void,
92+
name?: string | undefined,
93+
): void
94+
saveTransaction(
95+
callback: (err: Error | null | undefined) => void,
96+
name: string,
9097
): void
91-
saveTransaction(callback: (error?: Error | null) => void, name: string): void
9298
}
9399

94100
export type TediousIsolationLevel = Record<string, number>

src/dialect/mssql/mssql-driver.ts

+25-2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@ export class MssqlDriver implements Driver {
8686
await connection.rollbackTransaction()
8787
}
8888

89+
async savepoint(
90+
connection: MssqlConnection,
91+
savepointName: string,
92+
): Promise<void> {
93+
await connection.savepoint(savepointName)
94+
}
95+
96+
async rollbackToSavepoint(
97+
connection: MssqlConnection,
98+
savepointName: string,
99+
): Promise<void> {
100+
await connection.rollbackTransaction(savepointName)
101+
}
102+
89103
async releaseConnection(connection: MssqlConnection): Promise<void> {
90104
await connection[PRIVATE_RELEASE_METHOD]()
91105
this.#pool.release(connection)
@@ -174,12 +188,21 @@ class MssqlConnection implements DatabaseConnection {
174188
}
175189
}
176190

177-
async rollbackTransaction(): Promise<void> {
191+
async rollbackTransaction(savepointName?: string): Promise<void> {
178192
await new Promise((resolve, reject) =>
179193
this.#connection.rollbackTransaction((error) => {
180194
if (error) reject(error)
181195
else resolve(undefined)
182-
}),
196+
}, savepointName),
197+
)
198+
}
199+
200+
async savepoint(savepointName: string): Promise<void> {
201+
await new Promise((resolve, reject) =>
202+
this.#connection.saveTransaction((error) => {
203+
if (error) reject(error)
204+
else resolve(undefined)
205+
}, savepointName),
183206
)
184207
}
185208

src/dialect/mysql/mysql-driver.ts

+32
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import {
33
QueryResult,
44
} from '../../driver/database-connection.js'
55
import { Driver, TransactionSettings } from '../../driver/driver.js'
6+
import { parseSavepointCommand } from '../../parser/savepoint-parser.js'
67
import { CompiledQuery } from '../../query-compiler/compiled-query.js'
8+
import { QueryCompiler } from '../../query-compiler/query-compiler.js'
79
import { isFunction, isObject, freeze } from '../../util/object-utils.js'
810
import { extendStackTrace } from '../../util/stack-trace-utils.js'
911
import {
@@ -90,6 +92,36 @@ export class MysqlDriver implements Driver {
9092
await connection.executeQuery(CompiledQuery.raw('rollback'))
9193
}
9294

95+
async savepoint(
96+
connection: DatabaseConnection,
97+
savepointName: string,
98+
compileQuery: QueryCompiler['compileQuery'],
99+
): Promise<void> {
100+
await connection.executeQuery(
101+
compileQuery(parseSavepointCommand('savepoint', savepointName)),
102+
)
103+
}
104+
105+
async rollbackToSavepoint(
106+
connection: DatabaseConnection,
107+
savepointName: string,
108+
compileQuery: QueryCompiler['compileQuery'],
109+
): Promise<void> {
110+
await connection.executeQuery(
111+
compileQuery(parseSavepointCommand('rollback to', savepointName)),
112+
)
113+
}
114+
115+
async releaseSavepoint(
116+
connection: DatabaseConnection,
117+
savepointName: string,
118+
compileQuery: QueryCompiler['compileQuery'],
119+
): Promise<void> {
120+
await connection.executeQuery(
121+
compileQuery(parseSavepointCommand('release savepoint', savepointName)),
122+
)
123+
}
124+
93125
async releaseConnection(connection: MysqlConnection): Promise<void> {
94126
connection[PRIVATE_RELEASE_METHOD]()
95127
}

src/dialect/postgres/postgres-driver.ts

+37
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ import {
33
QueryResult,
44
} from '../../driver/database-connection.js'
55
import { Driver, TransactionSettings } from '../../driver/driver.js'
6+
import { IdentifierNode } from '../../operation-node/identifier-node.js'
7+
import { RawNode } from '../../operation-node/raw-node.js'
8+
import { parseSavepointCommand } from '../../parser/savepoint-parser.js'
69
import { CompiledQuery } from '../../query-compiler/compiled-query.js'
10+
import {
11+
QueryCompiler,
12+
RootOperationNode,
13+
} from '../../query-compiler/query-compiler.js'
714
import { isFunction, freeze } from '../../util/object-utils.js'
815
import { extendStackTrace } from '../../util/stack-trace-utils.js'
916
import {
@@ -78,6 +85,36 @@ export class PostgresDriver implements Driver {
7885
await connection.executeQuery(CompiledQuery.raw('rollback'))
7986
}
8087

88+
async savepoint(
89+
connection: DatabaseConnection,
90+
savepointName: string,
91+
compileQuery: QueryCompiler['compileQuery'],
92+
): Promise<void> {
93+
await connection.executeQuery(
94+
compileQuery(parseSavepointCommand('savepoint', savepointName)),
95+
)
96+
}
97+
98+
async rollbackToSavepoint(
99+
connection: DatabaseConnection,
100+
savepointName: string,
101+
compileQuery: QueryCompiler['compileQuery'],
102+
): Promise<void> {
103+
await connection.executeQuery(
104+
compileQuery(parseSavepointCommand('rollback to', savepointName)),
105+
)
106+
}
107+
108+
async releaseSavepoint(
109+
connection: DatabaseConnection,
110+
savepointName: string,
111+
compileQuery: QueryCompiler['compileQuery'],
112+
): Promise<void> {
113+
await connection.executeQuery(
114+
compileQuery(parseSavepointCommand('release', savepointName)),
115+
)
116+
}
117+
81118
async releaseConnection(connection: PostgresConnection): Promise<void> {
82119
connection[PRIVATE_RELEASE_METHOD]()
83120
}

src/dialect/sqlite/sqlite-driver.ts

+32
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import {
44
} from '../../driver/database-connection.js'
55
import { Driver } from '../../driver/driver.js'
66
import { SelectQueryNode } from '../../operation-node/select-query-node.js'
7+
import { parseSavepointCommand } from '../../parser/savepoint-parser.js'
78
import { CompiledQuery } from '../../query-compiler/compiled-query.js'
9+
import { QueryCompiler } from '../../query-compiler/query-compiler.js'
810
import { freeze, isFunction } from '../../util/object-utils.js'
911
import { SqliteDatabase, SqliteDialectConfig } from './sqlite-dialect-config.js'
1012

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

55+
async savepoint(
56+
connection: DatabaseConnection,
57+
savepointName: string,
58+
compileQuery: QueryCompiler['compileQuery'],
59+
): Promise<void> {
60+
await connection.executeQuery(
61+
compileQuery(parseSavepointCommand('savepoint', savepointName)),
62+
)
63+
}
64+
65+
async rollbackToSavepoint(
66+
connection: DatabaseConnection,
67+
savepointName: string,
68+
compileQuery: QueryCompiler['compileQuery'],
69+
): Promise<void> {
70+
await connection.executeQuery(
71+
compileQuery(parseSavepointCommand('rollback to', savepointName)),
72+
)
73+
}
74+
75+
async releaseSavepoint(
76+
connection: DatabaseConnection,
77+
savepointName: string,
78+
compileQuery: QueryCompiler['compileQuery'],
79+
): Promise<void> {
80+
await connection.executeQuery(
81+
compileQuery(parseSavepointCommand('release', savepointName)),
82+
)
83+
}
84+
5385
async releaseConnection(): Promise<void> {
5486
this.#connectionMutex.unlock()
5587
}

src/driver/driver.ts

+28
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QueryCompiler } from '../query-compiler/query-compiler.js'
12
import { ArrayItemType } from '../util/type-utils.js'
23
import { DatabaseConnection } from './database-connection.js'
34

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

41+
/**
42+
* Establishses a new savepoint within a transaction.
43+
*/
44+
savepoint?(
45+
connection: DatabaseConnection,
46+
savepointName: string,
47+
compileQuery: QueryCompiler['compileQuery'],
48+
): Promise<void>
49+
50+
/**
51+
* Rolls back to a savepoint within a transaction.
52+
*/
53+
rollbackToSavepoint?(
54+
connection: DatabaseConnection,
55+
savepointName: string,
56+
compileQuery: QueryCompiler['compileQuery'],
57+
): Promise<void>
58+
59+
/**
60+
* Releases a savepoint within a transaction.
61+
*/
62+
releaseSavepoint?(
63+
connection: DatabaseConnection,
64+
savepointName: string,
65+
compileQuery: QueryCompiler['compileQuery'],
66+
): Promise<void>
67+
4068
/**
4169
* Releases a connection back to the pool.
4270
*/

src/driver/dummy-driver.ts

+12
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ export class DummyDriver implements Driver {
6565
async destroy(): Promise<void> {
6666
// Nothing to do here.
6767
}
68+
69+
async releaseSavepoint(): Promise<void> {
70+
// Nothing to do here.
71+
}
72+
73+
async rollbackToSavepoint(): Promise<void> {
74+
// Nothing to do here.
75+
}
76+
77+
async savepoint(): Promise<void> {
78+
// Nothing to do here.
79+
}
6880
}
6981

7082
class DummyConnection implements DatabaseConnection {

src/driver/runtime-driver.ts

+49
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { CompiledQuery } from '../query-compiler/compiled-query.js'
2+
import { QueryCompiler } from '../query-compiler/query-compiler.js'
23
import { Log } from '../util/log.js'
34
import { performanceNow } from '../util/performance-now.js'
45
import { DatabaseConnection, QueryResult } from './database-connection.js'
@@ -85,6 +86,54 @@ export class RuntimeDriver implements Driver {
8586
return this.#driver.rollbackTransaction(connection)
8687
}
8788

89+
savepoint(
90+
connection: DatabaseConnection,
91+
savepointName: string,
92+
compileQuery: QueryCompiler['compileQuery'],
93+
): Promise<void> {
94+
if (this.#driver.savepoint) {
95+
return this.#driver.savepoint(connection, savepointName, compileQuery)
96+
}
97+
98+
throw new Error('The `savepoint` method is not supported by this driver')
99+
}
100+
101+
rollbackToSavepoint(
102+
connection: DatabaseConnection,
103+
savepointName: string,
104+
compileQuery: QueryCompiler['compileQuery'],
105+
): Promise<void> {
106+
if (this.#driver.rollbackToSavepoint) {
107+
return this.#driver.rollbackToSavepoint(
108+
connection,
109+
savepointName,
110+
compileQuery,
111+
)
112+
}
113+
114+
throw new Error(
115+
'The `rollbackToSavepoint` method is not supported by this driver',
116+
)
117+
}
118+
119+
releaseSavepoint(
120+
connection: DatabaseConnection,
121+
savepointName: string,
122+
compileQuery: QueryCompiler['compileQuery'],
123+
): Promise<void> {
124+
if (this.#driver.releaseSavepoint) {
125+
return this.#driver.releaseSavepoint(
126+
connection,
127+
savepointName,
128+
compileQuery,
129+
)
130+
}
131+
132+
throw new Error(
133+
'The `releaseSavepoint` method is not supported by this driver',
134+
)
135+
}
136+
88137
async destroy(): Promise<void> {
89138
if (!this.#initPromise) {
90139
return

0 commit comments

Comments
 (0)