Skip to content

Commit 6a4801f

Browse files
committed
build
1 parent 89a6a1c commit 6a4801f

File tree

7 files changed

+121
-9
lines changed

7 files changed

+121
-9
lines changed

cjs/src/index.js

+3-1
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

+2-2
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,9 @@ const fromKebab = module.exports.fromKebab = x => x.replace(/-/g, '_')
329329

330330
function createJsonTransform(fn) {
331331
return function jsonTransform(x, column) {
332-
return column.type === 114 || column.type === 3802
332+
return typeof x === 'object' && x !== null && (column.type === 114 || column.type === 3802)
333333
? Array.isArray(x)
334-
? x.map(jsonTransform)
334+
? x.map(x => jsonTransform(x, column))
335335
: Object.entries(x).reduce((acc, [k, v]) => Object.assign(acc, { [fn(k)]: v }), {})
336336
: x
337337
}

cjs/tests/index.js

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

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

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

deno/README.md

+29-1
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

+3-1
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

+2-2
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,9 @@ export const fromKebab = x => x.replace(/-/g, '_')
330330

331331
function createJsonTransform(fn) {
332332
return function jsonTransform(x, column) {
333-
return column.type === 114 || column.type === 3802
333+
return typeof x === 'object' && x !== null && (column.type === 114 || column.type === 3802)
334334
? Array.isArray(x)
335-
? x.map(jsonTransform)
335+
? x.map(x => jsonTransform(x, column))
336336
: Object.entries(x).reduce((acc, [k, v]) => Object.assign(acc, { [fn(k)]: v }), {})
337337
: x
338338
}

deno/tests/index.js

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

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

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

0 commit comments

Comments
 (0)