1717
1818//! [`EliminateOuterJoin`] converts `LEFT/RIGHT/FULL` joins to `INNER` joins
1919use crate :: { OptimizerConfig , OptimizerRule } ;
20- use datafusion_common:: { Column , DFSchema , Result } ;
20+ use datafusion_common:: { internal_err , Column , DFSchema , Result } ;
2121use datafusion_expr:: logical_plan:: { Join , JoinType , LogicalPlan } ;
22- use datafusion_expr:: { Expr , Operator } ;
22+ use datafusion_expr:: { Expr , Filter , Operator } ;
2323
2424use crate :: optimizer:: ApplyOrder ;
25+ use datafusion_common:: tree_node:: Transformed ;
2526use datafusion_expr:: expr:: { BinaryExpr , Cast , TryCast } ;
2627use std:: sync:: Arc ;
2728
@@ -61,9 +62,29 @@ impl EliminateOuterJoin {
6162impl OptimizerRule for EliminateOuterJoin {
6263 fn try_optimize (
6364 & self ,
64- plan : & LogicalPlan ,
65+ _plan : & LogicalPlan ,
6566 _config : & dyn OptimizerConfig ,
6667 ) -> Result < Option < LogicalPlan > > {
68+ internal_err ! ( "Should have called EliminateOuterJoin::rewrite" )
69+ }
70+
71+ fn name ( & self ) -> & str {
72+ "eliminate_outer_join"
73+ }
74+
75+ fn apply_order ( & self ) -> Option < ApplyOrder > {
76+ Some ( ApplyOrder :: TopDown )
77+ }
78+
79+ fn supports_rewrite ( & self ) -> bool {
80+ true
81+ }
82+
83+ fn rewrite (
84+ & self ,
85+ plan : LogicalPlan ,
86+ _config : & dyn OptimizerConfig ,
87+ ) -> Result < Transformed < LogicalPlan > > {
6788 match plan {
6889 LogicalPlan :: Filter ( filter) => match filter. input . as_ref ( ) {
6990 LogicalPlan :: Join ( join) => {
@@ -75,7 +96,7 @@ impl OptimizerRule for EliminateOuterJoin {
7596 join. left . schema ( ) ,
7697 join. right . schema ( ) ,
7798 true ,
78- ) ? ;
99+ ) ;
79100
80101 let new_join_type = if join. join_type . is_outer ( ) {
81102 let mut left_non_nullable = false ;
@@ -96,7 +117,7 @@ impl OptimizerRule for EliminateOuterJoin {
96117 } else {
97118 join. join_type
98119 } ;
99- let new_join = LogicalPlan :: Join ( Join {
120+ let new_join = Arc :: new ( LogicalPlan :: Join ( Join {
100121 left : Arc :: new ( ( * join. left ) . clone ( ) ) ,
101122 right : Arc :: new ( ( * join. right ) . clone ( ) ) ,
102123 join_type : new_join_type,
@@ -105,23 +126,15 @@ impl OptimizerRule for EliminateOuterJoin {
105126 filter : join. filter . clone ( ) ,
106127 schema : join. schema . clone ( ) ,
107128 null_equals_null : join. null_equals_null ,
108- } ) ;
109- let exprs = plan . expressions ( ) ;
110- plan . with_new_exprs ( exprs , vec ! [ new_join ] ) . map ( Some )
129+ } ) ) ;
130+ Filter :: try_new ( filter . predicate , new_join )
131+ . map ( |f| Transformed :: yes ( LogicalPlan :: Filter ( f ) ) )
111132 }
112- _ => Ok ( None ) ,
133+ _ => Ok ( Transformed :: no ( LogicalPlan :: Filter ( filter ) ) ) ,
113134 } ,
114- _ => Ok ( None ) ,
135+ _ => Ok ( Transformed :: no ( plan ) ) ,
115136 }
116137 }
117-
118- fn name ( & self ) -> & str {
119- "eliminate_outer_join"
120- }
121-
122- fn apply_order ( & self ) -> Option < ApplyOrder > {
123- Some ( ApplyOrder :: TopDown )
124- }
125138}
126139
127140pub fn eliminate_outer (
@@ -169,11 +182,10 @@ fn extract_non_nullable_columns(
169182 left_schema : & Arc < DFSchema > ,
170183 right_schema : & Arc < DFSchema > ,
171184 top_level : bool ,
172- ) -> Result < ( ) > {
185+ ) {
173186 match expr {
174187 Expr :: Column ( col) => {
175188 non_nullable_cols. push ( col. clone ( ) ) ;
176- Ok ( ( ) )
177189 }
178190 Expr :: BinaryExpr ( BinaryExpr { left, op, right } ) => match op {
179191 // If one of the inputs are null for these operators, the results should be false.
@@ -189,7 +201,7 @@ fn extract_non_nullable_columns(
189201 left_schema,
190202 right_schema,
191203 false ,
192- ) ? ;
204+ ) ;
193205 extract_non_nullable_columns (
194206 right,
195207 non_nullable_cols,
@@ -208,15 +220,15 @@ fn extract_non_nullable_columns(
208220 left_schema,
209221 right_schema,
210222 top_level,
211- ) ? ;
223+ ) ;
212224 extract_non_nullable_columns (
213225 right,
214226 non_nullable_cols,
215227 left_schema,
216228 right_schema,
217229 top_level,
218- ) ? ;
219- return Ok ( ( ) ) ;
230+ ) ;
231+ return ;
220232 }
221233
222234 let mut left_non_nullable_cols: Vec < Column > = vec ! [ ] ;
@@ -228,14 +240,14 @@ fn extract_non_nullable_columns(
228240 left_schema,
229241 right_schema,
230242 top_level,
231- ) ? ;
243+ ) ;
232244 extract_non_nullable_columns (
233245 right,
234246 & mut right_non_nullable_cols,
235247 left_schema,
236248 right_schema,
237249 top_level,
238- ) ? ;
250+ ) ;
239251
240252 // for query: select *** from a left join b where b.c1 ... or b.c2 ...
241253 // this can be eliminated to inner join.
@@ -259,9 +271,8 @@ fn extract_non_nullable_columns(
259271 }
260272 }
261273 }
262- Ok ( ( ) )
263274 }
264- _ => Ok ( ( ) ) ,
275+ _ => { }
265276 } ,
266277 Expr :: Not ( arg) => extract_non_nullable_columns (
267278 arg,
@@ -272,7 +283,7 @@ fn extract_non_nullable_columns(
272283 ) ,
273284 Expr :: IsNotNull ( arg) => {
274285 if !top_level {
275- return Ok ( ( ) ) ;
286+ return ;
276287 }
277288 extract_non_nullable_columns (
278289 arg,
@@ -290,7 +301,7 @@ fn extract_non_nullable_columns(
290301 right_schema,
291302 false ,
292303 ) ,
293- _ => Ok ( ( ) ) ,
304+ _ => { }
294305 }
295306}
296307
0 commit comments