pub trait UserDefinedLogicalNode: Debug + Send + Sync {
    // Required methods
    fn as_any(&self) -> &dyn Any;
    fn name(&self) -> &str;
    fn inputs(&self) -> Vec<&LogicalPlan>;
    fn schema(&self) -> &DFSchemaRef;
    fn expressions(&self) -> Vec<Expr>;
    fn fmt_for_explain(&self, f: &mut Formatter<'_>) -> Result;
    fn from_template(
        &self,
        exprs: &[Expr],
        inputs: &[LogicalPlan]
    ) -> Arc<dyn UserDefinedLogicalNode>;
    fn dyn_hash(&self, state: &mut dyn Hasher);
    fn dyn_eq(&self, other: &dyn UserDefinedLogicalNode) -> bool;

    // Provided method
    fn prevent_predicate_push_down_columns(&self) -> HashSet<String> { ... }
}
Expand description

This defines the interface for LogicalPlan nodes that can be used to extend DataFusion with custom relational operators.

The UserDefinedLogicalNodeCore trait is the recommended way to implement this trait and avoids having implementing some required boiler plate code.

Required Methods§

source

fn as_any(&self) -> &dyn Any

Return a reference to self as Any, to support dynamic downcasting

Typically this will look like:


  // canonical boiler plate
  fn as_any(&self) -> &dyn Any {
     self
  }
source

fn name(&self) -> &str

Return the plan’s name.

source

fn inputs(&self) -> Vec<&LogicalPlan>

Return the logical plan’s inputs.

source

fn schema(&self) -> &DFSchemaRef

Return the output schema of this logical plan node.

source

fn expressions(&self) -> Vec<Expr>

Returns all expressions in the current logical plan node. This should not include expressions of any inputs (aka non-recursively). These expressions are used for optimizer passes and rewrites.

source

fn fmt_for_explain(&self, f: &mut Formatter<'_>) -> Result

Write a single line, human readable string to f for use in explain plan.

For example: TopK: k=10

source

fn from_template( &self, exprs: &[Expr], inputs: &[LogicalPlan] ) -> Arc<dyn UserDefinedLogicalNode>

Create a new ExtensionPlanNode 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.

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

source

fn dyn_hash(&self, state: &mut dyn Hasher)

Update the hash state with this node requirements from Hash.

Note: consider using UserDefinedLogicalNodeCore instead of UserDefinedLogicalNode directly.

This method is required to support hashing LogicalPlans. 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 {
// ...
  // 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.

source

fn dyn_eq(&self, other: &dyn UserDefinedLogicalNode) -> bool

Compare other, respecting requirements from std::cmp::Eq.

Note: consider using UserDefinedLogicalNodeCore instead of UserDefinedLogicalNode directly.

When other has an another type than self, then the values are not equal.

This method is required to support Eq on LogicalPlans. To implement it, typically the type implementing UserDefinedLogicalNode typically implements Eq and then the following boiler plate is used:

Example:
// User defined node that derives Eq
#[derive(Hash, Debug, PartialEq, Eq)]
struct MyNode {
  val: u64
}

// impl UserDefinedLogicalNode {
// ...
  // 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.

Provided Methods§

source

fn prevent_predicate_push_down_columns(&self) -> HashSet<String>

A list of output columns (e.g. the names of columns in self.schema()) for which predicates can not be pushed below this node without changing the output.

By default, this returns all columns and thus prevents any predicates from being pushed below this node.

Trait Implementations§

source§

impl Hash for dyn UserDefinedLogicalNode

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
source§

impl PartialEq<dyn UserDefinedLogicalNode> for dyn UserDefinedLogicalNode

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Eq for dyn UserDefinedLogicalNode

Implementors§

source§

impl<T: UserDefinedLogicalNodeCore> UserDefinedLogicalNode for T

Automatically derive UserDefinedLogicalNode to UserDefinedLogicalNode to avoid boiler plate for implementing as_any, Hash and PartialEq