Skip to content

Commit e2a7b22

Browse files
committed
Add support for unsafe (raw) queries
1 parent b3c1dd5 commit e2a7b22

File tree

1 file changed

+41
-20
lines changed

1 file changed

+41
-20
lines changed

lib/index.js

+41-20
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default function Postgres(url, options) {
3737
, typeArrayMap = {}
3838

3939
function postgres(xs, ...args) {
40-
return query(getConnection(), xs, args)
40+
return query(false, getConnection(), xs, args)
4141
}
4242

4343
Object.assign(postgres, {
@@ -74,7 +74,7 @@ export default function Postgres(url, options) {
7474
savepoint = ''
7575
}, connection) {
7676
begin && (connection.savepoints = 0)
77-
addTypes(scoped)
77+
addTypes(scoped, connection)
7878
scoped.savepoint = (name, fn) => new Promise((resolve, reject) => {
7979
transaction({
8080
savepoint: 'savepoint s' + connection.savepoints++ + '_' + (fn ? name : ''),
@@ -84,7 +84,7 @@ export default function Postgres(url, options) {
8484
}, connection)
8585
})
8686

87-
query(connection, raw(begin || savepoint))
87+
query(true, connection, begin || savepoint)
8888
.then(() => {
8989
const result = fn(scoped)
9090
return (Array.isArray(result)
@@ -98,11 +98,11 @@ export default function Postgres(url, options) {
9898
: resolve(x)
9999
)
100100
.catch((err) => {
101-
query(connection, raw(
101+
query(true, connection,
102102
begin
103103
? 'rollback'
104104
: 'rollback to ' + savepoint
105-
))
105+
)
106106
.then(() => reject(err))
107107
})
108108
.then(() => {
@@ -111,7 +111,7 @@ export default function Postgres(url, options) {
111111
})
112112

113113
function scoped(xs, ...args) {
114-
return query(connection, xs, args).catch(err => {
114+
return query(false, connection, xs, args).catch(err => {
115115
reject(err)
116116
throw err
117117
})
@@ -128,15 +128,15 @@ export default function Postgres(url, options) {
128128
while ((x = queries.shift()) && (c = getConnection(x.fn))) {
129129
x.fn
130130
? transaction(x, c)
131-
: c.send(x.query, parse(x.xs, x.args))
131+
: send(c, x.query, x.xs, x.args)
132132
}
133133
}
134134

135-
function query(connection, xs, args) {
136-
if (!Array.isArray(xs) || !Array.isArray(xs.raw))
135+
function query(raw, connection, xs, args) {
136+
if (!raw && (!Array.isArray(xs) || !Array.isArray(xs.raw)))
137137
throw errors.generic({ message: 'Query not called as a tagged template literal', code: 'NOT_TAGGED_CALL' })
138138

139-
const query = {}
139+
const query = { raw }
140140

141141
const promise = new Promise((resolve, reject) => {
142142
query.resolve = resolve
@@ -156,7 +156,7 @@ export default function Postgres(url, options) {
156156

157157
function send(connection, query, xs, args) {
158158
connection
159-
? connection.send(query, parse(xs, args))
159+
? connection.send(query, query.raw ? parseRaw(xs, args) : parse(xs, args))
160160
: queries.push({ query, xs, args })
161161
}
162162

@@ -179,11 +179,11 @@ export default function Postgres(url, options) {
179179

180180
function instance({ fn }, connection) {
181181
let queries = 0
182-
addTypes(scoped)
182+
addTypes(scoped, connection)
183183
const container = fn(scoped)
184184
function scoped(xs, ...args) {
185185
queries++
186-
const promise = query(connection, xs, args)
186+
const promise = query(false, connection, xs, args)
187187
promise.then(finished, finished)
188188
return promise
189189
}
@@ -230,11 +230,11 @@ export default function Postgres(url, options) {
230230
function fetchArrayTypes(connection) {
231231
return arrayTypesPromise || (arrayTypesPromise =
232232
new Promise((resolve, reject) => {
233-
send(connection, { resolve, reject }, raw(`
233+
send(connection, { resolve, reject, raw: true }, `
234234
select oid, typelem
235235
from pg_catalog.pg_type
236236
where typcategory = 'A'
237-
`))
237+
`)
238238
}).then(types => {
239239
types.forEach(({ oid, typelem }) => addArrayType(oid, typelem))
240240
ready = true
@@ -251,9 +251,10 @@ export default function Postgres(url, options) {
251251
options.serializers[oid] = (xs) => arraySerializer(xs, serializer)
252252
}
253253

254-
function addTypes(instance) {
254+
function addTypes(instance, connection) {
255255
Object.assign(instance, {
256256
notify: (channel, payload) => instance`select pg_notify(${ channel }, ${ String(payload) })`,
257+
unsafe: (xs, args) => query(true, connection || getConnection(), xs, args),
257258
array,
258259
rows,
259260
row,
@@ -276,7 +277,7 @@ export default function Postgres(url, options) {
276277
? listeners[x].push(fn)
277278
: (listeners[x] = [fn])
278279

279-
return query(getListener(), raw('listen "' + x + '"')).then(() => x)
280+
return query(true, getListener(), 'listen "' + x + '"').then(() => x)
280281
}
281282

282283
function getListener() {
@@ -311,6 +312,21 @@ export default function Postgres(url, options) {
311312
.then(() => clearTimeout(destroy))
312313
}
313314

315+
function parseRaw(str, args = []) {
316+
const types = []
317+
, xargs = args.map(x => {
318+
const type = getType(x)
319+
types.push(type.type)
320+
return type
321+
})
322+
323+
return {
324+
sig: types + str,
325+
str,
326+
args: xargs
327+
}
328+
}
329+
314330
function parse(xs, args = []) {
315331
const xargs = []
316332
, types = []
@@ -345,16 +361,21 @@ export default function Postgres(url, options) {
345361
}
346362

347363
function parseValue(x, xargs, types) {
364+
const type = getType(x)
365+
types.push(type.type)
366+
return '$' + xargs.push(type)
367+
}
368+
369+
function getType(x) {
348370
const value = x.value ? x.value : x
349371
, type = x.type || (Array.isArray(value) ? typeArrayMap[inferType(value)] : inferType(value))
350372

351-
types.push(type)
352-
return '$' + xargs.push({
373+
return {
353374
type,
354375
value: type
355376
? (options.serializers[type] || types.string.serialize)(value)
356377
: value
357-
})
378+
}
358379
}
359380
}
360381

0 commit comments

Comments
 (0)