Skip to content

Commit c8d94a5

Browse files
Merge pull request #1722 from taozhi8833998/feat-json-expr-bigquery
feat: support json type, fix array column vistior in bigquery
2 parents 87d01c2 + 1a3f9cd commit c8d94a5

File tree

5 files changed

+62
-11
lines changed

5 files changed

+62
-11
lines changed

pegjs/bigquery.pegjs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,17 +1650,18 @@ columns_list
16501650
return createList(head, tail);
16511651
}
16521652

1653-
column_offset_expr
1654-
= n:expr __ LBRAKE __ l:literal_numeric __ RBRAKE {
1655-
return {
1656-
expr: n,
1657-
offset: `[${l.value}]`
1658-
}
1653+
column_offset_expr_list
1654+
= l:(LBRAKE __ (literal_numeric / literal_string) __ RBRAKE)+ {
1655+
return l.map(item => ({ value: item[2] }))
1656+
}
1657+
/ l:(LBRAKE __ (KW_OFFSET / KW_ORDINAL / KW_SAFE_OFFSET / KW_SAFE_ORDINAL) __ LPAREN __ (literal_numeric / literal_string) __ RPAREN __ RBRAKE)+ {
1658+
return l.map(item => ({ name: item[2], value: item[6] }))
16591659
}
1660-
/ n:expr __ LBRAKE __ t:(KW_OFFSET / KW_ORDINAL / KW_SAFE_OFFSET / KW_SAFE_ORDINAL) __ LPAREN __ l:literal_numeric __ RPAREN __ RBRAKE {
1660+
column_offset_expr
1661+
= n:expr __ l:column_offset_expr_list {
16611662
return {
16621663
expr: n,
1663-
offset: `[${t}(${l.value})]`
1664+
offset: l
16641665
}
16651666
}
16661667

@@ -1706,8 +1707,8 @@ column_list_item
17061707
as: null
17071708
}
17081709
}
1709-
/ c:column_offset_expr __ as:alias_clause? {
1710-
columnList.add(`select::null::${c}`)
1710+
/ c:column_offset_expr __ s:(DOT __ column_without_kw)? __ as:alias_clause? {
1711+
if (s) c.suffix = `.${s[2]}`
17111712
return {
17121713
expr: {
17131714
type: 'column_ref',
@@ -2014,6 +2015,7 @@ expr_list
20142015

20152016
_expr
20162017
= struct_expr
2018+
/ json_expr
20172019
/ logic_operator_expr // support concatenation operator || and &&
20182020
/ or_expr
20192021
/ unary_expr
@@ -2062,6 +2064,15 @@ array_expr
20622064
}
20632065
}
20642066

2067+
json_expr
2068+
= KW_JSON __ l:literal_list {
2069+
return {
2070+
type: 'json',
2071+
keyword: 'json',
2072+
expr_list: l
2073+
}
2074+
}
2075+
20652076
struct_expr
20662077
= s:(struct_type / KW_STRUCT) __ LPAREN __ c:column_clause __ RPAREN {
20672078
return {
@@ -2240,6 +2251,7 @@ multiplicative_operator
22402251
primary
22412252
= array_expr
22422253
/ struct_expr
2254+
/ json_expr
22432255
/ cast_expr
22442256
/ literal
22452257
/ aggr_func

src/column.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
function columnOffsetToSQL(column, isDual) {
1919
if (typeof column === 'string') return identifierToSql(column, isDual)
2020
const { expr, offset, suffix } = column
21-
return [exprToSQL(expr), offset, suffix].filter(hasVal).join('')
21+
const offsetExpr = offset && offset.map(offsetItem => ['[', offsetItem.name, `${offsetItem.name ? '(' : ''}`, literalToSQL(offsetItem.value), `${offsetItem.name ? ')' : ''}`, ']'].filter(hasVal).join('')).join('')
22+
return [exprToSQL(expr), offsetExpr, suffix].filter(hasVal).join('')
2223
}
2324
function columnRefToSQL(expr) {
2425
const {

src/expr.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { caseToSQL } from './case'
77
import { columnDefinitionToSQL, columnRefToSQL, fullTextSearchToSQL } from './column'
88
import { anyValueFuncToSQL, castToSQL, extractFunToSQL, flattenFunToSQL, funcToSQL, tablefuncFunToSQL } from './func'
99
import { intervalToSQL } from './interval'
10+
import { jsonExprToSQL } from './json'
1011
import { selectToSQL } from './select'
1112
import { showToSQL } from './show'
1213
import { arrayStructExprToSQL } from './array-struct'
@@ -33,6 +34,7 @@ const exprToSQLConvertFn = {
3334
function : funcToSQL,
3435
insert : unionToSQL,
3536
interval : intervalToSQL,
37+
json : jsonExprToSQL,
3638
show : showToSQL,
3739
struct : arrayStructExprToSQL,
3840
tablefunc : tablefuncFunToSQL,

src/json.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { exprToSQL } from './expr'
2+
import { toUpper } from './util'
3+
4+
function jsonExprToSQL(expr) {
5+
const { keyword, expr_list: exprList } = expr
6+
const result = [toUpper(keyword), exprList.map(exprItem => exprToSQL(exprItem)).join(', ')].join(' ')
7+
return result
8+
}
9+
10+
export {
11+
jsonExprToSQL,
12+
}

test/bigquery.spec.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,30 @@ describe('BigQuery', () => {
823823
'SELECT if(((a)), b, NULL)'
824824
]
825825
},
826+
{
827+
title: 'offset column with dot',
828+
sql: [
829+
`WITH your_table AS (
830+
SELECT [STRUCT(1 AS id, 'John' AS name), STRUCT(2 AS id, 'Jane' AS name)] AS some_array_column
831+
)
832+
SELECT some_array_column[SAFE_OFFSET(0)].id from your_table`,
833+
"WITH your_table AS (SELECT [STRUCT(1 AS id, 'John' AS name), STRUCT(2 AS id, 'Jane' AS name)] AS some_array_column) SELECT some_array_column[SAFE_OFFSET(0)].id FROM your_table"
834+
]
835+
},
836+
{
837+
title: 'json expr',
838+
sql: [
839+
`SELECT json_value.class.students[0]['name'] AS first_student
840+
FROM
841+
UNNEST(
842+
[
843+
JSON '{"class" : {"students" : [{"name" : "Jane"}]}}',
844+
JSON '{"class" : {"students" : []}}',
845+
JSON '{"class" : {"students" : [{"name" : "John"}, {"name": "Jamie"}]}}'])
846+
AS json_value`,
847+
`SELECT json_value.class.students[0]['name'] AS first_student FROM UNNEST([JSON '{"class" : {"students" : [{"name" : "Jane"}]}}', JSON '{"class" : {"students" : []}}', JSON '{"class" : {"students" : [{"name" : "John"}, {"name": "Jamie"}]}}']) AS json_value`
848+
]
849+
}
826850
]
827851

828852
SQL_LIST.forEach(sqlInfo => {

0 commit comments

Comments
 (0)