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;
}