-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Consolidate Filter::remove_aliases
into Expr::unalias_nested
#11001
Changes from 9 commits
9340380
745b3cb
b07100d
72ee283
41ca96d
0ab5826
22e37ef
c16eb3c
66c4bed
2738ab1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1198,32 +1198,53 @@ impl Expr { | |
} | ||
} | ||
|
||
/// Recursively potentially multiple aliases from an expression. | ||
/// Recursively removed potentially multiple aliases from an expression. | ||
/// | ||
/// If the expression is not an alias, the expression is returned unchanged. | ||
/// This method removes directly nested aliases, but not other nested | ||
/// aliases. | ||
/// This method removes nested aliases and returns [`Transformed`] | ||
/// to signal if the expression was changed. | ||
/// | ||
/// # Example | ||
/// ``` | ||
/// # use datafusion_expr::col; | ||
/// // `foo as "bar"` is unaliased to `foo` | ||
/// let expr = col("foo").alias("bar"); | ||
/// assert_eq!(expr.unalias_nested(), col("foo")); | ||
/// assert_eq!(expr.unalias_nested().data, col("foo")); | ||
/// | ||
/// // `foo as "bar" + baz` is not unaliased | ||
/// // `foo as "bar" + baz` is unaliased | ||
/// let expr = col("foo").alias("bar") + col("baz"); | ||
/// assert_eq!(expr.clone().unalias_nested(), expr); | ||
/// assert_eq!(expr.clone().unalias_nested().data, col("foo") + col("baz")); | ||
/// | ||
/// // `foo as "bar" as "baz" is unalaised to foo | ||
/// let expr = col("foo").alias("bar").alias("baz"); | ||
/// assert_eq!(expr.unalias_nested(), col("foo")); | ||
/// assert_eq!(expr.unalias_nested().data, col("foo")); | ||
/// ``` | ||
pub fn unalias_nested(self) -> Expr { | ||
match self { | ||
Expr::Alias(alias) => alias.expr.unalias_nested(), | ||
_ => self, | ||
} | ||
pub fn unalias_nested(self) -> Transformed<Expr> { | ||
self.transform_down_up( | ||
|expr| { | ||
// f_down: skip subqueries. Check in f_down to avoid recursing into them | ||
let recursion = if matches!( | ||
expr, | ||
Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks @alamb
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I don't think aliases can be set for such plans via SQL -- I think they are (or were) sometimes set programatically (e.g. via some other optimizer pass or rewrite) |
||
) { | ||
// subqueries could contain aliases so don't recurse into those | ||
TreeNodeRecursion::Jump | ||
} else { | ||
TreeNodeRecursion::Continue | ||
}; | ||
Ok(Transformed::new(expr, false, recursion)) | ||
}, | ||
|expr| { | ||
// f_up: unalias on up so we can remove nested aliases like | ||
// `(x as foo) as bar` | ||
if let Expr::Alias(Alias { expr, .. }) = expr { | ||
Ok(Transformed::yes(*expr)) | ||
} else { | ||
Ok(Transformed::no(expr)) | ||
} | ||
}, | ||
) | ||
// unreachable code: internal closure doesn't return err | ||
.unwrap() | ||
} | ||
|
||
/// Return `self IN <list>` if `negated` is false, otherwise | ||
|
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.
this is an API change (it returns Transformed rather than just Expr) but I think that makes more sense