@@ -390,13 +390,17 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
390
390
match constraint {
391
391
JoinConstraint :: On ( sql_expr) => {
392
392
let mut keys: Vec < ( String , String ) > = vec ! [ ] ;
393
- let join_schema = left. schema ( ) . join ( & right. schema ( ) ) ?;
393
+ let left_schema = left. schema ( ) ;
394
+ let right_schema = right. schema ( ) ;
395
+ let join_schema = left_schema. join ( right_schema) ?;
394
396
395
397
// parse ON expression
396
398
let expr = self . sql_to_rex ( sql_expr, & join_schema) ?;
397
399
398
400
// extract join keys
399
- if let Err ( e) = extract_join_keys ( & expr, & mut keys) {
401
+ if let Err ( e) =
402
+ extract_join_keys ( & expr, left_schema, right_schema, & mut keys)
403
+ {
400
404
// Complex condition, try cross join. We still prefer to **not** allow cross
401
405
// joins in general case to avoid abysmal performance.
402
406
// However, CubeStore needs this specific form for "rolling window" queries.
@@ -1558,15 +1562,27 @@ fn remove_join_expressions(
1558
1562
/// foo = bar
1559
1563
/// foo = bar AND bar = baz AND ...
1560
1564
///
1561
- fn extract_join_keys ( expr : & Expr , accum : & mut Vec < ( String , String ) > ) -> Result < ( ) > {
1565
+ fn extract_join_keys (
1566
+ expr : & Expr ,
1567
+ ls : & DFSchema ,
1568
+ rs : & DFSchema ,
1569
+ accum : & mut Vec < ( String , String ) > ,
1570
+ ) -> Result < ( ) > {
1562
1571
match expr {
1563
1572
Expr :: BinaryExpr { left, op, right } => match op {
1564
1573
Operator :: Eq => match ( left. as_ref ( ) , right. as_ref ( ) ) {
1565
1574
( Expr :: Column ( l, la) , Expr :: Column ( r, ra) ) => {
1566
- accum. push ( (
1567
- Column :: new_with_alias ( l, la. clone ( ) ) . full_name ( ) ,
1568
- Column :: new_with_alias ( r, ra. clone ( ) ) . full_name ( ) ,
1569
- ) ) ;
1575
+ let mut lc = Column :: new_with_alias ( l, la. clone ( ) ) ;
1576
+ let mut rc = Column :: new_with_alias ( r, ra. clone ( ) ) ;
1577
+ // `L = R` and `R = L` are equivalent, handle the latter case.
1578
+ if ls. field_with_name ( lc. relation ( ) , lc. name ( ) ) . is_err ( )
1579
+ && rs. field_with_name ( lc. relation ( ) , lc. name ( ) ) . is_ok ( )
1580
+ {
1581
+ // Other cases should result in errors later, e.g. ambiguities in lookup.
1582
+ std:: mem:: swap ( & mut lc, & mut rc)
1583
+ }
1584
+
1585
+ accum. push ( ( lc. full_name ( ) , rc. full_name ( ) ) ) ;
1570
1586
Ok ( ( ) )
1571
1587
}
1572
1588
other => Err ( DataFusionError :: SQL ( ParserError ( format ! (
@@ -1575,8 +1591,8 @@ fn extract_join_keys(expr: &Expr, accum: &mut Vec<(String, String)>) -> Result<(
1575
1591
) ) ) ) ,
1576
1592
} ,
1577
1593
Operator :: And => {
1578
- extract_join_keys ( left, accum) ?;
1579
- extract_join_keys ( right, accum)
1594
+ extract_join_keys ( left, ls , rs , accum) ?;
1595
+ extract_join_keys ( right, ls , rs , accum)
1580
1596
}
1581
1597
other => Err ( DataFusionError :: SQL ( ParserError ( format ! (
1582
1598
"Unsupported expression '{:?}' in JOIN condition" ,
0 commit comments