@@ -18093,3 +18093,148 @@ fn test_binary_kw_as_cast() {
1809318093 all_dialects_where(|d| d.supports_binary_kw_as_cast())
1809418094 .one_statement_parses_to("SELECT BINARY 1+1", "SELECT CAST(1 + 1 AS BINARY)");
1809518095}
18096+
18097+ #[test]
18098+ fn parse_semi_structured_data_traversal() {
18099+ let dialects = TestedDialects::new(vec![
18100+ Box::new(GenericDialect {}),
18101+ Box::new(SnowflakeDialect {}),
18102+ Box::new(DatabricksDialect {}),
18103+ ]);
18104+
18105+ // most basic case
18106+ let sql = "SELECT a:b FROM t";
18107+ let select = dialects.verified_only_select(sql);
18108+ assert_eq!(
18109+ SelectItem::UnnamedExpr(Expr::JsonAccess {
18110+ value: Box::new(Expr::Identifier(Ident::new("a"))),
18111+ path: JsonPath {
18112+ path: vec![JsonPathElem::Dot {
18113+ key: "b".to_owned(),
18114+ quoted: false
18115+ }]
18116+ },
18117+ }),
18118+ select.projection[0]
18119+ );
18120+
18121+ // identifier can be quoted
18122+ let sql = r#"SELECT a:"my long object key name" FROM t"#;
18123+ let select = dialects.verified_only_select(sql);
18124+ assert_eq!(
18125+ SelectItem::UnnamedExpr(Expr::JsonAccess {
18126+ value: Box::new(Expr::Identifier(Ident::new("a"))),
18127+ path: JsonPath {
18128+ path: vec![JsonPathElem::Dot {
18129+ key: "my long object key name".to_owned(),
18130+ quoted: true
18131+ }]
18132+ },
18133+ }),
18134+ select.projection[0]
18135+ );
18136+
18137+ dialects.verified_stmt("SELECT a:b::INT FROM t");
18138+
18139+ // unquoted keywords are permitted in the object key
18140+ let sql = "SELECT a:select, a:from FROM t";
18141+ let select = dialects.verified_only_select(sql);
18142+ assert_eq!(
18143+ vec![
18144+ SelectItem::UnnamedExpr(Expr::JsonAccess {
18145+ value: Box::new(Expr::Identifier(Ident::new("a"))),
18146+ path: JsonPath {
18147+ path: vec![JsonPathElem::Dot {
18148+ key: "select".to_owned(),
18149+ quoted: false
18150+ }]
18151+ },
18152+ }),
18153+ SelectItem::UnnamedExpr(Expr::JsonAccess {
18154+ value: Box::new(Expr::Identifier(Ident::new("a"))),
18155+ path: JsonPath {
18156+ path: vec![JsonPathElem::Dot {
18157+ key: "from".to_owned(),
18158+ quoted: false
18159+ }]
18160+ },
18161+ })
18162+ ],
18163+ select.projection
18164+ );
18165+
18166+ // multiple levels can be traversed
18167+ // https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation
18168+ let sql = r#"SELECT a:foo."bar".baz"#;
18169+ let select = dialects.verified_only_select(sql);
18170+ assert_eq!(
18171+ vec![SelectItem::UnnamedExpr(Expr::JsonAccess {
18172+ value: Box::new(Expr::Identifier(Ident::new("a"))),
18173+ path: JsonPath {
18174+ path: vec![
18175+ JsonPathElem::Dot {
18176+ key: "foo".to_owned(),
18177+ quoted: false,
18178+ },
18179+ JsonPathElem::Dot {
18180+ key: "bar".to_owned(),
18181+ quoted: true,
18182+ },
18183+ JsonPathElem::Dot {
18184+ key: "baz".to_owned(),
18185+ quoted: false,
18186+ }
18187+ ]
18188+ },
18189+ })],
18190+ select.projection
18191+ );
18192+
18193+ // dot and bracket notation can be mixed (starting with : case)
18194+ // https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation
18195+ let sql = r#"SELECT a:foo[0].bar"#;
18196+ let select = dialects.verified_only_select(sql);
18197+ assert_eq!(
18198+ vec![SelectItem::UnnamedExpr(Expr::JsonAccess {
18199+ value: Box::new(Expr::Identifier(Ident::new("a"))),
18200+ path: JsonPath {
18201+ path: vec![
18202+ JsonPathElem::Dot {
18203+ key: "foo".to_owned(),
18204+ quoted: false,
18205+ },
18206+ JsonPathElem::Bracket {
18207+ key: Expr::value(number("0")),
18208+ },
18209+ JsonPathElem::Dot {
18210+ key: "bar".to_owned(),
18211+ quoted: false,
18212+ }
18213+ ]
18214+ },
18215+ })],
18216+ select.projection
18217+ );
18218+ }
18219+
18220+ #[test]
18221+ fn parse_array_subscript() {
18222+ let dialects = all_dialects_except(|d| {
18223+ d.is::<MsSqlDialect>()
18224+ || d.is::<SnowflakeDialect>()
18225+ || d.is::<SQLiteDialect>()
18226+ || d.is::<RedshiftSqlDialect>()
18227+ });
18228+
18229+ dialects.verified_stmt("SELECT arr[1]");
18230+ dialects.verified_stmt("SELECT arr[:]");
18231+ dialects.verified_stmt("SELECT arr[1:2]");
18232+ dialects.verified_stmt("SELECT arr[1:2:4]");
18233+ dialects.verified_stmt("SELECT arr[1:array_length(arr)]");
18234+ dialects.verified_stmt("SELECT arr[array_length(arr) - 1:array_length(arr)]");
18235+ dialects
18236+ .verified_stmt("SELECT arr[array_length(arr) - 2:array_length(arr) - 1:array_length(arr)]");
18237+
18238+ dialects.verified_stmt("SELECT arr[1][2]");
18239+ dialects.verified_stmt("SELECT arr[:][:]");
18240+ }
0 commit comments