@@ -76,6 +76,36 @@ impl OptimizerRule for ExtractEquijoinPredicate {
76
76
right_schema,
77
77
) ?;
78
78
79
+ // If there are no equijoin predicates and no existing on then try a nullable join
80
+ if equijoin_predicates. is_empty ( ) && on. is_empty ( ) {
81
+ let ( equinullable_predicates, non_equinullable_expr) =
82
+ split_eq_and_noneq_join_predicate_nullable (
83
+ expr,
84
+ left_schema,
85
+ right_schema,
86
+ ) ?;
87
+ if !equinullable_predicates. is_empty ( ) {
88
+ let optimized_plan = ( !equinullable_predicates. is_empty ( ) )
89
+ . then ( || {
90
+ let mut new_on = on. clone ( ) ;
91
+ new_on. extend ( equinullable_predicates) ;
92
+
93
+ LogicalPlan :: Join ( Join {
94
+ left : left. clone ( ) ,
95
+ right : right. clone ( ) ,
96
+ on : new_on,
97
+ filter : non_equinullable_expr,
98
+ join_type : * join_type,
99
+ join_constraint : * join_constraint,
100
+ schema : schema. clone ( ) ,
101
+ null_equals_null : true ,
102
+ } )
103
+ } ) ;
104
+
105
+ return Ok ( optimized_plan) ;
106
+ }
107
+ }
108
+
79
109
let optimized_plan = ( !equijoin_predicates. is_empty ( ) ) . then ( || {
80
110
let mut new_on = on. clone ( ) ;
81
111
new_on. extend ( equijoin_predicates) ;
@@ -108,22 +138,19 @@ impl OptimizerRule for ExtractEquijoinPredicate {
108
138
}
109
139
}
110
140
111
- fn split_eq_and_noneq_join_predicate (
141
+ fn split_equality_join_predicate (
112
142
filter : & Expr ,
113
143
left_schema : & Arc < DFSchema > ,
114
144
right_schema : & Arc < DFSchema > ,
145
+ match_bin_op : Operator ,
115
146
) -> Result < ( Vec < EquijoinPredicate > , Option < Expr > ) > {
116
147
let exprs = split_conjunction ( filter) ;
117
148
118
149
let mut accum_join_keys: Vec < ( Expr , Expr ) > = vec ! [ ] ;
119
150
let mut accum_filters: Vec < Expr > = vec ! [ ] ;
120
151
for expr in exprs {
121
152
match expr {
122
- Expr :: BinaryExpr ( BinaryExpr {
123
- left,
124
- op : Operator :: Eq ,
125
- right,
126
- } ) => {
153
+ Expr :: BinaryExpr ( BinaryExpr { left, op, right } ) if op == & match_bin_op => {
127
154
let left = left. as_ref ( ) ;
128
155
let right = right. as_ref ( ) ;
129
156
@@ -155,6 +182,27 @@ fn split_eq_and_noneq_join_predicate(
155
182
Ok ( ( accum_join_keys, result_filter) )
156
183
}
157
184
185
+ fn split_eq_and_noneq_join_predicate (
186
+ filter : & Expr ,
187
+ left_schema : & Arc < DFSchema > ,
188
+ right_schema : & Arc < DFSchema > ,
189
+ ) -> Result < ( Vec < EquijoinPredicate > , Option < Expr > ) > {
190
+ split_equality_join_predicate ( filter, left_schema, right_schema, Operator :: Eq )
191
+ }
192
+
193
+ fn split_eq_and_noneq_join_predicate_nullable (
194
+ filter : & Expr ,
195
+ left_schema : & Arc < DFSchema > ,
196
+ right_schema : & Arc < DFSchema > ,
197
+ ) -> Result < ( Vec < EquijoinPredicate > , Option < Expr > ) > {
198
+ split_equality_join_predicate (
199
+ filter,
200
+ left_schema,
201
+ right_schema,
202
+ Operator :: IsNotDistinctFrom ,
203
+ )
204
+ }
205
+
158
206
#[ cfg( test) ]
159
207
mod tests {
160
208
use super :: * ;
0 commit comments