diff --git a/datafusion/src/logical_plan/builder.rs b/datafusion/src/logical_plan/builder.rs index a742f346207a..0dfc1e7aa048 100644 --- a/datafusion/src/logical_plan/builder.rs +++ b/datafusion/src/logical_plan/builder.rs @@ -287,16 +287,63 @@ impl LogicalPlanBuilder { .into_iter() .zip(join_keys.1.into_iter()) .map(|(l, r)| { - let mut swap = false; let l = l.into(); - let left_key = l.clone().normalize(&self.plan).or_else(|_| { - swap = true; - l.normalize(right) - }); - if swap { - (r.into().normalize(&self.plan), left_key) - } else { - (left_key, r.into().normalize(right)) + let r = r.into(); + + match (&l.relation, &r.relation) { + (Some(lr), Some(rr)) => { + let l_is_left = + self.plan.schema().field_with_qualified_name(lr, &l.name); + let l_is_right = + right.schema().field_with_qualified_name(lr, &l.name); + let r_is_left = + self.plan.schema().field_with_qualified_name(rr, &r.name); + let r_is_right = + right.schema().field_with_qualified_name(rr, &r.name); + + match (l_is_left, l_is_right, r_is_left, r_is_right) { + (_, Ok(_), Ok(_), _) => (Ok(r), Ok(l)), + (Ok(_), _, _, Ok(_)) => (Ok(l), Ok(r)), + _ => (l.normalize(&self.plan), r.normalize(right)), + } + } + (Some(lr), None) => { + let l_is_left = + self.plan.schema().field_with_qualified_name(lr, &l.name); + let l_is_right = + right.schema().field_with_qualified_name(lr, &l.name); + + match (l_is_left, l_is_right) { + (Ok(_), _) => (Ok(l), r.normalize(right)), + (_, Ok(_)) => (r.normalize(&self.plan), Ok(l)), + _ => (l.normalize(&self.plan), r.normalize(right)), + } + } + (None, Some(rr)) => { + let r_is_left = + self.plan.schema().field_with_qualified_name(rr, &r.name); + let r_is_right = + right.schema().field_with_qualified_name(rr, &r.name); + + match (r_is_left, r_is_right) { + (Ok(_), _) => (Ok(r), l.normalize(right)), + (_, Ok(_)) => (l.normalize(&self.plan), Ok(r)), + _ => (l.normalize(&self.plan), r.normalize(right)), + } + } + (None, None) => { + let mut swap = false; + let left_key = + l.clone().normalize(&self.plan).or_else(|_| { + swap = true; + l.normalize(right) + }); + if swap { + (r.normalize(&self.plan), left_key) + } else { + (left_key, r.normalize(right)) + } + } } }) .unzip(); diff --git a/datafusion/tests/sql.rs b/datafusion/tests/sql.rs index bfe2f2fc4913..68c4c4ebe694 100644 --- a/datafusion/tests/sql.rs +++ b/datafusion/tests/sql.rs @@ -1730,6 +1730,17 @@ async fn equijoin() -> Result<()> { let actual = execute(&mut ctx, sql).await; assert_eq!(expected, actual); } + + let mut ctx = create_join_context_qualified()?; + let equivalent_sql = [ + "SELECT t1.a, t2.b FROM t1 INNER JOIN t2 ON t1.a = t2.a ORDER BY t1.a", + "SELECT t1.a, t2.b FROM t1 INNER JOIN t2 ON t2.a = t1.a ORDER BY t1.a", + ]; + let expected = vec![vec!["1", "100"], vec!["2", "200"], vec!["4", "400"]]; + for sql in equivalent_sql.iter() { + let actual = execute(&mut ctx, sql).await; + assert_eq!(expected, actual); + } Ok(()) }