Skip to content

Commit 250d792

Browse files
committed
feat: support updating JSON using subscripting in pg
1 parent 9adf7f7 commit 250d792

File tree

8 files changed

+73
-25
lines changed

8 files changed

+73
-25
lines changed

pegjs/hive.pegjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,9 +1037,13 @@ array_index
10371037
property,
10381038
}
10391039
}
1040+
array_index_list
1041+
= head:array_index tail:(__ array_index)* {
1042+
return createList(head, tail, 1)
1043+
}
10401044

10411045
expr_item
1042-
= e:binary_column_expr __ a:array_index? {
1046+
= e:binary_column_expr __ a:array_index_list? {
10431047
if (a) e.array_index = a
10441048
return e
10451049
}
@@ -1774,7 +1778,7 @@ primary
17741778
/ func_call
17751779
/ case_expr
17761780
/ interval_expr
1777-
/ c:column_ref __ a:array_index {
1781+
/ c:column_ref __ a:array_index_list {
17781782
// => column_ref
17791783
c.array_index = a
17801784
return c

pegjs/noql.pegjs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,8 +2809,13 @@ array_index
28092809
}
28102810
}
28112811

2812+
array_index_list
2813+
= head:array_index tail:(__ array_index)* {
2814+
return createList(head, tail, 1)
2815+
}
2816+
28122817
expr_item
2813-
= e:binary_column_expr __ a:array_index? {
2818+
= e:binary_column_expr __ a:array_index_list? {
28142819
// => binary_expr & { array_index: array_index }
28152820
if (a) e.array_index = a
28162821
return e
@@ -3931,7 +3936,7 @@ multiplicative_operator
39313936
= "*" / "/" / "%" / "||"
39323937

39333938
column_ref_array_index
3934-
= c:column_ref __ a:array_index? {
3939+
= c:column_ref __ a:array_index_list? {
39353940
// => column_ref
39363941
if (a) c.array_index = a
39373942
return c

pegjs/postgresql.pegjs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2863,8 +2863,14 @@ array_index
28632863
}
28642864
}
28652865

2866+
array_index_list
2867+
= head:array_index tail:(__ array_index)* {
2868+
// => array_index[]
2869+
return createList(head, tail, 1)
2870+
}
2871+
28662872
expr_item
2867-
= e:binary_column_expr __ a:array_index? {
2873+
= e:binary_column_expr __ a:array_index_list? {
28682874
// => binary_expr & { array_index: array_index }
28692875
if (a) e.array_index = a
28702876
return e
@@ -3371,7 +3377,7 @@ update_stmt
33713377
const table = queryTableAlias(col.table)
33723378
tableList.add(`update::${dbObj[table] || null}::${table}`)
33733379
}
3374-
columnList.add(`update::${col.table}::${col.column}`)
3380+
columnList.add(`update::${col.table}::${col.column.expr.value}`)
33753381
});
33763382
}
33773383
return {
@@ -3444,13 +3450,13 @@ set_list
34443450
* 'col1 = (col2 > 3)'
34453451
*/
34463452
set_item
3447-
= tbl:(ident __ DOT)? __ c:column_without_kw_type __ '=' __ v:additive_expr {
3448-
// => { column: ident; value: additive_expr; table?: ident;}
3449-
return { column: { expr: c }, value: v, table: tbl && tbl[0] };
3450-
}
3451-
/ tbl:(ident __ DOT)? __ c:column_without_kw_type __ '=' __ KW_VALUES __ LPAREN __ v:column_ref __ RPAREN {
3452-
// => { column: ident; value: column_ref; table?: ident; keyword: 'values' }
3453-
return { column: { expr: c }, value: v, table: tbl && tbl[0], keyword: 'values' };
3453+
= c:column_ref_array_index __ '=' __ v:additive_expr {
3454+
// => { column: ident; value: additive_expr; table?: ident;}
3455+
return { ...c, value: v };
3456+
}
3457+
/ column_ref_array_index __ '=' __ KW_VALUES __ LPAREN __ v:column_ref __ RPAREN {
3458+
// => { column: ident; value: column_ref; table?: ident; keyword: 'values' }
3459+
return { ...c, value: v, keyword: 'values' };
34543460
}
34553461

34563462
returning_stmt
@@ -3983,7 +3989,7 @@ multiplicative_operator
39833989
= "*" / "/" / "%" / "||"
39843990

39853991
column_ref_array_index
3986-
= c:column_ref __ a:array_index? {
3992+
= c:column_ref __ a:array_index_list? {
39873993
// => column_ref
39883994
if (a) c.array_index = a
39893995
return c

pegjs/redshift.pegjs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2848,8 +2848,13 @@ array_index
28482848
}
28492849
}
28502850

2851+
array_index_list
2852+
= head:array_index tail:(__ array_index)* {
2853+
return createList(head, tail, 1)
2854+
}
2855+
28512856
expr_item
2852-
= e:binary_column_expr __ a:array_index? {
2857+
= e:binary_column_expr __ a:array_index_list? {
28532858
// => binary_expr & { array_index: array_index }
28542859
if (a) e.array_index = a
28552860
return e
@@ -3971,7 +3976,7 @@ multiplicative_operator
39713976
= "*" / "/" / "%" / "||"
39723977

39733978
column_ref_array_index
3974-
= c:column_ref __ a:array_index? {
3979+
= c:column_ref __ a:array_index_list? {
39753980
// => column_ref
39763981
if (a) c.array_index = a
39773982
return c

pegjs/snowflake.pegjs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,9 +2146,12 @@ array_index
21462146
index: n
21472147
}
21482148
}
2149-
2149+
array_index_list
2150+
= head:array_index tail:(__ array_index)* {
2151+
return createList(head, tail, 1)
2152+
}
21502153
expr_item
2151-
= e:binary_column_expr __ a:array_index? {
2154+
= e:binary_column_expr __ a:array_index_list? {
21522155
// => binary_expr & { array_index: array_index }
21532156
if (a) e.array_index = a
21542157
return e
@@ -3284,7 +3287,7 @@ multiplicative_operator
32843287
= "*" / "/" / "%" / "||"
32853288

32863289
column_ref_array_index
3287-
= c:column_ref __ a:array_index? {
3290+
= c:column_ref __ a:array_index_list? {
32883291
// => column_ref
32893292
if (a) c.array_index = a
32903293
return c

src/column.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ function columnRefToSQL(expr) {
3131
const prefix = [db, schema, table].filter(hasVal).map(val => `${typeof val === 'string' ? identifierToSql(val) : exprToSQL(val)}`).join('.')
3232
if (prefix) str = `${prefix}.${str}`
3333
if (array_index) {
34-
str = `${str}[${literalToSQL(array_index.index)}]`
35-
if (array_index.property) str = `${str}.${literalToSQL(array_index.property)}`
34+
for (const arrayIndex of array_index) {
35+
str = `${str}[${literalToSQL(arrayIndex.index)}]`
36+
if (arrayIndex.property) str = `${str}.${literalToSQL(arrayIndex.property)}`
37+
}
3638
}
3739
str = [str, ...subFields].join('.')
3840
const result = [
@@ -160,7 +162,11 @@ function columnToSQL(column, isDual) {
160162
return result.filter(hasVal).join(' ')
161163
}
162164
if (expr.parentheses && Reflect.has(expr, 'array_index')) str = `(${str})`
163-
if (expr.array_index && expr.type !== 'column_ref') str = `${str}[${literalToSQL(expr.array_index.index)}]`
165+
if (expr.array_index && expr.type !== 'column_ref') {
166+
for (const arrayIndex of expr.array_index) {
167+
str = `${str}[${literalToSQL(arrayIndex.index)}]`
168+
}
169+
}
164170
return [str, asToSQL(column.as)].filter(hasVal).join(' ')
165171
}
166172

src/update.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { tablesToSQL } from './tables'
22
import { exprToSQL, orderOrPartitionByToSQL } from './expr'
33
import { columnRefToSQL } from './column'
44
import { limitToSQL } from './limit'
5-
import { hasVal, identifierToSql, commonOptionConnector, returningToSQL } from './util'
5+
import { hasVal, commonOptionConnector, returningToSQL } from './util'
66
import { withToSQL } from './with'
77

88
/**
@@ -13,8 +13,13 @@ function setToSQL(sets) {
1313
if (!sets || sets.length === 0) return ''
1414
const clauses = []
1515
for (const set of sets) {
16-
const { table, column, value } = set
17-
const str = [identifierToSql(table), columnRefToSQL({ column })].filter(hasVal).join('.')
16+
const column = {}
17+
const { value } = set
18+
for (const key in set) {
19+
if (key === 'value' || key === 'keyword') continue
20+
if (Object.prototype.hasOwnProperty.call(set, key)) column[key] = set[key]
21+
}
22+
const str = columnRefToSQL(column)
1823
const setItem = [str]
1924
let val = ''
2025
if (value) {

test/postgres.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,20 @@ describe('Postgres', () => {
14361436
'TRUNCATE TABLE ONLY "employee" * CONTINUE IDENTITY RESTRICT'
14371437
]
14381438
},
1439+
{
1440+
title: 'jsonb in select column',
1441+
sql: [
1442+
"SELECT data['author']['first_name'] as title FROM blogs",
1443+
`SELECT data['author']['first_name'] AS "title" FROM "blogs"`
1444+
]
1445+
},
1446+
{
1447+
title: 'jsonb in update set',
1448+
sql: [
1449+
`UPDATE blogs SET data['author']['first_name'] = '"Sarah"'`,
1450+
`UPDATE "blogs" SET data['author']['first_name'] = '"Sarah"'`
1451+
]
1452+
},
14391453
]
14401454
function neatlyNestTestedSQL(sqlList){
14411455
sqlList.forEach(sqlInfo => {

0 commit comments

Comments
 (0)