use crate::LogicalPlan;
use datafusion_common::tree_node::{TreeNode, TreeNodeVisitor, VisitRecursion};
use datafusion_common::{handle_tree_recursion, Result};
impl TreeNode for LogicalPlan {
fn apply<F: FnMut(&Self) -> Result<VisitRecursion>>(
&self,
op: &mut F,
) -> Result<VisitRecursion> {
handle_tree_recursion!(op(self)?);
self.apply_subqueries(op)?;
self.apply_children(&mut |node| node.apply(op))
}
fn visit<V: TreeNodeVisitor<N = Self>>(
&self,
visitor: &mut V,
) -> Result<VisitRecursion> {
handle_tree_recursion!(visitor.pre_visit(self)?);
self.visit_subqueries(visitor)?;
handle_tree_recursion!(self.apply_children(&mut |node| node.visit(visitor))?);
visitor.post_visit(self)
}
fn apply_children<F: FnMut(&Self) -> Result<VisitRecursion>>(
&self,
op: &mut F,
) -> Result<VisitRecursion> {
for child in self.inputs() {
handle_tree_recursion!(op(child)?)
}
Ok(VisitRecursion::Continue)
}
fn map_children<F>(self, transform: F) -> Result<Self>
where
F: FnMut(Self) -> Result<Self>,
{
let old_children = self.inputs();
let new_children = old_children
.iter()
.map(|&c| c.clone())
.map(transform)
.collect::<Result<Vec<_>>>()?;
if old_children
.into_iter()
.zip(new_children.iter())
.any(|(c1, c2)| c1 != c2)
{
self.with_new_exprs(self.expressions(), new_children)
} else {
Ok(self)
}
}
}