@@ -21,9 +21,10 @@ use super::AnalyzerRule;
21
21
use datafusion_common:: config:: ConfigOptions ;
22
22
use datafusion_common:: tree_node:: { Transformed , TreeNodeRewriter } ;
23
23
use datafusion_common:: { DFSchema , Result } ;
24
+ use datafusion_expr:: expr:: { Exists , InSubquery } ;
24
25
use datafusion_expr:: expr_rewriter:: { rewrite_preserving_name, FunctionRewrite } ;
25
26
use datafusion_expr:: utils:: merge_schema;
26
- use datafusion_expr:: { Expr , LogicalPlan } ;
27
+ use datafusion_expr:: { Expr , LogicalPlan , Subquery } ;
27
28
use std:: sync:: Arc ;
28
29
29
30
/// Analyzer rule that invokes [`FunctionRewrite`]s on expressions
@@ -45,52 +46,66 @@ impl AnalyzerRule for ApplyFunctionRewrites {
45
46
}
46
47
47
48
fn analyze ( & self , plan : LogicalPlan , options : & ConfigOptions ) -> Result < LogicalPlan > {
48
- self . analyze_internal ( & plan, options)
49
+ analyze_internal ( & plan, & self . function_rewrites , options)
49
50
}
50
51
}
51
52
52
- impl ApplyFunctionRewrites {
53
- fn analyze_internal (
54
- & self ,
55
- plan : & LogicalPlan ,
56
- options : & ConfigOptions ,
57
- ) -> Result < LogicalPlan > {
58
- // optimize child plans first
59
- let new_inputs = plan
60
- . inputs ( )
61
- . iter ( )
62
- . map ( |p| self . analyze_internal ( p, options) )
63
- . collect :: < Result < Vec < _ > > > ( ) ?;
64
-
65
- // get schema representing all available input fields. This is used for data type
66
- // resolution only, so order does not matter here
67
- let mut schema = merge_schema ( new_inputs. iter ( ) . collect ( ) ) ;
68
-
69
- if let LogicalPlan :: TableScan ( ts) = plan {
70
- let source_schema =
71
- DFSchema :: try_from_qualified_schema ( & ts. table_name , & ts. source . schema ( ) ) ?;
72
- schema. merge ( & source_schema) ;
73
- }
53
+ fn analyze_internal (
54
+ plan : & LogicalPlan ,
55
+ function_rewrites : & [ Arc < dyn FunctionRewrite + Send + Sync > ] ,
56
+ options : & ConfigOptions ,
57
+ ) -> Result < LogicalPlan > {
58
+ // optimize child plans first
59
+ let new_inputs = plan
60
+ . inputs ( )
61
+ . iter ( )
62
+ . map ( |p| analyze_internal ( p, function_rewrites, options) )
63
+ . collect :: < Result < Vec < _ > > > ( ) ?;
74
64
75
- let mut expr_rewrite = OperatorToFunctionRewriter {
76
- function_rewrites : & self . function_rewrites ,
77
- options,
78
- schema : & schema,
79
- } ;
65
+ // get schema representing all available input fields. This is used for data type
66
+ // resolution only, so order does not matter here
67
+ let mut schema = merge_schema ( new_inputs. iter ( ) . collect ( ) ) ;
80
68
81
- let new_expr = plan
82
- . expressions ( )
83
- . into_iter ( )
84
- . map ( |expr| {
85
- // ensure names don't change:
86
- // https://github.com/apache/arrow-datafusion/issues/3555
87
- rewrite_preserving_name ( expr, & mut expr_rewrite)
88
- } )
89
- . collect :: < Result < Vec < _ > > > ( ) ?;
90
-
91
- plan. with_new_exprs ( new_expr, new_inputs)
69
+ if let LogicalPlan :: TableScan ( ts) = plan {
70
+ let source_schema = DFSchema :: try_from_qualified_schema (
71
+ ts. table_name . clone ( ) ,
72
+ & ts. source . schema ( ) ,
73
+ ) ?;
74
+ schema. merge ( & source_schema) ;
92
75
}
76
+
77
+ let mut expr_rewrite = OperatorToFunctionRewriter {
78
+ function_rewrites,
79
+ options,
80
+ schema : & schema,
81
+ } ;
82
+
83
+ let new_expr = plan
84
+ . expressions ( )
85
+ . into_iter ( )
86
+ . map ( |expr| {
87
+ // ensure names don't change:
88
+ // https://github.com/apache/arrow-datafusion/issues/3555
89
+ rewrite_preserving_name ( expr, & mut expr_rewrite)
90
+ } )
91
+ . collect :: < Result < Vec < _ > > > ( ) ?;
92
+
93
+ plan. with_new_exprs ( new_expr, new_inputs)
93
94
}
95
+
96
+ fn rewrite_subquery (
97
+ mut subquery : Subquery ,
98
+ function_rewrites : & [ Arc < dyn FunctionRewrite + Send + Sync > ] ,
99
+ options : & ConfigOptions ,
100
+ ) -> Result < Subquery > {
101
+ subquery. subquery = Arc :: new ( analyze_internal (
102
+ & subquery. subquery ,
103
+ function_rewrites,
104
+ options,
105
+ ) ?) ;
106
+ Ok ( subquery)
107
+ }
108
+
94
109
struct OperatorToFunctionRewriter < ' a > {
95
110
function_rewrites : & ' a [ Arc < dyn FunctionRewrite + Send + Sync > ] ,
96
111
options : & ' a ConfigOptions ,
@@ -111,6 +126,40 @@ impl<'a> TreeNodeRewriter for OperatorToFunctionRewriter<'a> {
111
126
expr = result. data
112
127
}
113
128
129
+ // recurse into subqueries if needed
130
+ let expr = match expr {
131
+ Expr :: ScalarSubquery ( subquery) => Expr :: ScalarSubquery ( rewrite_subquery (
132
+ subquery,
133
+ self . function_rewrites ,
134
+ self . options ,
135
+ ) ?) ,
136
+
137
+ Expr :: Exists ( Exists { subquery, negated } ) => Expr :: Exists ( Exists {
138
+ subquery : rewrite_subquery (
139
+ subquery,
140
+ self . function_rewrites ,
141
+ self . options ,
142
+ ) ?,
143
+ negated,
144
+ } ) ,
145
+
146
+ Expr :: InSubquery ( InSubquery {
147
+ expr,
148
+ subquery,
149
+ negated,
150
+ } ) => Expr :: InSubquery ( InSubquery {
151
+ expr,
152
+ subquery : rewrite_subquery (
153
+ subquery,
154
+ self . function_rewrites ,
155
+ self . options ,
156
+ ) ?,
157
+ negated,
158
+ } ) ,
159
+
160
+ expr => expr,
161
+ } ;
162
+
114
163
Ok ( if transformed {
115
164
Transformed :: yes ( expr)
116
165
} else {
0 commit comments