Skip to content

Commit 60c47c4

Browse files
authored
Fix handling of transactions with explicit isolation level (#3)
1 parent b393995 commit 60c47c4

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

src/connection.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {CompiledQuery, DatabaseConnection, QueryResult, TransactionSettings} from 'kysely'
1+
import {CompiledQuery, DatabaseConnection, QueryResult, TransactionSettings} from 'kysely'
22
import type {Sql} from 'postgres'
33

44
import {PostgresJSDialectError} from './errors.js'
@@ -24,17 +24,19 @@ export class PostgresJSConnection implements DatabaseConnection {
2424

2525
this.#transaction = createPostgres({...this.#config, options: {...this.#config.options, max: 1}})
2626

27-
const statement = `start transaction${isolationLevel ? ` ${isolationLevel}` : ''}`
27+
const compiledQuery = CompiledQuery.raw(
28+
isolationLevel ? `start transaction isolation level ${isolationLevel}` : 'begin',
29+
)
2830

29-
await this.#transaction.unsafe(statement)
31+
await this.executeQuery(compiledQuery)
3032
}
3133

3234
async commitTransaction(): Promise<void> {
3335
if (!this.#transaction) {
3436
throw new PostgresJSDialectError('no transaction to commit!')
3537
}
3638

37-
await this.#transaction`commit`
39+
await this.executeQuery(CompiledQuery.raw('commit'))
3840

3941
this.#releaseTransaction()
4042
}
@@ -58,7 +60,7 @@ export class PostgresJSConnection implements DatabaseConnection {
5860
throw new PostgresJSDialectError('no transaction to rollback!')
5961
}
6062

61-
await this.#transaction`rollback`
63+
await this.executeQuery(CompiledQuery.raw('rollback'))
6264

6365
this.#releaseTransaction()
6466
}

tests/nodejs/index.test.ts

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {DeleteResult, InsertResult, UpdateResult, sql, type Kysely, type Transaction} from 'kysely'
1+
import {CompiledQuery, DeleteResult, InsertResult, UpdateResult, sql, type Kysely, type Transaction} from 'kysely'
22

33
import {
44
CONFIGS,
@@ -19,13 +19,19 @@ import {
1919

2020
forEach(CONFIGS).describe('PostgresJSDialect: %s', (config: TestConfig) => {
2121
let ctx: TestContext
22+
let executedQueries: CompiledQuery[] = []
2223

2324
before(async function () {
24-
ctx = await initTest(this, config.config)
25+
ctx = await initTest(this, config.config, (event) => {
26+
if (event.level === 'query') {
27+
executedQueries.push(event.query)
28+
}
29+
})
2530
})
2631

2732
beforeEach(async () => {
2833
await insertDefaultDataSet(ctx)
34+
executedQueries = []
2935
})
3036

3137
afterEach(async () => {
@@ -87,6 +93,57 @@ forEach(CONFIGS).describe('PostgresJSDialect: %s', (config: TestConfig) => {
8793
}
8894
})
8995

96+
it('should set the transaction isolation level', async () => {
97+
await ctx.db
98+
.transaction()
99+
.setIsolationLevel('serializable')
100+
.execute(async (trx) => {
101+
await trx
102+
.insertInto('person')
103+
.values({
104+
first_name: 'Foo',
105+
last_name: 'Barson',
106+
gender: 'male',
107+
})
108+
.execute()
109+
})
110+
111+
expect(
112+
executedQueries.map((it) => ({
113+
sql: it.sql,
114+
parameters: it.parameters,
115+
})),
116+
).to.eql([
117+
{
118+
sql: 'start transaction isolation level serializable',
119+
parameters: [],
120+
},
121+
{
122+
sql: 'insert into "person" ("first_name", "last_name", "gender") values ($1, $2, $3)',
123+
parameters: ['Foo', 'Barson', 'male'],
124+
},
125+
{sql: 'commit', parameters: []},
126+
])
127+
})
128+
129+
it('should be able to start a transaction with a single connection', async () => {
130+
const result = await ctx.db.connection().execute((db) => {
131+
return db.transaction().execute((trx) => {
132+
return trx
133+
.insertInto('person')
134+
.values({
135+
first_name: 'Foo',
136+
last_name: 'Barson',
137+
gender: 'male',
138+
})
139+
.returning('first_name')
140+
.executeTakeFirstOrThrow()
141+
})
142+
})
143+
144+
expect(result.first_name).to.equal('Foo')
145+
})
146+
90147
it('should stream results', async () => {
91148
const males: unknown[] = []
92149

0 commit comments

Comments
 (0)