@@ -28,6 +28,15 @@ use crate::{
2828} ;
2929use datafusion_expr_common:: signature:: { Signature , TypeSignature } ;
3030
31+ /// Alias used to mark inferred join predicates that should remain join filters
32+ /// and not be converted into additional equijoin keys during optimization.
33+ pub const INFERRED_PREDICATE_ALIAS : & str = "__datafusion_inferred_join_predicate" ;
34+
35+ /// Returns true if expr is an alias used to mark inferred join predicates.
36+ pub fn is_inferred_alias ( expr : & Expr ) -> bool {
37+ matches ! ( expr, Expr :: Alias ( Alias { name, .. } ) if name == INFERRED_PREDICATE_ALIAS )
38+ }
39+
3140use arrow:: datatypes:: { DataType , Field , Schema } ;
3241use datafusion_common:: tree_node:: {
3342 Transformed , TransformedResult , TreeNode , TreeNodeRecursion ,
@@ -946,7 +955,9 @@ fn split_conjunction_impl<'a>(expr: &'a Expr, mut exprs: Vec<&'a Expr>) -> Vec<&
946955 let exprs = split_conjunction_impl ( left, exprs) ;
947956 split_conjunction_impl ( right, exprs)
948957 }
949- Expr :: Alias ( Alias { expr, .. } ) => split_conjunction_impl ( expr, exprs) ,
958+ Expr :: Alias ( alias) if !is_inferred_alias ( expr) => {
959+ split_conjunction_impl ( & alias. expr , exprs)
960+ }
950961 other => {
951962 exprs. push ( other) ;
952963 exprs
@@ -970,7 +981,11 @@ pub fn iter_conjunction(expr: &Expr) -> impl Iterator<Item = &Expr> {
970981 stack. push ( right) ;
971982 stack. push ( left) ;
972983 }
973- Expr :: Alias ( Alias { expr, .. } ) => stack. push ( expr) ,
984+ Expr :: Alias ( Alias { expr, name, .. } )
985+ if name != INFERRED_PREDICATE_ALIAS =>
986+ {
987+ stack. push ( expr) ;
988+ }
974989 other => return Some ( other) ,
975990 }
976991 }
@@ -994,7 +1009,11 @@ pub fn iter_conjunction_owned(expr: Expr) -> impl Iterator<Item = Expr> {
9941009 stack. push ( * right) ;
9951010 stack. push ( * left) ;
9961011 }
997- Expr :: Alias ( Alias { expr, .. } ) => stack. push ( * expr) ,
1012+ Expr :: Alias ( Alias { expr, name, .. } )
1013+ if name != INFERRED_PREDICATE_ALIAS =>
1014+ {
1015+ stack. push ( * expr) ;
1016+ }
9981017 other => return Some ( other) ,
9991018 }
10001019 }
@@ -1063,8 +1082,13 @@ fn split_binary_owned_impl(
10631082 let exprs = split_binary_owned_impl ( * left, operator, exprs) ;
10641083 split_binary_owned_impl ( * right, operator, exprs)
10651084 }
1066- Expr :: Alias ( Alias { expr, .. } ) => {
1067- split_binary_owned_impl ( * expr, operator, exprs)
1085+ Expr :: Alias ( alias) => {
1086+ if is_inferred_alias ( & Expr :: Alias ( alias. clone ( ) ) ) {
1087+ exprs. push ( Expr :: Alias ( alias) ) ;
1088+ exprs
1089+ } else {
1090+ split_binary_owned_impl ( * alias. expr , operator, exprs)
1091+ }
10681092 }
10691093 other => {
10701094 exprs. push ( other) ;
@@ -1090,7 +1114,9 @@ fn split_binary_impl<'a>(
10901114 let exprs = split_binary_impl ( left, operator, exprs) ;
10911115 split_binary_impl ( right, operator, exprs)
10921116 }
1093- Expr :: Alias ( Alias { expr, .. } ) => split_binary_impl ( expr, operator, exprs) ,
1117+ Expr :: Alias ( alias) if !is_inferred_alias ( expr) => {
1118+ split_binary_impl ( & alias. expr , operator, exprs)
1119+ }
10941120 other => {
10951121 exprs. push ( other) ;
10961122 exprs
@@ -1648,6 +1674,17 @@ mod tests {
16481674 assert_eq ! ( result, vec![ & expr1, & expr2] ) ;
16491675 }
16501676
1677+ #[ test]
1678+ fn test_split_conjunction_inferred_alias ( ) {
1679+ let expr = col ( "a" ) . eq ( col ( "b" ) ) . alias ( INFERRED_PREDICATE_ALIAS ) ;
1680+ let result = split_conjunction ( & expr) ;
1681+ assert_eq ! ( result. len( ) , 1 ) ;
1682+ match result[ 0 ] {
1683+ Expr :: Alias ( alias) => assert_eq ! ( alias. name, INFERRED_PREDICATE_ALIAS ) ,
1684+ _ => panic ! ( "expected alias" ) ,
1685+ }
1686+ }
1687+
16511688 #[ test]
16521689 fn test_split_conjunction_or ( ) {
16531690 let expr = col ( "a" ) . eq ( lit ( 5 ) ) . or ( col ( "b" ) ) ;
@@ -1705,6 +1742,17 @@ mod tests {
17051742 ) ;
17061743 }
17071744
1745+ #[ test]
1746+ fn test_split_conjunction_owned_inferred_alias ( ) {
1747+ let expr = col ( "a" ) . eq ( col ( "b" ) ) . alias ( INFERRED_PREDICATE_ALIAS ) ;
1748+ let result = split_conjunction_owned ( expr) ;
1749+ assert_eq ! ( result. len( ) , 1 ) ;
1750+ match & result[ 0 ] {
1751+ Expr :: Alias ( alias) => assert_eq ! ( alias. name, INFERRED_PREDICATE_ALIAS ) ,
1752+ _ => panic ! ( "expected alias" ) ,
1753+ }
1754+ }
1755+
17081756 #[ test]
17091757 fn test_conjunction_empty ( ) {
17101758 assert_eq ! ( conjunction( vec![ ] ) , None ) ;
0 commit comments