Skip to content

Commit a763cb4

Browse files
committed
support for weirder stuff
1 parent bb9ad26 commit a763cb4

File tree

2 files changed

+48
-13
lines changed

2 files changed

+48
-13
lines changed

src/parser/mod.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3715,29 +3715,26 @@ impl<'a> Parser<'a> {
37153715
})
37163716
}
37173717

3718+
// Parser is either looking at a : or a bracket expression.
37183719
fn parse_json_path(&mut self) -> Result<JsonPath, ParserError> {
37193720
let mut path = Vec::new();
3720-
let has_colon = self.peek_token_ref().token == Token::Colon;
3721+
let mut has_colon = false;
37213722
loop {
37223723
match self.next_token().token {
37233724
Token::Colon if path.is_empty() => {
3724-
path.push(self.parse_json_path_object_key()?);
3725+
has_colon = true;
3726+
if *self.peek_token_ref() == Token::LBracket {
3727+
path.push(self.parse_json_path_bracket_element()?);
3728+
} else {
3729+
path.push(self.parse_json_path_object_key()?);
3730+
}
37253731
}
37263732
Token::Period if !path.is_empty() => {
37273733
path.push(self.parse_json_path_object_key()?);
37283734
}
37293735
Token::LBracket => {
3730-
if self.peek_token_ref().token == Token::Mul
3731-
&& self.dialect.supports_semi_structured_array_all_elements()
3732-
{
3733-
self.expect_token(&Token::Mul)?;
3734-
path.push(JsonPathElem::AllElements);
3735-
} else {
3736-
let key = self.parse_expr()?;
3737-
path.push(JsonPathElem::Bracket { key });
3738-
}
3739-
3740-
self.expect_token(&Token::RBracket)?;
3736+
self.prev_token();
3737+
path.push(self.parse_json_path_bracket_element()?);
37413738
}
37423739
_ => {
37433740
self.prev_token();
@@ -3750,6 +3747,22 @@ impl<'a> Parser<'a> {
37503747
Ok(JsonPath { has_colon, path })
37513748
}
37523749

3750+
/// Parses a single bracketed element in a JSON path expression, including both brackets.
3751+
fn parse_json_path_bracket_element(&mut self) -> Result<JsonPathElem, ParserError> {
3752+
self.expect_token(&Token::LBracket)?;
3753+
let elem = if *self.peek_token_ref() == Token::Mul
3754+
&& self.dialect.supports_semi_structured_array_all_elements()
3755+
{
3756+
self.expect_token(&Token::Mul)?;
3757+
JsonPathElem::AllElements
3758+
} else {
3759+
let key = self.parse_expr()?;
3760+
JsonPathElem::Bracket { key }
3761+
};
3762+
self.expect_token(&Token::RBracket)?;
3763+
Ok(elem)
3764+
}
3765+
37533766
/// Parses the parens following the `[ NOT ] IN` operator.
37543767
pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
37553768
// BigQuery allows `IN UNNEST(array_expression)`

tests/sqlparser_databricks.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,28 @@ fn parse_semi_structured_data_traversal() {
408408
select.projection[0]
409409
);
410410

411+
// asterisk for arrays
412+
let sql = "SELECT a:['b'].c FROM t";
413+
let select = databricks().verified_only_select(sql);
414+
assert_eq!(
415+
SelectItem::UnnamedExpr(Expr::JsonAccess {
416+
value: Box::new(Expr::Identifier(Ident::new("a"))),
417+
path: JsonPath {
418+
has_colon: true,
419+
path: vec![
420+
JsonPathElem::Bracket {
421+
key: Expr::value(Value::SingleQuotedString("b".to_owned())),
422+
},
423+
JsonPathElem::Dot {
424+
key: "c".to_owned(),
425+
quoted: false
426+
}
427+
]
428+
},
429+
}),
430+
select.projection[0]
431+
);
432+
411433
// asterisk for arrays
412434
let sql = "SELECT a:b[*].c FROM t";
413435
let select = databricks().verified_only_select(sql);

0 commit comments

Comments
 (0)