Skip to content

Commit 6397d3c

Browse files
committed
add JsonPathElem::ColonBracket variant and remove AST tests
1 parent c7a1127 commit 6397d3c

File tree

4 files changed

+20
-126
lines changed

4 files changed

+20
-126
lines changed

src/ast/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,14 @@ pub enum JsonPathElem {
651651
/// The expression used as the bracket key (string or numeric expression).
652652
key: Expr,
653653
},
654+
/// Access an object field using colon bracket notation
655+
/// e.g. `obj:['foo']`
656+
///
657+
/// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
658+
ColonBracket {
659+
/// The expression used as the bracket key (string or numeric expression).
660+
key: Expr,
661+
},
654662
}
655663

656664
/// A JSON path.
@@ -685,6 +693,9 @@ impl fmt::Display for JsonPath {
685693
JsonPathElem::Bracket { key } => {
686694
write!(f, "[{key}]")?;
687695
}
696+
JsonPathElem::ColonBracket { key } => {
697+
write!(f, ":[{key}]")?;
698+
}
688699
}
689700
}
690701
Ok(())

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,7 @@ impl Spanned for JsonPathElem {
17971797
match self {
17981798
JsonPathElem::Dot { .. } => Span::empty(),
17991799
JsonPathElem::Bracket { key } => key.span(),
1800+
JsonPathElem::ColonBracket { key } => key.span(),
18001801
}
18011802
}
18021803
}

src/parser/mod.rs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4211,15 +4211,6 @@ impl<'a> Parser<'a> {
42114211
}
42124212
}
42134213

4214-
fn parse_json_path_bracket_key(&mut self) -> Result<Expr, ParserError> {
4215-
// Databricks supports [*] wildcard accessor
4216-
if self.consume_token(&Token::Mul) {
4217-
Ok(Expr::Wildcard(AttachedToken::empty()))
4218-
} else {
4219-
self.parse_expr()
4220-
}
4221-
}
4222-
42234214
fn parse_json_access(&mut self, expr: Expr) -> Result<Expr, ParserError> {
42244215
let path = self.parse_json_path()?;
42254216
Ok(Expr::JsonAccess {
@@ -4232,27 +4223,20 @@ impl<'a> Parser<'a> {
42324223
let mut path = Vec::new();
42334224
loop {
42344225
match self.next_token().token {
4226+
Token::Colon if path.is_empty() && self.peek_token_ref() == &Token::LBracket => {
4227+
self.next_token();
4228+
let key = self.parse_wildcard_expr()?;
4229+
self.expect_token(&Token::RBracket)?;
4230+
path.push(JsonPathElem::ColonBracket { key });
4231+
}
42354232
Token::Colon if path.is_empty() => {
4236-
if self.peek_token_ref().token == Token::LBracket {
4237-
// A bracket element directly after the colon, e.g. `raw:['field']`.
4238-
// Push an empty Dot so the display re-emits the leading `:` for syntax roundtrip.
4239-
path.push(JsonPathElem::Dot {
4240-
key: String::new(),
4241-
quoted: false,
4242-
});
4243-
self.next_token();
4244-
let key = self.parse_json_path_bracket_key()?;
4245-
self.expect_token(&Token::RBracket)?;
4246-
path.push(JsonPathElem::Bracket { key });
4247-
} else {
4248-
path.push(self.parse_json_path_object_key()?);
4249-
}
4233+
path.push(self.parse_json_path_object_key()?);
42504234
}
42514235
Token::Period if !path.is_empty() => {
42524236
path.push(self.parse_json_path_object_key()?);
42534237
}
42544238
Token::LBracket => {
4255-
let key = self.parse_json_path_bracket_key()?;
4239+
let key = self.parse_wildcard_expr()?;
42564240
self.expect_token(&Token::RBracket)?;
42574241

42584242
path.push(JsonPathElem::Bracket { key });

tests/sqlparser_databricks.rs

Lines changed: 0 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -644,106 +644,4 @@ fn parse_databricks_json_accessor() {
644644
"SELECT raw:store.bicycle.price::double FROM store_data",
645645
"SELECT raw:store.bicycle.price::DOUBLE FROM store_data",
646646
);
647-
648-
// --- AST structure assertions ---
649-
650-
// Simple dot access
651-
assert_eq!(
652-
databricks().verified_expr("raw:owner"),
653-
Expr::JsonAccess {
654-
value: Box::new(Expr::Identifier(Ident::new("raw"))),
655-
path: JsonPath {
656-
path: vec![JsonPathElem::Dot {
657-
key: "owner".to_owned(),
658-
quoted: false,
659-
}],
660-
},
661-
}
662-
);
663-
664-
// Multi-level dot access
665-
assert_eq!(
666-
databricks().verified_expr("raw:store.bicycle"),
667-
Expr::JsonAccess {
668-
value: Box::new(Expr::Identifier(Ident::new("raw"))),
669-
path: JsonPath {
670-
path: vec![
671-
JsonPathElem::Dot {
672-
key: "store".to_owned(),
673-
quoted: false,
674-
},
675-
JsonPathElem::Dot {
676-
key: "bicycle".to_owned(),
677-
quoted: false,
678-
},
679-
],
680-
},
681-
}
682-
);
683-
684-
// Dot path followed by an integer-index bracket
685-
assert_eq!(
686-
databricks().verified_expr("raw:store.fruit[0]"),
687-
Expr::JsonAccess {
688-
value: Box::new(Expr::Identifier(Ident::new("raw"))),
689-
path: JsonPath {
690-
path: vec![
691-
JsonPathElem::Dot {
692-
key: "store".to_owned(),
693-
quoted: false,
694-
},
695-
JsonPathElem::Dot {
696-
key: "fruit".to_owned(),
697-
quoted: false,
698-
},
699-
JsonPathElem::Bracket {
700-
key: Expr::value(number("0")),
701-
},
702-
],
703-
},
704-
}
705-
);
706-
707-
// [*] is stored as Expr::Wildcard inside a Bracket element
708-
assert_eq!(
709-
databricks().verified_expr("raw:store.basket[*]"),
710-
Expr::JsonAccess {
711-
value: Box::new(Expr::Identifier(Ident::new("raw"))),
712-
path: JsonPath {
713-
path: vec![
714-
JsonPathElem::Dot {
715-
key: "store".to_owned(),
716-
quoted: false,
717-
},
718-
JsonPathElem::Dot {
719-
key: "basket".to_owned(),
720-
quoted: false,
721-
},
722-
JsonPathElem::Bracket {
723-
key: Expr::Wildcard(AttachedToken::empty()),
724-
},
725-
],
726-
},
727-
}
728-
);
729-
730-
// raw:['OWNER'] — bracket directly after the colon. An empty-key sentinel Dot is prepended
731-
// so that the display re-emits the leading `:`, enabling a correct round-trip.
732-
assert_eq!(
733-
databricks().verified_expr("raw:['OWNER']"),
734-
Expr::JsonAccess {
735-
value: Box::new(Expr::Identifier(Ident::new("raw"))),
736-
path: JsonPath {
737-
path: vec![
738-
JsonPathElem::Dot {
739-
key: String::new(),
740-
quoted: false,
741-
},
742-
JsonPathElem::Bracket {
743-
key: Expr::value(Value::SingleQuotedString("OWNER".to_owned())),
744-
},
745-
],
746-
},
747-
}
748-
);
749647
}

0 commit comments

Comments
 (0)