use crate::LogicalPlan;
use datafusion_common::tree_node::{TreeNodeVisitor, VisitRecursion};
use datafusion_common::{tree_node::TreeNode, Result};
impl TreeNode for LogicalPlan {
fn apply<F>(&self, op: &mut F) -> Result<VisitRecursion>
where
F: FnMut(&Self) -> Result<VisitRecursion>,
{
match op(self)? {
VisitRecursion::Continue => {}
VisitRecursion::Skip => return Ok(VisitRecursion::Continue),
VisitRecursion::Stop => return Ok(VisitRecursion::Stop),
};
self.apply_subqueries(op)?;
self.apply_children(&mut |node| node.apply(op))
}
fn visit<V: TreeNodeVisitor<N = Self>>(
&self,
visitor: &mut V,
) -> Result<VisitRecursion> {
match visitor.pre_visit(self)? {
VisitRecursion::Continue => {}
VisitRecursion::Skip => return Ok(VisitRecursion::Continue),
VisitRecursion::Stop => return Ok(VisitRecursion::Stop),
};
self.visit_subqueries(visitor)?;
match self.apply_children(&mut |node| node.visit(visitor))? {
VisitRecursion::Continue => {}
VisitRecursion::Skip => return Ok(VisitRecursion::Continue),
VisitRecursion::Stop => return Ok(VisitRecursion::Stop),
}
visitor.post_visit(self)
}
fn apply_children<F>(&self, op: &mut F) -> Result<VisitRecursion>
where
F: FnMut(&Self) -> Result<VisitRecursion>,
{
for child in self.inputs() {
match op(child)? {
VisitRecursion::Continue => {}
VisitRecursion::Skip => return Ok(VisitRecursion::Continue),
VisitRecursion::Stop => return Ok(VisitRecursion::Stop),
}
}
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
.iter()
.zip(new_children.iter())
.any(|(c1, c2)| c1 != &c2)
{
self.with_new_inputs(new_children.as_slice())
} else {
Ok(self)
}
}
}