Closed peter-toth closed 2 days ago
This PR:
- Gets rid of
map_until_stop_and_collect
macro
that's great
Adds the Container trait and blanket implementations for Box, Option, Vec, tuples, ...
Do we need that?
What about calling this trait TreeNode or GraphNode and implementing it for our types only?
Adds the Container trait and blanket implementations for Box, Option, Vec, tuples, ...
Do we need that?
What about calling this trait TreeNode or GraphNode and implementing it for our types only?
Yes, we do. We already have the TreeNode
trait with a well defined API. It has TreeNode::apply_children()
/ TreeNode::map_children()
to let the tree implementations define how to visit/map the children of a node.
This new Container
trait with the above mentioned blankets just make the implementation of that apply_children()
/ map_children()
of logical plan trees (Expr
and LogicalPlan
) simpler.
We can actually move Container
and its blanket implementations to datafusion::expr
if that's cleaner.
cc @alamb, @berkaysynnada
~Let me check a few more things before we merge this PR. There might be a way to make this even simpler.~
NVM.
Thanks for the review @alamb , @berkaysynnada , @findepi!
Which issue does this PR close?
Part of https://github.com/apache/datafusion/issues/8913.
Rationale for this change
The current implementation of
LogicalPlan:apply_children()
,LogicalPlan::map_children()
,LogicalPlan::apply_expressions()
,LogicalPlan::map_expressions()
,Expr::apply_children()
andExpr::map_children()
are confusing due themap_until_stop_and_collect
macro. I think we can introduce a trait that can contain arbitrary sibling elements that functions can be applied on and mapped:As example for the new trait usage, this is how
Expr::map_children()
handledExpr::Case
before this PR:and this is how it is handled with this PR:
Please see the type of the
Case
struct fields in comments. Let's focus onwhen_then_expr: Vec<(Box<Expr>, Box<Expr>)>
first. The composable nature ofTreeNodeContainer
and the blanket implementation we provide forBox
, 2-tuple andVec
makes it possible to just callwhen_then_expr. map_elements(f)
to map all the expressions inwhen_then_expr
. But we can go further and replace themap_until_stop_and_collect
macro to deal with all 3 fields ofCase
. We can put them into a 3-tuple and can call.map_elements()
as we have blanket implementation for 3-tuple as well. (Note that we can't useVec
for this as the type of the 3 fields differ.)What changes are included in this PR?
This PR:
map_until_stop_and_collect
macro and manytransform
andrewrite
helper methods.TreeNodeContainer
trait and blanket implementations forBox
,Option
,Vec
, tuples, ...TreeNodeContainer
implementation forExpr
andLogicalPlan
.apply...
andmap...
methods.Are these changes tested?
Yes, with exitsing UTs.
Are there any user-facing changes?
No.