From b85d7db48553739829c59dd5e2e0069c8491dfa0 Mon Sep 17 00:00:00 2001 From: osipovartem Date: Sun, 13 Sep 2026 23:21:20 +0300 Subject: [PATCH] feat(sql): plan Snowflake directed joins --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- datafusion/sql/src/unparser/plan.rs | 3 +++ datafusion/sql/tests/sql_integration.rs | 18 ++++++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e843f90a4c3a..cbc481bfcc3a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5877,7 +5877,7 @@ dependencies = [ [[package]] name = "sqlparser" version = "0.62.0" -source = "git+https://github.com/Embucket/datafusion-sqlparser-rs.git?rev=ff0378d5b2205e839360ab473efe9bcfa520f65f#ff0378d5b2205e839360ab473efe9bcfa520f65f" +source = "git+https://github.com/Embucket/datafusion-sqlparser-rs.git?rev=707457f75c46c99c441b2859ad5bb01e21e5f105#707457f75c46c99c441b2859ad5bb01e21e5f105" dependencies = [ "log", "recursive", @@ -5887,7 +5887,7 @@ dependencies = [ [[package]] name = "sqlparser_derive" version = "0.5.0" -source = "git+https://github.com/Embucket/datafusion-sqlparser-rs.git?rev=ff0378d5b2205e839360ab473efe9bcfa520f65f#ff0378d5b2205e839360ab473efe9bcfa520f65f" +source = "git+https://github.com/Embucket/datafusion-sqlparser-rs.git?rev=707457f75c46c99c441b2859ad5bb01e21e5f105#707457f75c46c99c441b2859ad5bb01e21e5f105" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 06e9a6155c24b..5f116e7ffc46a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -196,7 +196,7 @@ regex = "1.12" rstest = "0.26.1" serde_json = "1" sha2 = "^0.11.0" -sqlparser = { git = "https://github.com/Embucket/datafusion-sqlparser-rs.git", rev = "ff0378d5b2205e839360ab473efe9bcfa520f65f", default-features = false, features = [ +sqlparser = { git = "https://github.com/Embucket/datafusion-sqlparser-rs.git", rev = "707457f75c46c99c441b2859ad5bb01e21e5f105", default-features = false, features = [ "std", "visitor", ] } diff --git a/datafusion/sql/src/unparser/plan.rs b/datafusion/sql/src/unparser/plan.rs index cf8bf1a03c8f6..94b3476021b06 100644 --- a/datafusion/sql/src/unparser/plan.rs +++ b/datafusion/sql/src/unparser/plan.rs @@ -609,6 +609,7 @@ impl Unparser<'_> { let cross_join = ast::Join { relation: flatten_factor, global: false, + directed: false, join_operator: ast::JoinOperator::CrossJoin( ast::JoinConstraint::None, ), @@ -1449,6 +1450,7 @@ impl Unparser<'_> { let ast_join = ast::Join { relation, global: false, + directed: false, join_operator: self .join_operator_to_sql(join.join_type, join_constraint)?, }; @@ -1870,6 +1872,7 @@ impl Unparser<'_> { let ast_join = ast::Join { relation, global: false, + directed: false, join_operator: ast::JoinOperator::AsOf { match_condition, constraint, diff --git a/datafusion/sql/tests/sql_integration.rs b/datafusion/sql/tests/sql_integration.rs index 04a903e09d45e..fc1ef89331a84 100644 --- a/datafusion/sql/tests/sql_integration.rs +++ b/datafusion/sql/tests/sql_integration.rs @@ -3455,6 +3455,24 @@ fn minus_is_an_alias_for_except() { ); } +#[test] +fn snowflake_directed_join_plans() { + let sql = "SELECT person.id, orders.order_id \ + FROM person \ + INNER DIRECTED JOIN orders \ + ON person.id = orders.customer_id"; + let plan = logical_plan_with_dialect(sql, &SnowflakeDialect {}).unwrap(); + assert_snapshot!( + plan, + @r" + Projection: person.id, orders.order_id + Inner Join: Filter: person.id = orders.customer_id + TableScan: person + TableScan: orders + " + ); +} + #[test] fn empty_over() { let sql = "SELECT order_id, MAX(order_id) OVER () from orders";