@@ -13,9 +13,21 @@ import {
13
13
toCamel ,
14
14
toKebab ,
15
15
errors ,
16
+ escape ,
16
17
types
17
18
} from './types.js'
18
19
20
+ const notPromise = {
21
+ P : { } ,
22
+ finally : notTagged ,
23
+ then : notTagged ,
24
+ catch : notTagged
25
+ }
26
+
27
+ function notTagged ( ) {
28
+ throw errors . generic ( { message : 'Query not called as a tagged template literal' , code : 'NOT_TAGGED_CALL' } )
29
+ }
30
+
19
31
Object . assign ( Postgres , {
20
32
toPascal,
21
33
toCamel,
@@ -37,6 +49,8 @@ export default function Postgres(url, options) {
37
49
, listeners = { }
38
50
, typeArrayMap = { }
39
51
, files = { }
52
+ , isInsert = / ( ^ | \) ) \s * i n s e r t \s * i n t o \s / i
53
+ , isSelect = / ( ^ | \) ) \s * s e l e c t \s / i
40
54
41
55
function postgres ( xs , ...args ) {
42
56
return query ( { } , getConnection ( ) , xs , args )
@@ -138,7 +152,7 @@ export default function Postgres(url, options) {
138
152
139
153
function query ( query , connection , xs , args ) {
140
154
if ( ! query . raw && ( ! Array . isArray ( xs ) || ! Array . isArray ( xs . raw ) ) )
141
- throw errors . generic ( { message : 'Query not called as a tagged template literal' , code : 'NOT_TAGGED_CALL' } )
155
+ return nested ( xs , args )
142
156
143
157
const promise = new Promise ( ( resolve , reject ) => {
144
158
query . resolve = resolve
@@ -155,6 +169,13 @@ export default function Postgres(url, options) {
155
169
return promise
156
170
}
157
171
172
+ function nested ( first , rest ) {
173
+ const o = Object . create ( notPromise )
174
+ o . first = first
175
+ o . rest = rest
176
+ return o
177
+ }
178
+
158
179
function send ( connection , query , xs , args ) {
159
180
connection
160
181
? connection . send ( query , query . raw ? parseRaw ( xs , args ) : parse ( xs , args ) )
@@ -206,22 +227,6 @@ export default function Postgres(url, options) {
206
227
}
207
228
}
208
229
209
- function rows ( rows , ...args ) {
210
- return {
211
- rows : typeof args [ 0 ] === 'string'
212
- ? rows . map ( x => Array . isArray ( x ) ? x : args . map ( a => x [ a ] ) ) // pluck
213
- : typeof args [ 0 ] === 'function'
214
- ? rows . map ( x => args [ 0 ] ( x ) ) // map
215
- : rows
216
- }
217
- }
218
-
219
- function row ( row , ...args ) {
220
- return {
221
- row : args . map ( a => row [ a ] )
222
- }
223
- }
224
-
225
230
function array ( value ) {
226
231
return {
227
232
type : inferType ( value ) || 25 ,
@@ -267,9 +272,7 @@ export default function Postgres(url, options) {
267
272
unsafe,
268
273
array,
269
274
file,
270
- json,
271
- rows,
272
- row
275
+ json
273
276
} )
274
277
275
278
function notify ( channel , payload ) {
@@ -380,13 +383,9 @@ export default function Postgres(url, options) {
380
383
381
384
for ( let i = 1 ; i < xs . length ; i ++ ) {
382
385
arg = args [ i - 1 ]
383
- str += ( ! arg
384
- ? parseValue ( arg , xargs , types )
385
- : arg . rows
386
- ? parseRows ( arg . rows , xargs , types )
387
- : arg . row
388
- ? parseRow ( arg . row , xargs , types )
389
- : parseValue ( arg , xargs , types )
386
+ str += ( arg && arg . P === notPromise . P
387
+ ? parseHelper ( str , arg , xargs , types )
388
+ : parseValue ( arg , xargs , types )
390
389
) + xs [ i ]
391
390
}
392
391
@@ -397,19 +396,66 @@ export default function Postgres(url, options) {
397
396
}
398
397
}
399
398
400
- function parseRows ( rows , xargs , types ) {
401
- xargs . dynamic = true
402
- return rows . map ( row => parseRow ( row , xargs , types ) ) . join ( ',' )
399
+ function parseHelper ( str , { first, rest } , xargs , types ) {
400
+ if ( first !== null && typeof first === 'object' && typeof first [ 0 ] !== 'string' ) {
401
+ if ( isInsert . test ( str ) )
402
+ return insertHelper ( first , rest , xargs , types )
403
+ else if ( isSelect . test ( str ) )
404
+ return selectHelper ( first , rest , xargs , types )
405
+ else if ( ! Array . isArray ( first ) )
406
+ return equalsHelper ( first , rest , xargs , types )
407
+ }
408
+
409
+ return escapeHelper ( Array . isArray ( first ) ? first : [ first ] . concat ( rest ) )
403
410
}
404
411
405
- function parseRow ( row , xargs , types ) {
406
- return '(' + row . map ( x => parseValue ( x , xargs , types ) ) . join ( ',' ) + ')'
412
+ function selectHelper ( first , columns , xargs , types ) {
413
+ return Object . entries ( first ) . reduce ( ( acc , [ k , v ] ) =>
414
+ acc + ( ! columns . length || columns . indexOf ( k ) > - 1
415
+ ? ( acc ? ', ' : '' ) + parseValue ( v , xargs , types ) + ' as ' + escape ( k )
416
+ : ''
417
+ )
418
+ , '' )
419
+ }
420
+
421
+ function insertHelper ( first , columns , xargs , types ) {
422
+ first = Array . isArray ( first ) ? first : [ first ]
423
+ return '(' + escapeHelper ( Object . keys ( first [ 0 ] ) ) + ') values ' +
424
+ first . map ( row =>
425
+ '(' + Object . entries ( row ) . reduce ( ( acc , [ k , v ] ) =>
426
+ acc + ( ! columns . length || columns . indexOf ( k ) > - 1
427
+ ? ( acc ? ', ' : '' ) + parseValue ( v , xargs , types )
428
+ : ''
429
+ )
430
+ , '' ) + ')'
431
+ ) . join ( ', ' )
432
+ }
433
+
434
+ function equalsHelper ( first , columns , xargs , types ) {
435
+ return Object . entries ( first ) . reduce ( ( acc , [ k , v ] ) =>
436
+ acc + ( ! columns . length || columns . indexOf ( k ) > - 1
437
+ ? ( acc ? ', ' : '' ) + escape ( k ) + ' = ' + parseValue ( v , xargs , types )
438
+ : ''
439
+ )
440
+ , '' )
441
+ }
442
+
443
+ function escapeHelper ( xs ) {
444
+ return xs . reduce ( ( acc , x ) => acc + ( acc ? ', ' : '' ) + escape ( x ) , '' )
407
445
}
408
446
409
447
function parseValue ( x , xargs , types ) {
448
+ return Array . isArray ( x )
449
+ ? x . reduce ( ( acc , x ) => addValue ( x , xargs , types ) , '' )
450
+ : addValue ( x , xargs , types )
451
+ }
452
+
453
+ function addValue ( x , xargs , types ) {
410
454
const type = getType ( x )
411
- types . push ( type . type )
412
- return '$' + xargs . push ( type )
455
+ , i = types . push ( type - type )
456
+
457
+ xargs . push ( type )
458
+ return '$' + i
413
459
}
414
460
415
461
function getType ( x ) {
0 commit comments