-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Add rewrite_expr
convenience method for rewriting Expr
s
#5092
Conversation
/// comments on `Expr::rewrite` for details on its use | ||
/// invoked recursively on all nodes of an expression tree. | ||
/// | ||
/// Performs a depth first walk of an expression and its children |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved so it is more visible in rustdocs
@@ -429,27 +433,14 @@ pub fn normalize_col_with_schemas( | |||
schemas: &[&Arc<DFSchema>], | |||
using_columns: &[HashSet<Column>], | |||
) -> Result<Expr> { | |||
struct ColumnNormalizer<'a> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is a pretty good example the boilerplate that can be avoided by using rewrite_expr
rather than ExprRewriter
(rust generates a closure that captures schemas
and using_columns
) rather than having to do it explicitly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really like this example.👍
I wonder if @jackwener / @HaoYang670 have any thoughts on this approach? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really very like this PR. After merge it, we can more convenient to use rewrite_expr
.
Thanks @alamb .
cc @mingmwang , how do you think it?
/// | ||
/// assert_eq!(rewritten, col("a") + lit(42)); | ||
/// ``` | ||
pub fn rewrite_expr<F>(expr: Expr, f: F) -> Result<Expr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The real change in this PR is to add this function.
Really sorry for the late. I just came back from the Spring Festival. I will review this tomorrow, thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @alamb. I learned much from your PR.
where | ||
F: FnMut(Expr) -> Result<Expr>, | ||
{ | ||
fn mutate(&mut self, expr: Expr) -> Result<Expr> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we let ExprRewriter::mutate
return Result<Option<E>>
in the future, just like what we've done for LogicalPlan::try_optimize
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is an interesting idea. What usecase do you have in mind?
Since mutate
takes the expr by ownership (rather than by reference), I think returning expr
would be the same as not changing the original expr
(perhaps the same as returning None
?)
However, I do wonder what actually happens when rewriting Boxed exprs 🤔 maybe they are still copied
@@ -519,6 +495,49 @@ pub fn unnormalize_cols(exprs: impl IntoIterator<Item = Expr>) -> Vec<Expr> { | |||
exprs.into_iter().map(unnormalize_col).collect() | |||
} | |||
|
|||
struct RewriterAdapter<F> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is better to add some comments for RewriterAdapter
, but this is not a blocker.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, added in 34a725c
…sion into alamb/rewrite_adapter
Co-authored-by: Remzi Yang <59198230+HaoYang670@users.noreply.github.com>
Thank you for the reviews @HaoYang670 and @jackwener |
Benchmark runs are scheduled for baseline = 67b1da8 and contender = 51d5840. 51d5840 is a master commit associated with this PR. Results will be available as each benchmark for each run completes. |
Note: this may look like a large change, but it is mostly comments.
Which issue does this PR close?
related to #4854
Rationale for this change
There are some rewrites (like constant propagation) that require the full generality of
ExprRewriter
that saves state on a previst on down and then rewrite while walking back up. However, most rewrites simply callmutate
.Now you have to define a Visitor struct to pass arguments down the tree. Letting rust do the work for you via a closure makes for less code
What changes are included in this PR?
Changes:
rewrite_expr
convenience function (likeinspect_expr_pre
) for the common case-fold-searchExprRewriter
to demonstrate how to use itIf this PR is approved, I'll spend some time porting over other uses of
ExprRewriter
sAre these changes tested?
Yes, both a new doc tests and existing coverage
Are there any user-facing changes?
Developers can hopefully write lest code