This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-2377-86a61436587f2ffdfd916f4966a5dba463266d5f
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit ed98c40011ea0966392e85bb81f815955f2a7de1
Author: Mosha Pasumansky <[email protected]>
AuthorDate: Tue Jul 14 00:47:28 2026 -0700

    PostgreSQL: support right-deep join chains (deferred ON clauses) (#2377)
    
    Co-authored-by: Claude Sonnet 4.6 <[email protected]>
---
 src/dialect/postgresql.rs   |  6 ++++++
 tests/sqlparser_postgres.rs | 17 +++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/src/dialect/postgresql.rs b/src/dialect/postgresql.rs
index e980fc64..d342276e 100644
--- a/src/dialect/postgresql.rs
+++ b/src/dialect/postgresql.rs
@@ -299,6 +299,12 @@ impl Dialect for PostgreSqlDialect {
         true
     }
 
+    /// PostgreSQL supports right-deep join chains: `t0 JOIN t1 JOIN t2 ON c1 
ON c2`
+    /// See: 
<https://www.postgresql.org/docs/current/queries-table-expressions.html#QUERIES-JOIN>
+    fn supports_left_associative_joins_without_parens(&self) -> bool {
+        false
+    }
+
     /// Postgres supports `NOTNULL` as an alias for `IS NOT NULL`
     /// See: <https://www.postgresql.org/docs/17/functions-comparison.html>
     fn supports_notnull_operator(&self) -> bool {
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index 9ee6ab3d..9efa1dac 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -9582,3 +9582,20 @@ fn parse_limit_after_locking_clause() {
     // The pre-existing ordering keeps round-tripping unchanged.
     pg().verified_stmt("SELECT * FROM t ORDER BY id LIMIT 5 FOR UPDATE SKIP 
LOCKED");
 }
+
+#[test]
+fn parse_right_deep_join_chain() {
+    // PostgreSQL supports right-deep join syntax where ON clauses follow all 
JOIN keywords:
+    //   t0 JOIN t1 JOIN t2 ON c1 ON c2
+    // which is equivalent to (and serialized as) t0 JOIN (t1 JOIN t2 ON c1) 
ON c2.
+    pg().one_statement_parses_to(
+        "SELECT * FROM t0 INNER JOIN t1 INNER JOIN t2 ON true ON true",
+        "SELECT * FROM t0 INNER JOIN (t1 INNER JOIN t2 ON true) ON true",
+    );
+    pg().one_statement_parses_to(
+        "SELECT * FROM t0 INNER JOIN t1 INNER JOIN t2 INNER JOIN t3 ON true ON 
true ON true",
+        "SELECT * FROM t0 INNER JOIN (t1 INNER JOIN (t2 INNER JOIN t3 ON true) 
ON true) ON true",
+    );
+    // NATURAL JOIN followed by a constrained join must stay left-associative.
+    pg().verified_stmt("SELECT * FROM t0 NATURAL JOIN t1 INNER JOIN t2 ON 
true");
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to