Skip to content

Commit f7c8ae6

Browse files
committed
Transaction rejects with rethrown error - fixes #289
1 parent a782edf commit f7c8ae6

File tree

9 files changed

+71
-24
lines changed

9 files changed

+71
-24
lines changed

cjs/src/index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,22 +198,25 @@ function Postgres(a, b) {
198198
async function scope(c, fn, name) {
199199
const sql = Sql(handler, true)
200200
sql.savepoint = savepoint
201-
let errored
201+
let uncaughtError
202202
name && await sql`savepoint ${ sql(name) }`
203203
try {
204204
const result = await new Promise((resolve, reject) => {
205-
errored = reject
206205
const x = fn(sql)
207206
Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(resolve, reject)
208207
})
208+
209+
if (uncaughtError)
210+
throw uncaughtError
211+
209212
!name && await sql`commit`
210213
return result
211214
} catch (e) {
212215
await (name
213216
? sql`rollback to ${ sql(name) }`
214217
: sql`rollback`
215218
)
216-
throw e
219+
throw e instanceof PostgresError && e.code === '25P02' && uncaughtError || e
217220
}
218221

219222
function savepoint(name, fn) {
@@ -225,7 +228,7 @@ function Postgres(a, b) {
225228
}
226229

227230
function handler(q) {
228-
errored && q.catch(errored)
231+
q.catch(e => uncaughtError || (uncaughtError = e))
229232
c.state === 'full'
230233
? queries.push(q)
231234
: c.execute(q) || (c.state = 'full', full.push(c))

cjs/src/query.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,19 @@ const Query = module.exports.Query = class Query extends Promise {
3131
this.executed = false
3232
this.signature = ''
3333

34-
this[originError] = handler.debug || !this.tagged
34+
this[originError] = this.handler.debug
3535
? new Error()
36-
: cachedError(this.strings)
36+
: this.tagged && cachedError(this.strings)
3737
}
3838

3939
get origin() {
40-
return this.handler.debug || !this.tagged
40+
return this.handler.debug
4141
? this[originError].stack
42-
: originStackCache.has(this.strings)
43-
? originStackCache.get(this.strings)
44-
: originStackCache.set(this.strings, this[originError].stack).get(this.strings)
42+
: this.tagged
43+
? originStackCache.has(this.strings)
44+
? originStackCache.get(this.strings)
45+
: originStackCache.set(this.strings, this[originError].stack).get(this.strings)
46+
: ''
4547
}
4648

4749
static get [Symbol.species]() {

cjs/src/subscribe.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module.exports = Subscribe;function Subscribe(postgres, options) {
88

99
options.max = 1
1010
options.onclose = onclose
11+
options.fetch_types = false
1112
options.connection = {
1213
...options.connection,
1314
replication: 'database'

cjs/tests/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ t('Uncaught transaction request errors bubbles to transaction', async() => [
254254
)).catch(e => e.code))
255255
])
256256

257+
t('Transaction rejects with rethrown error', async() => [
258+
'WAT',
259+
await sql.begin(async sql => {
260+
try {
261+
await sql`select exception`
262+
} catch (ex) {
263+
throw new Error('WAT')
264+
}
265+
}).catch(e => e.message)
266+
])
267+
257268
t('Parallel transactions', async() => {
258269
await sql`create table test (a int)`
259270
return ['11', (await Promise.all([

deno/src/index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,22 +199,25 @@ function Postgres(a, b) {
199199
async function scope(c, fn, name) {
200200
const sql = Sql(handler, true)
201201
sql.savepoint = savepoint
202-
let errored
202+
let uncaughtError
203203
name && await sql`savepoint ${ sql(name) }`
204204
try {
205205
const result = await new Promise((resolve, reject) => {
206-
errored = reject
207206
const x = fn(sql)
208207
Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(resolve, reject)
209208
})
209+
210+
if (uncaughtError)
211+
throw uncaughtError
212+
210213
!name && await sql`commit`
211214
return result
212215
} catch (e) {
213216
await (name
214217
? sql`rollback to ${ sql(name) }`
215218
: sql`rollback`
216219
)
217-
throw e
220+
throw e instanceof PostgresError && e.code === '25P02' && uncaughtError || e
218221
}
219222

220223
function savepoint(name, fn) {
@@ -226,7 +229,7 @@ function Postgres(a, b) {
226229
}
227230

228231
function handler(q) {
229-
errored && q.catch(errored)
232+
q.catch(e => uncaughtError || (uncaughtError = e))
230233
c.state === 'full'
231234
? queries.push(q)
232235
: c.execute(q) || (c.state = 'full', full.push(c))

deno/src/query.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,19 @@ export class Query extends Promise {
3131
this.executed = false
3232
this.signature = ''
3333

34-
this[originError] = handler.debug || !this.tagged
34+
this[originError] = this.handler.debug
3535
? new Error()
36-
: cachedError(this.strings)
36+
: this.tagged && cachedError(this.strings)
3737
}
3838

3939
get origin() {
40-
return this.handler.debug || !this.tagged
40+
return this.handler.debug
4141
? this[originError].stack
42-
: originStackCache.has(this.strings)
43-
? originStackCache.get(this.strings)
44-
: originStackCache.set(this.strings, this[originError].stack).get(this.strings)
42+
: this.tagged
43+
? originStackCache.has(this.strings)
44+
? originStackCache.get(this.strings)
45+
: originStackCache.set(this.strings, this[originError].stack).get(this.strings)
46+
: ''
4547
}
4648

4749
static get [Symbol.species]() {

deno/tests/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,17 @@ t('Uncaught transaction request errors bubbles to transaction', async() => [
255255
)).catch(e => e.code))
256256
])
257257

258+
t('Transaction rejects with rethrown error', async() => [
259+
'WAT',
260+
await sql.begin(async sql => {
261+
try {
262+
await sql`select exception`
263+
} catch (ex) {
264+
throw new Error('WAT')
265+
}
266+
}).catch(e => e.message)
267+
])
268+
258269
t('Parallel transactions', async() => {
259270
await sql`create table test (a int)`
260271
return ['11', (await Promise.all([

src/index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,22 +198,25 @@ function Postgres(a, b) {
198198
async function scope(c, fn, name) {
199199
const sql = Sql(handler, true)
200200
sql.savepoint = savepoint
201-
let errored
201+
let uncaughtError
202202
name && await sql`savepoint ${ sql(name) }`
203203
try {
204204
const result = await new Promise((resolve, reject) => {
205-
errored = reject
206205
const x = fn(sql)
207206
Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(resolve, reject)
208207
})
208+
209+
if (uncaughtError)
210+
throw uncaughtError
211+
209212
!name && await sql`commit`
210213
return result
211214
} catch (e) {
212215
await (name
213216
? sql`rollback to ${ sql(name) }`
214217
: sql`rollback`
215218
)
216-
throw e
219+
throw e instanceof PostgresError && e.code === '25P02' && uncaughtError || e
217220
}
218221

219222
function savepoint(name, fn) {
@@ -225,7 +228,7 @@ function Postgres(a, b) {
225228
}
226229

227230
function handler(q) {
228-
errored && q.catch(errored)
231+
q.catch(e => uncaughtError || (uncaughtError = e))
229232
c.state === 'full'
230233
? queries.push(q)
231234
: c.execute(q) || (c.state = 'full', full.push(c))

tests/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ t('Uncaught transaction request errors bubbles to transaction', async() => [
254254
)).catch(e => e.code))
255255
])
256256

257+
t('Transaction rejects with rethrown error', async() => [
258+
'WAT',
259+
await sql.begin(async sql => {
260+
try {
261+
await sql`select exception`
262+
} catch (ex) {
263+
throw new Error('WAT')
264+
}
265+
}).catch(e => e.message)
266+
])
267+
257268
t('Parallel transactions', async() => {
258269
await sql`create table test (a int)`
259270
return ['11', (await Promise.all([

0 commit comments

Comments
 (0)