@ogc/postgres-tmp
Version:
Fastest full featured PostgreSQL client for Node.js
174 lines (143 loc) • 3.6 kB
JavaScript
const originCache = new Map()
, originStackCache = new Map()
, originError = Symbol('OriginError')
export const CLOSE = {}
export class Query extends Promise {
constructor(strings, args, handler, canceller, options = {}) {
let resolve
, reject
super((a, b) => {
resolve = a
reject = b
})
this.tagged = Array.isArray(strings.raw)
this.strings = strings
this.args = args
this.handler = handler
this.canceller = canceller
this.options = options
this.state = null
this.statement = null
this.resolve = x => (this.active = false, resolve(x))
this.reject = x => (this.active = false, reject(x))
this.active = false
this.cancelled = null
this.executed = false
this.signature = ''
this[originError] = this.handler.debug
? new Error()
: this.tagged && cachedError(this.strings)
}
get origin() {
return (this.handler.debug
? this[originError].stack
: this.tagged && originStackCache.has(this.strings)
? originStackCache.get(this.strings)
: originStackCache.set(this.strings, this[originError].stack).get(this.strings)
) || ''
}
static get [Symbol.species]() {
return Promise
}
cancel() {
return this.canceller && (this.canceller(this), this.canceller = null)
}
simple() {
this.options.simple = true
this.options.prepare = false
return this
}
async readable() {
this.simple()
this.streaming = true
return this
}
async writable() {
this.simple()
this.streaming = true
return this
}
cursor(rows = 1, fn) {
this.options.simple = false
if (typeof rows === 'function') {
fn = rows
rows = 1
}
this.cursorRows = rows
if (typeof fn === 'function')
return (this.cursorFn = fn, this)
let prev
return {
[Symbol.asyncIterator]: () => ({
next: () => {
if (this.executed && !this.active)
return { done: true }
prev && prev()
const promise = new Promise((resolve, reject) => {
this.cursorFn = value => {
resolve({ value, done: false })
return new Promise(r => prev = r)
}
this.resolve = () => (this.active = false, resolve({ done: true }))
this.reject = x => (this.active = false, reject(x))
})
this.execute()
return promise
},
return() {
prev && prev(CLOSE)
return { done: true }
}
})
}
}
describe() {
this.options.simple = false
this.onlyDescribe = this.options.prepare = true
return this
}
stream() {
throw new Error('.stream has been renamed to .forEach')
}
forEach(fn) {
this.forEachFn = fn
this.handle()
return this
}
raw() {
this.isRaw = true
return this
}
values() {
this.isRaw = 'values'
return this
}
async handle() {
!this.executed && (this.executed = true) && await 1 && this.handler(this)
}
execute() {
this.handle()
return this
}
then() {
this.handle()
return super.then.apply(this, arguments)
}
catch() {
this.handle()
return super.catch.apply(this, arguments)
}
finally() {
this.handle()
return super.finally.apply(this, arguments)
}
}
function cachedError(xs) {
if (originCache.has(xs))
return originCache.get(xs)
const x = Error.stackTraceLimit
Error.stackTraceLimit = 4
originCache.set(xs, new Error())
Error.stackTraceLimit = x
return originCache.get(xs)
}