Skip to content

Commit

Permalink
Merge pull request #1722 from taozhi8833998/feat-json-expr-bigquery
Browse files Browse the repository at this point in the history
feat: support json type, fix array column vistior in bigquery
  • Loading branch information
taozhi8833998 authored Dec 18, 2023
2 parents 87d01c2 + 1a3f9cd commit c8d94a5
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 11 deletions.
32 changes: 22 additions & 10 deletions pegjs/bigquery.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -1650,17 +1650,18 @@ columns_list
return createList(head, tail);
}

column_offset_expr
= n:expr __ LBRAKE __ l:literal_numeric __ RBRAKE {
return {
expr: n,
offset: `[${l.value}]`
}
column_offset_expr_list
= l:(LBRAKE __ (literal_numeric / literal_string) __ RBRAKE)+ {
return l.map(item => ({ value: item[2] }))
}
/ l:(LBRAKE __ (KW_OFFSET / KW_ORDINAL / KW_SAFE_OFFSET / KW_SAFE_ORDINAL) __ LPAREN __ (literal_numeric / literal_string) __ RPAREN __ RBRAKE)+ {
return l.map(item => ({ name: item[2], value: item[6] }))
}
/ n:expr __ LBRAKE __ t:(KW_OFFSET / KW_ORDINAL / KW_SAFE_OFFSET / KW_SAFE_ORDINAL) __ LPAREN __ l:literal_numeric __ RPAREN __ RBRAKE {
column_offset_expr
= n:expr __ l:column_offset_expr_list {
return {
expr: n,
offset: `[${t}(${l.value})]`
offset: l
}
}

Expand Down Expand Up @@ -1706,8 +1707,8 @@ column_list_item
as: null
}
}
/ c:column_offset_expr __ as:alias_clause? {
columnList.add(`select::null::${c}`)
/ c:column_offset_expr __ s:(DOT __ column_without_kw)? __ as:alias_clause? {
if (s) c.suffix = `.${s[2]}`
return {
expr: {
type: 'column_ref',
Expand Down Expand Up @@ -2014,6 +2015,7 @@ expr_list

_expr
= struct_expr
/ json_expr
/ logic_operator_expr // support concatenation operator || and &&
/ or_expr
/ unary_expr
Expand Down Expand Up @@ -2062,6 +2064,15 @@ array_expr
}
}

json_expr
= KW_JSON __ l:literal_list {
return {
type: 'json',
keyword: 'json',
expr_list: l
}
}

struct_expr
= s:(struct_type / KW_STRUCT) __ LPAREN __ c:column_clause __ RPAREN {
return {
Expand Down Expand Up @@ -2240,6 +2251,7 @@ multiplicative_operator
primary
= array_expr
/ struct_expr
/ json_expr
/ cast_expr
/ literal
/ aggr_func
Expand Down
3 changes: 2 additions & 1 deletion src/column.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
function columnOffsetToSQL(column, isDual) {
if (typeof column === 'string') return identifierToSql(column, isDual)
const { expr, offset, suffix } = column
return [exprToSQL(expr), offset, suffix].filter(hasVal).join('')
const offsetExpr = offset && offset.map(offsetItem => ['[', offsetItem.name, `${offsetItem.name ? '(' : ''}`, literalToSQL(offsetItem.value), `${offsetItem.name ? ')' : ''}`, ']'].filter(hasVal).join('')).join('')
return [exprToSQL(expr), offsetExpr, suffix].filter(hasVal).join('')
}
function columnRefToSQL(expr) {
const {
Expand Down
2 changes: 2 additions & 0 deletions src/expr.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { caseToSQL } from './case'
import { columnDefinitionToSQL, columnRefToSQL, fullTextSearchToSQL } from './column'
import { anyValueFuncToSQL, castToSQL, extractFunToSQL, flattenFunToSQL, funcToSQL, tablefuncFunToSQL } from './func'
import { intervalToSQL } from './interval'
import { jsonExprToSQL } from './json'
import { selectToSQL } from './select'
import { showToSQL } from './show'
import { arrayStructExprToSQL } from './array-struct'
Expand All @@ -33,6 +34,7 @@ const exprToSQLConvertFn = {
function : funcToSQL,
insert : unionToSQL,
interval : intervalToSQL,
json : jsonExprToSQL,
show : showToSQL,
struct : arrayStructExprToSQL,
tablefunc : tablefuncFunToSQL,
Expand Down
12 changes: 12 additions & 0 deletions src/json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { exprToSQL } from './expr'
import { toUpper } from './util'

function jsonExprToSQL(expr) {
const { keyword, expr_list: exprList } = expr
const result = [toUpper(keyword), exprList.map(exprItem => exprToSQL(exprItem)).join(', ')].join(' ')
return result
}

export {
jsonExprToSQL,
}
24 changes: 24 additions & 0 deletions test/bigquery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,30 @@ describe('BigQuery', () => {
'SELECT if(((a)), b, NULL)'
]
},
{
title: 'offset column with dot',
sql: [
`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`,
"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"
]
},
{
title: 'json expr',
sql: [
`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`,
`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`
]
}
]

SQL_LIST.forEach(sqlInfo => {
Expand Down

0 comments on commit c8d94a5

Please sign in to comment.