1515// specific language governing permissions and limitations
1616// under the License.
1717
18- //! [`PhysicalExprResolver`] ensures that the physical plan is prepared for placeholder resolution
19- //! by wrapping it in a [`TransformPlanExec`] with a [`ResolvePlaceholdersRule`] if the plan
20- //! contains any unresolved placeholders. The actual resolution happens during execution.
18+ //! [`ExecutionTransformationApplier`] ensures that the required execution transformations
19+ //! are applied to the physical plan.
2120
22- use std:: sync:: Arc ;
21+ use std:: { borrow :: Cow , sync:: Arc } ;
2322
2423use datafusion_common:: {
2524 Result ,
@@ -28,71 +27,72 @@ use datafusion_common::{
2827} ;
2928use datafusion_physical_plan:: {
3029 ExecutionPlan ,
31- plan_transformer:: { ResolvePlaceholdersRule , TransformPlanExec } ,
30+ plan_transformer:: { ExecutionTransformationRule , TransformPlanExec } ,
3231} ;
3332
3433use crate :: PhysicalOptimizerRule ;
3534
36- /// The phase in which the [`PhysicalExprResolver `] rule is applied.
37- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
38- pub enum PhysicalExprResolverPhase {
35+ /// The phase in which the [`ExecutionTransformationApplier `] rule is applied.
36+ #[ derive( Debug ) ]
37+ pub enum ExecutionTransformationApplierPhase {
3938 /// Optimization that happens before most other optimizations.
4039 /// This optimization removes all [`TransformPlanExec`] execution plans from the plan
4140 /// tree.
4241 Pre ,
4342 /// Optimization that happens after most other optimizations.
44- /// This optimization checks for the presence of placeholders in the optimized plan, and if
45- /// they are present, wraps the plan in a [`TransformPlanExec`] with a [`ResolvePlaceholdersRule`].
46- Post ,
43+ /// This optimization checks if `rule` requires to transform the plan and wraps the plan with
44+ /// [`TransformPlanExec`] if it so, or adds rule to the existing transformation node.
45+ Post {
46+ rule : Arc < dyn ExecutionTransformationRule > ,
47+ } ,
4748}
4849
49- /// Physical optimizer rule that prepares the plan for placeholder resolution during execution.
50+ /// Physical optimizer rule that wraps the plan with a certain execution-stage transformation .
5051#[ derive( Debug ) ]
51- pub struct PhysicalExprResolver {
52- phase : PhysicalExprResolverPhase ,
52+ pub struct ExecutionTransformationApplier {
53+ phase : ExecutionTransformationApplierPhase ,
54+ name : Cow < ' static , str > ,
5355}
5456
55- impl PhysicalExprResolver {
56- /// Creates a new [`PhysicalExprResolver`] optimizer rule that runs in the pre-optimization
57- /// phase. In this phase, the rule removes any existing [`TransformPlanExec`] from the
58- /// plan tree.
57+ impl ExecutionTransformationApplier {
58+ /// Creates a new [`ExecutionTransformationApplier`] optimizer rule that runs in the
59+ /// pre-optimization phase.
5960 pub fn new ( ) -> Self {
6061 Self {
61- phase : PhysicalExprResolverPhase :: Pre ,
62+ phase : ExecutionTransformationApplierPhase :: Pre ,
63+ name : Cow :: Borrowed ( "ExecutionTransformationApplier" ) ,
6264 }
6365 }
6466
65- /// Creates a new [`PhysicalExprResolver `] optimizer rule that runs in the post-optimization
66- /// phase. In this phase, the rule wraps the physical plan in a [`TransformPlanExec`] with a
67- /// [`ResolvePlaceholdersRule`] if the plan contains any unresolved placeholders.
68- pub fn new_post_optimization ( ) -> Self {
67+ /// Creates a new [`ExecutionTransformationApplier `] optimizer rule that runs in the
68+ /// post-optimization phase.
69+ pub fn new_post_optimization ( rule : Arc < dyn ExecutionTransformationRule > ) -> Self {
70+ let name = format ! ( "ExecutionTransformationApplier({})" , rule . name ( ) ) ;
6971 Self {
70- phase : PhysicalExprResolverPhase :: Post ,
72+ phase : ExecutionTransformationApplierPhase :: Post { rule } ,
73+ name : name. into ( ) ,
7174 }
7275 }
7376}
7477
75- impl Default for PhysicalExprResolver {
78+ impl Default for ExecutionTransformationApplier {
7679 fn default ( ) -> Self {
7780 Self :: new ( )
7881 }
7982}
8083
81- impl PhysicalOptimizerRule for PhysicalExprResolver {
84+ impl PhysicalOptimizerRule for ExecutionTransformationApplier {
8285 fn name ( & self ) -> & str {
83- match self . phase {
84- PhysicalExprResolverPhase :: Pre => "PhysicalExprResolver" ,
85- PhysicalExprResolverPhase :: Post => "PhysicalExprResolver(Post)" ,
86- }
86+ & self . name
8787 }
8888
8989 fn optimize (
9090 & self ,
9191 plan : Arc < dyn ExecutionPlan > ,
9292 _config : & ConfigOptions ,
9393 ) -> Result < Arc < dyn ExecutionPlan > > {
94- match self . phase {
95- PhysicalExprResolverPhase :: Pre => plan
94+ match & self . phase {
95+ ExecutionTransformationApplierPhase :: Pre => plan
9696 . transform_up ( |plan| {
9797 if let Some ( plan) = plan. as_any ( ) . downcast_ref :: < TransformPlanExec > ( )
9898 {
@@ -102,26 +102,22 @@ impl PhysicalOptimizerRule for PhysicalExprResolver {
102102 }
103103 } )
104104 . map ( |t| t. data ) ,
105- PhysicalExprResolverPhase :: Post => {
105+ ExecutionTransformationApplierPhase :: Post { rule } => {
106106 if let Some ( transformer) =
107107 plan. as_any ( ) . downcast_ref :: < TransformPlanExec > ( )
108108 {
109- let resolves_placeholders =
110- transformer. has_rule :: < ResolvePlaceholdersRule > ( ) ;
111-
112- if resolves_placeholders {
109+ let has_rule = transformer. has_dyn_rule ( rule) ;
110+ if has_rule {
111+ // Rule is already applied.
113112 Ok ( plan)
114113 } else {
115114 transformer
116- . add_rule ( Box :: new ( ResolvePlaceholdersRule :: new ( ) ) )
115+ . add_rule ( Arc :: clone ( rule ) )
117116 . map ( |r| Arc :: new ( r) as Arc < _ > )
118117 }
119118 } else {
120- let transformer = TransformPlanExec :: try_new (
121- plan,
122- vec ! [ Box :: new( ResolvePlaceholdersRule :: new( ) ) ] ,
123- ) ?;
124-
119+ let transformer =
120+ TransformPlanExec :: try_new ( plan, vec ! [ Arc :: clone( rule) ] ) ?;
125121 if transformer. plans_to_transform ( ) > 0 {
126122 Ok ( Arc :: new ( transformer) )
127123 } else {
0 commit comments