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/arrow-datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 0ead640e8 Minor: Improve docs for UserDefinedLogicalNode `dyn_eq` and 
`dyn_hash` (#5515)
0ead640e8 is described below

commit 0ead640e887c19607a371c22a183dc91a55baf45
Author: Andrew Lamb <[email protected]>
AuthorDate: Wed Mar 8 21:20:54 2023 +0100

    Minor: Improve docs for UserDefinedLogicalNode `dyn_eq` and `dyn_hash` 
(#5515)
---
 datafusion/common/src/config.rs               |  2 +-
 datafusion/expr/src/logical_plan/extension.rs | 80 ++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/datafusion/common/src/config.rs b/datafusion/common/src/config.rs
index 4a71bce61..cab8d254a 100644
--- a/datafusion/common/src/config.rs
+++ b/datafusion/common/src/config.rs
@@ -684,7 +684,7 @@ trait Visit {
 ///
 ///
 /// [`Debug`]: std::fmt::Debug
-/// [`ExtensionsOptions`]: crate::config::ExtensionsOptions
+/// [`ExtensionsOptions`]: crate::config::ExtensionOptions
 #[macro_export]
 macro_rules! extensions_options {
     (
diff --git a/datafusion/expr/src/logical_plan/extension.rs 
b/datafusion/expr/src/logical_plan/extension.rs
index 5f147c217..1ad328319 100644
--- a/datafusion/expr/src/logical_plan/extension.rs
+++ b/datafusion/expr/src/logical_plan/extension.rs
@@ -29,6 +29,20 @@ use std::{any::Any, cmp::Eq, collections::HashSet, fmt, 
sync::Arc};
 /// example of how to use this extension API.
 pub trait UserDefinedLogicalNode: fmt::Debug + Send + Sync {
     /// Return a reference to self as Any, to support dynamic downcasting
+    ///
+    /// Typically this will look like:
+    ///
+    /// ```
+    /// # use std::any::Any;
+    /// # struct Dummy { }
+    ///
+    /// # impl Dummy {
+    ///   // canonical boiler plate
+    ///   fn as_any(&self) -> &dyn Any {
+    ///      self
+    ///   }
+    /// # }
+    /// ```
     fn as_any(&self) -> &dyn Any;
 
     /// Return the plan's name
@@ -82,12 +96,72 @@ pub trait UserDefinedLogicalNode: fmt::Debug + Send + Sync {
         inputs: &[LogicalPlan],
     ) -> Arc<dyn UserDefinedLogicalNode>;
 
-    /// Hashing respecting requirements from [std::hash::Hash].
+    /// Update the hash `state` with this node requirements from
+    /// [`Hash`].
+    ///
+    /// This method is required to support hashing [`LogicalPlan`]s.  To
+    /// implement it, typically the type implementing
+    /// [`UserDefinedLogicalNode`] typically implements [`Hash`] and
+    /// then the following boiler plate is used:
+    ///
+    /// # Example:
+    /// ```
+    /// // User defined node that derives Hash
+    /// #[derive(Hash, Debug, PartialEq, Eq)]
+    /// struct MyNode {
+    ///   val: u64
+    /// }
+    ///
+    /// // impl UserDefinedLogicalNode {
+    /// // ...
+    /// # impl MyNode {
+    ///   // Boiler plate to call the derived Hash impl
+    ///   fn dyn_hash(&self, state: &mut dyn std::hash::Hasher) {
+    ///     use std::hash::Hash;
+    ///     let mut s = state;
+    ///     self.hash(&mut s);
+    ///   }
+    /// // }
+    /// # }
+    /// ```
+    /// Note: [`UserDefinedLogicalNode`] is not constrained by [`Hash`]
+    /// directly because it must remain object safe.
     fn dyn_hash(&self, state: &mut dyn Hasher);
 
-    /// Comparison respecting requirements from [std::cmp::Eq].
+    /// Compare `other`, respecting requirements from [std::cmp::Eq].
+    ///
+    /// When `other` has an another type than `self`, then the values
+    /// are *not* equal.
+    ///
+    /// This method is required to support Eq on [`LogicalPlan`]s.  To
+    /// implement it, typically the type implementing
+    /// [`UserDefinedLogicalNode`] typically implements [`Eq`] and
+    /// then the following boiler plate is used:
+    ///
+    /// # Example:
+    /// ```
+    /// # use datafusion_expr::UserDefinedLogicalNode;
+    /// // User defined node that derives Eq
+    /// #[derive(Hash, Debug, PartialEq, Eq)]
+    /// struct MyNode {
+    ///   val: u64
+    /// }
     ///
-    /// When `other` has an another type than `self`, then the values are 
*not* equal.
+    /// // impl UserDefinedLogicalNode {
+    /// // ...
+    /// # impl MyNode {
+    ///   // Boiler plate to call the derived Eq impl
+    ///   fn dyn_eq(&self, other: &dyn UserDefinedLogicalNode) -> bool {
+    ///     match other.as_any().downcast_ref::<Self>() {
+    ///       Some(o) => self == o,
+    ///       None => false,
+    ///     }
+    ///   }
+    /// // }
+    /// # }
+    /// ```
+    /// Note: [`UserDefinedLogicalNode`] is not constrained by [`Eq`]
+    /// directly because it must remain object safe.
     fn dyn_eq(&self, other: &dyn UserDefinedLogicalNode) -> bool;
 }
 

Reply via email to