This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 65e281a85b Improve UserDefinedLogicalNodeCore::from_template API to 
return Result (#10597)
65e281a85b is described below

commit 65e281a85bb656a0dd5eb4c213920b0d96620f87
Author: 张林伟 <[email protected]>
AuthorDate: Wed May 22 05:52:23 2024 +0800

    Improve UserDefinedLogicalNodeCore::from_template API to return Result 
(#10597)
    
    Co-authored-by: Andrew Lamb <[email protected]>
---
 datafusion/core/src/physical_planner.rs            |  6 ++++-
 .../core/tests/user_defined/user_defined_plan.rs   | 14 ++++++----
 datafusion/expr/src/logical_plan/extension.rs      | 30 ++++++++++++----------
 datafusion/optimizer/src/analyzer/subquery.rs      | 10 +++++---
 .../optimizer/src/optimize_projections/mod.rs      | 30 ++++++++++++++--------
 datafusion/optimizer/src/push_down_filter.rs       | 12 ++++++---
 datafusion/optimizer/src/test/user_defined.rs      | 12 ++++++---
 .../proto/tests/cases/roundtrip_logical_plan.rs    | 14 ++++++----
 8 files changed, 82 insertions(+), 46 deletions(-)

diff --git a/datafusion/core/src/physical_planner.rs 
b/datafusion/core/src/physical_planner.rs
index 597a03a52f..090b1d59d9 100644
--- a/datafusion/core/src/physical_planner.rs
+++ b/datafusion/core/src/physical_planner.rs
@@ -2819,7 +2819,11 @@ mod tests {
             write!(f, "NoOp")
         }
 
-        fn from_template(&self, _exprs: &[Expr], _inputs: &[LogicalPlan]) -> 
Self {
+        fn with_exprs_and_inputs(
+            &self,
+            _exprs: Vec<Expr>,
+            _inputs: Vec<LogicalPlan>,
+        ) -> Result<Self> {
             unimplemented!("NoOp");
         }
     }
diff --git a/datafusion/core/tests/user_defined/user_defined_plan.rs 
b/datafusion/core/tests/user_defined/user_defined_plan.rs
index 2c12e108bb..54dcffe35f 100644
--- a/datafusion/core/tests/user_defined/user_defined_plan.rs
+++ b/datafusion/core/tests/user_defined/user_defined_plan.rs
@@ -365,14 +365,18 @@ impl UserDefinedLogicalNodeCore for TopKPlanNode {
         write!(f, "TopK: k={}", self.k)
     }
 
-    fn from_template(&self, exprs: &[Expr], inputs: &[LogicalPlan]) -> Self {
+    fn with_exprs_and_inputs(
+        &self,
+        mut exprs: Vec<Expr>,
+        mut inputs: Vec<LogicalPlan>,
+    ) -> Result<Self> {
         assert_eq!(inputs.len(), 1, "input size inconsistent");
         assert_eq!(exprs.len(), 1, "expression size inconsistent");
-        Self {
+        Ok(Self {
             k: self.k,
-            input: inputs[0].clone(),
-            expr: exprs[0].clone(),
-        }
+            input: inputs.swap_remove(0),
+            expr: exprs.swap_remove(0),
+        })
     }
 }
 
diff --git a/datafusion/expr/src/logical_plan/extension.rs 
b/datafusion/expr/src/logical_plan/extension.rs
index 918e290ee4..2f581c1928 100644
--- a/datafusion/expr/src/logical_plan/extension.rs
+++ b/datafusion/expr/src/logical_plan/extension.rs
@@ -215,7 +215,7 @@ impl Eq for dyn UserDefinedLogicalNode {}
 /// [user_defined_plan.rs](../../tests/user_defined_plan.rs) for an
 /// example of how to use this extension API.
 pub trait UserDefinedLogicalNodeCore:
-    fmt::Debug + Eq + Hash + Send + Sync + 'static
+    fmt::Debug + Eq + Hash + Sized + Send + Sync + 'static
 {
     /// Return the plan's name.
     fn name(&self) -> &str;
@@ -248,23 +248,27 @@ pub trait UserDefinedLogicalNodeCore:
     /// For example: `TopK: k=10`
     fn fmt_for_explain(&self, f: &mut fmt::Formatter) -> fmt::Result;
 
-    /// Create a new `ExtensionPlanNode` with the specified children
+    #[deprecated(since = "39.0.0", note = "use with_exprs_and_inputs instead")]
+    #[allow(clippy::wrong_self_convention)]
+    fn from_template(&self, exprs: &[Expr], inputs: &[LogicalPlan]) -> Self {
+        self.with_exprs_and_inputs(exprs.to_vec(), inputs.to_vec())
+            .unwrap()
+    }
+
+    /// Create a new `UserDefinedLogicalNode` with the specified children
     /// and expressions. This function is used during optimization
     /// when the plan is being rewritten and a new instance of the
-    /// `ExtensionPlanNode` must be created.
+    /// `UserDefinedLogicalNode` must be created.
     ///
     /// Note that exprs and inputs are in the same order as the result
     /// of self.inputs and self.exprs.
     ///
-    /// So, `self.from_template(exprs, ..).expressions() == exprs
-    //
-    // TODO(clippy): This should probably be renamed to use a `with_*` prefix. 
Something
-    // like `with_template`, or `with_exprs_and_inputs`.
-    //
-    // Also, I think `ExtensionPlanNode` has been renamed to 
`UserDefinedLogicalNode`
-    // but the doc comments have not been updated.
-    #[allow(clippy::wrong_self_convention)]
-    fn from_template(&self, exprs: &[Expr], inputs: &[LogicalPlan]) -> Self;
+    /// So, `self.with_exprs_and_inputs(exprs, ..).expressions() == exprs
+    fn with_exprs_and_inputs(
+        &self,
+        exprs: Vec<Expr>,
+        inputs: Vec<LogicalPlan>,
+    ) -> Result<Self>;
 
     /// Returns the necessary input columns for this node required to compute
     /// the columns in the output schema
@@ -321,7 +325,7 @@ impl<T: UserDefinedLogicalNodeCore> UserDefinedLogicalNode 
for T {
         exprs: Vec<Expr>,
         inputs: Vec<LogicalPlan>,
     ) -> Result<Arc<dyn UserDefinedLogicalNode>> {
-        Ok(Arc::new(self.from_template(&exprs, &inputs)))
+        Ok(Arc::new(self.with_exprs_and_inputs(exprs, inputs)?))
     }
 
     fn necessary_children_exprs(
diff --git a/datafusion/optimizer/src/analyzer/subquery.rs 
b/datafusion/optimizer/src/analyzer/subquery.rs
index b46516017a..444ee94c42 100644
--- a/datafusion/optimizer/src/analyzer/subquery.rs
+++ b/datafusion/optimizer/src/analyzer/subquery.rs
@@ -370,10 +370,14 @@ mod test {
             write!(f, "MockUserDefinedLogicalPlan")
         }
 
-        fn from_template(&self, _exprs: &[Expr], _inputs: &[LogicalPlan]) -> 
Self {
-            Self {
+        fn with_exprs_and_inputs(
+            &self,
+            _exprs: Vec<Expr>,
+            _inputs: Vec<LogicalPlan>,
+        ) -> Result<Self> {
+            Ok(Self {
                 empty_schema: self.empty_schema.clone(),
-            }
+            })
         }
     }
 
diff --git a/datafusion/optimizer/src/optimize_projections/mod.rs 
b/datafusion/optimizer/src/optimize_projections/mod.rs
index a13ae4bd41..49b52aa53a 100644
--- a/datafusion/optimizer/src/optimize_projections/mod.rs
+++ b/datafusion/optimizer/src/optimize_projections/mod.rs
@@ -870,12 +870,16 @@ mod tests {
             write!(f, "NoOpUserDefined")
         }
 
-        fn from_template(&self, exprs: &[Expr], inputs: &[LogicalPlan]) -> 
Self {
-            Self {
-                exprs: exprs.to_vec(),
-                input: Arc::new(inputs[0].clone()),
+        fn with_exprs_and_inputs(
+            &self,
+            exprs: Vec<Expr>,
+            mut inputs: Vec<LogicalPlan>,
+        ) -> Result<Self> {
+            Ok(Self {
+                exprs,
+                input: Arc::new(inputs.swap_remove(0)),
                 schema: self.schema.clone(),
-            }
+            })
         }
 
         fn necessary_children_exprs(
@@ -932,14 +936,18 @@ mod tests {
             write!(f, "UserDefinedCrossJoin")
         }
 
-        fn from_template(&self, exprs: &[Expr], inputs: &[LogicalPlan]) -> 
Self {
+        fn with_exprs_and_inputs(
+            &self,
+            exprs: Vec<Expr>,
+            mut inputs: Vec<LogicalPlan>,
+        ) -> Result<Self> {
             assert_eq!(inputs.len(), 2);
-            Self {
-                exprs: exprs.to_vec(),
-                left_child: Arc::new(inputs[0].clone()),
-                right_child: Arc::new(inputs[1].clone()),
+            Ok(Self {
+                exprs,
+                left_child: Arc::new(inputs.remove(0)),
+                right_child: Arc::new(inputs.remove(0)),
                 schema: self.schema.clone(),
-            }
+            })
         }
 
         fn necessary_children_exprs(
diff --git a/datafusion/optimizer/src/push_down_filter.rs 
b/datafusion/optimizer/src/push_down_filter.rs
index ad9294dd6a..e56bfd051f 100644
--- a/datafusion/optimizer/src/push_down_filter.rs
+++ b/datafusion/optimizer/src/push_down_filter.rs
@@ -1364,11 +1364,15 @@ mod tests {
             write!(f, "NoopPlan")
         }
 
-        fn from_template(&self, _exprs: &[Expr], inputs: &[LogicalPlan]) -> 
Self {
-            Self {
-                input: inputs.to_vec(),
+        fn with_exprs_and_inputs(
+            &self,
+            _exprs: Vec<Expr>,
+            inputs: Vec<LogicalPlan>,
+        ) -> Result<Self> {
+            Ok(Self {
+                input: inputs,
                 schema: Arc::clone(&self.schema),
-            }
+            })
         }
     }
 
diff --git a/datafusion/optimizer/src/test/user_defined.rs 
b/datafusion/optimizer/src/test/user_defined.rs
index c60342fa00..d040fa2bae 100644
--- a/datafusion/optimizer/src/test/user_defined.rs
+++ b/datafusion/optimizer/src/test/user_defined.rs
@@ -65,11 +65,15 @@ impl UserDefinedLogicalNodeCore for TestUserDefinedPlanNode 
{
         write!(f, "TestUserDefined")
     }
 
-    fn from_template(&self, exprs: &[Expr], inputs: &[LogicalPlan]) -> Self {
+    fn with_exprs_and_inputs(
+        &self,
+        exprs: Vec<Expr>,
+        mut inputs: Vec<LogicalPlan>,
+    ) -> datafusion_common::Result<Self> {
         assert_eq!(inputs.len(), 1, "input size inconsistent");
         assert_eq!(exprs.len(), 0, "expression size inconsistent");
-        Self {
-            input: inputs[0].clone(),
-        }
+        Ok(Self {
+            input: inputs.swap_remove(0),
+        })
     }
 }
diff --git a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs 
b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs
index 472d64905b..6e819ef5bf 100644
--- a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs
+++ b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs
@@ -728,14 +728,18 @@ impl UserDefinedLogicalNodeCore for TopKPlanNode {
         write!(f, "TopK: k={}", self.k)
     }
 
-    fn from_template(&self, exprs: &[Expr], inputs: &[LogicalPlan]) -> Self {
+    fn with_exprs_and_inputs(
+        &self,
+        mut exprs: Vec<Expr>,
+        mut inputs: Vec<LogicalPlan>,
+    ) -> Result<Self> {
         assert_eq!(inputs.len(), 1, "input size inconsistent");
         assert_eq!(exprs.len(), 1, "expression size inconsistent");
-        Self {
+        Ok(Self {
             k: self.k,
-            input: inputs[0].clone(),
-            expr: exprs[0].clone(),
-        }
+            input: inputs.swap_remove(0),
+            expr: exprs.swap_remove(0),
+        })
     }
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to