Skip to content

Commit 211f6b9

Browse files
committed
build
1 parent b250eae commit 211f6b9

File tree

7 files changed

+121
-9
lines changed

7 files changed

+121
-9
lines changed

cjs/src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@ function Postgres(a, b) {
176176
return { state: result.state, unlisten }
177177
}
178178

179-
channels[name] = { result: sql`listen ${ sql(name) }`, listeners: [listener] }
179+
channels[name] = { result: sql`listen ${
180+
sql.unsafe('"' + name.replace(/"/g, '""') + '"')
181+
}`, listeners: [listener] }
180182
const result = await channels[name].result
181183
listener.onlisten && listener.onlisten()
182184
return { state: result.state, unlisten }

cjs/src/types.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,9 @@ const fromKebab = module.exports.fromKebab = x => x.replace(/-/g, '_')
325325

326326
function createJsonTransform(fn) {
327327
return function jsonTransform(x, column) {
328-
return column.type === 114 || column.type === 3802
328+
return typeof x === 'object' && x !== null && (column.type === 114 || column.type === 3802)
329329
? Array.isArray(x)
330-
? x.map(jsonTransform)
330+
? x.map(x => jsonTransform(x, column))
331331
: Object.entries(x).reduce((acc, [k, v]) => Object.assign(acc, { [fn(k)]: v }), {})
332332
: x
333333
}

cjs/tests/index.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,46 @@ t('column toKebab', async() => {
604604
return ['hello-world', Object.keys((await sql`select * from test`)[0])[0], await sql`drop table test`]
605605
})
606606

607+
t('Transform nested json in arrays', async() => {
608+
const sql = postgres({
609+
...options,
610+
transform: postgres.camel
611+
})
612+
return ['aBcD', (await sql`select '[{"a_b":1},{"c_d":2}]'::jsonb as x`)[0].x.map(Object.keys).join('')]
613+
})
614+
615+
t('Bypass transform for json primitive', async () => {
616+
const sql = postgres({
617+
...options,
618+
transform: postgres.camel,
619+
})
620+
621+
const x = (
622+
await sql`select 'null'::json as a, 'false'::json as b, '"a"'::json as c, '1'::json as d`
623+
)[0]
624+
625+
return [
626+
JSON.stringify({ a: null, b: false, c: 'a', d: 1 }),
627+
JSON.stringify(x),
628+
]
629+
})
630+
631+
t('Bypass transform for jsonb primitive', async () => {
632+
const sql = postgres({
633+
...options,
634+
transform: postgres.camel,
635+
})
636+
637+
const x = (
638+
await sql`select 'null'::jsonb as a, 'false'::jsonb as b, '"a"'::jsonb as c, '1'::jsonb as d`
639+
)[0]
640+
641+
return [
642+
JSON.stringify({ a: null, b: false, c: 'a', d: 1 }),
643+
JSON.stringify(x),
644+
]
645+
})
646+
607647
t('unsafe', async() => {
608648
await sql`create table test (x int)`
609649
return [1, (await sql.unsafe('insert into test values ($1) returning *', [1]))[0].x, await sql`drop table test`]
@@ -701,7 +741,7 @@ t('multiple listeners work after a reconnect', async() => {
701741

702742
t('listen and notify with weird name', async() => {
703743
const sql = postgres(options)
704-
const channel = 'wat-;ø§'
744+
const channel = 'wat-;.ø.§'
705745
const result = await new Promise(async r => {
706746
await sql.listen(channel, r)
707747
sql.notify(channel, 'works')

deno/README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,21 @@ sql`
228228
update users set "name" = $1, "age" = $2 where user_id = $3
229229
```
230230

231+
### Multiple updates in one query
232+
It's possible to create multiple udpates in a single query. It's necessary to use arrays intead of objects to ensure the order of the items so that these correspond with the column names.
233+
```js
234+
const users = [
235+
[1, 'John', 34],
236+
[2, 'Jane', 27],
237+
]
238+
239+
sql`
240+
update users set name = update_data.name, age = update_data.age
241+
from (values ${sql(users)}) as update_data (id, name, age)
242+
where users.id = update_data.id
243+
`
244+
```
245+
231246
### Dynamic values and `where in`
232247
Value lists can also be created dynamically, making `where in` queries simple too.
233248
```js
@@ -320,6 +335,17 @@ sql`
320335
select "id" from "users"
321336
```
322337

338+
### Quick primer on interpolation
339+
340+
Here's a quick oversight over all the ways to do interpolation in a query template string:
341+
342+
| Interpolation syntax | Usage | Example |
343+
| ------------- | ------------- | ------------- |
344+
| `${ sql`` }` | for keywords or sql fragments | ``sql`SELECT * FROM users ${sql`order by age desc` }` `` |
345+
| `${ sql(string) }` | for identifiers | ``sql`SELECT * FROM ${sql('table_name')` `` |
346+
| `${ sql([] or {}, ...) }` | for helpers | ``sql`INSERT INTO users ${sql({ name: 'Peter'})}` `` |
347+
| `${ 'somevalue' }` | for values | ``sql`SELECT * FROM users WHERE age = ${42}` `` |
348+
323349
## Advanced query methods
324350

325351
### Cursors
@@ -393,7 +419,7 @@ await sql`
393419
```
394420

395421
### Query Descriptions
396-
#### ```await sql``.describe([rows = 1], fn) -> Result[]```
422+
#### ```await sql``.describe() -> Result[]```
397423

398424
Rather than executing a given query, `.describe` will return information utilized in the query process. This information can include the query identifier, column types, etc.
399425

@@ -585,6 +611,8 @@ Built in transformation functions are:
585611
* For PascalCase - `postgres.pascal`, `postgres.toPascal`, `postgres.fromPascal`
586612
* For Kebab-Case - `postgres.kebab`, `postgres.toKebab`, `postgres.fromKebab`
587613

614+
These built in transformations will only convert to/from snake_case. For example, using `{ transform: postgres.toCamel }` will convert the column names to camelCase only if the column names are in snake_case to begin with. `{ transform: postgres.fromCamel }` will convert camelCase only to snake_case.
615+
588616
By default, using `postgres.camel`, `postgres.pascal` and `postgres.kebab` will perform a two-way transformation - both the data passed to the query and the data returned by the query will be transformed:
589617

590618
```js

deno/src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,9 @@ function Postgres(a, b) {
177177
return { state: result.state, unlisten }
178178
}
179179

180-
channels[name] = { result: sql`listen ${ sql(name) }`, listeners: [listener] }
180+
channels[name] = { result: sql`listen ${
181+
sql.unsafe('"' + name.replace(/"/g, '""') + '"')
182+
}`, listeners: [listener] }
181183
const result = await channels[name].result
182184
listener.onlisten && listener.onlisten()
183185
return { state: result.state, unlisten }

deno/src/types.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,9 @@ export const fromKebab = x => x.replace(/-/g, '_')
326326

327327
function createJsonTransform(fn) {
328328
return function jsonTransform(x, column) {
329-
return column.type === 114 || column.type === 3802
329+
return typeof x === 'object' && x !== null && (column.type === 114 || column.type === 3802)
330330
? Array.isArray(x)
331-
? x.map(jsonTransform)
331+
? x.map(x => jsonTransform(x, column))
332332
: Object.entries(x).reduce((acc, [k, v]) => Object.assign(acc, { [fn(k)]: v }), {})
333333
: x
334334
}

deno/tests/index.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,46 @@ t('column toKebab', async() => {
606606
return ['hello-world', Object.keys((await sql`select * from test`)[0])[0], await sql`drop table test`]
607607
})
608608

609+
t('Transform nested json in arrays', async() => {
610+
const sql = postgres({
611+
...options,
612+
transform: postgres.camel
613+
})
614+
return ['aBcD', (await sql`select '[{"a_b":1},{"c_d":2}]'::jsonb as x`)[0].x.map(Object.keys).join('')]
615+
})
616+
617+
t('Bypass transform for json primitive', async () => {
618+
const sql = postgres({
619+
...options,
620+
transform: postgres.camel,
621+
})
622+
623+
const x = (
624+
await sql`select 'null'::json as a, 'false'::json as b, '"a"'::json as c, '1'::json as d`
625+
)[0]
626+
627+
return [
628+
JSON.stringify({ a: null, b: false, c: 'a', d: 1 }),
629+
JSON.stringify(x),
630+
]
631+
})
632+
633+
t('Bypass transform for jsonb primitive', async () => {
634+
const sql = postgres({
635+
...options,
636+
transform: postgres.camel,
637+
})
638+
639+
const x = (
640+
await sql`select 'null'::jsonb as a, 'false'::jsonb as b, '"a"'::jsonb as c, '1'::jsonb as d`
641+
)[0]
642+
643+
return [
644+
JSON.stringify({ a: null, b: false, c: 'a', d: 1 }),
645+
JSON.stringify(x),
646+
]
647+
})
648+
609649
t('unsafe', async() => {
610650
await sql`create table test (x int)`
611651
return [1, (await sql.unsafe('insert into test values ($1) returning *', [1]))[0].x, await sql`drop table test`]
@@ -703,7 +743,7 @@ t('multiple listeners work after a reconnect', async() => {
703743

704744
t('listen and notify with weird name', async() => {
705745
const sql = postgres(options)
706-
const channel = 'wat-;ø§'
746+
const channel = 'wat-;.ø.§'
707747
const result = await new Promise(async r => {
708748
await sql.listen(channel, r)
709749
sql.notify(channel, 'works')

0 commit comments

Comments
 (0)