| 249 | } |
| 250 | |
| 251 | async function scope(c, fn, name) { |
| 252 | const sql = Sql(handler) |
| 253 | sql.savepoint = savepoint |
| 254 | sql.prepare = x => prepare = x.replace(/[^a-z0-9$-_. ]/gi) |
| 255 | let uncaughtError |
| 256 | , result |
| 257 | |
| 258 | name && await sql`savepoint ${ sql(name) }` |
| 259 | try { |
| 260 | result = await new Promise((resolve, reject) => { |
| 261 | const x = fn(sql) |
| 262 | Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(resolve, reject) |
| 263 | }) |
| 264 | |
| 265 | if (uncaughtError) |
| 266 | throw uncaughtError |
| 267 | } catch (e) { |
| 268 | await (name |
| 269 | ? sql`rollback to ${ sql(name) }` |
| 270 | : sql`rollback` |
| 271 | ) |
| 272 | throw e instanceof PostgresError && e.code === '25P02' && uncaughtError || e |
| 273 | } |
| 274 | |
| 275 | if (!name) { |
| 276 | prepare |
| 277 | ? await sql`prepare transaction '${ sql.unsafe(prepare) }'` |
| 278 | : await sql`commit` |
| 279 | } |
| 280 | |
| 281 | return result |
| 282 | |
| 283 | function savepoint(name, fn) { |
| 284 | if (name && Array.isArray(name.raw)) |
| 285 | return savepoint(sql => sql.apply(sql, arguments)) |
| 286 | |
| 287 | arguments.length === 1 && (fn = name, name = null) |
| 288 | return scope(c, fn, 's' + savepoints++ + (name ? '_' + name : '')) |
| 289 | } |
| 290 | |
| 291 | function handler(q) { |
| 292 | q.catch(e => uncaughtError || (uncaughtError = e)) |
| 293 | c.queue === full |
| 294 | ? queries.push(q) |
| 295 | : c.execute(q) || move(c, full) |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | function onexecute(c) { |
| 300 | connection = c |