Skip to content

Commit e6cac7f

Browse files
alambfindepi
authored andcommitted
Consolidate Filter::remove_aliases into Expr::unalias_nested (apache#11001)
* Consolidate Expr::unalias_nested * fix doc test * Clarify unreachable code * Use transform_down_up to handle recursion
1 parent cc50fe6 commit e6cac7f

File tree

4 files changed

+42
-51
lines changed

4 files changed

+42
-51
lines changed

datafusion/expr/src/expr.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,32 +1198,53 @@ impl Expr {
11981198
}
11991199
}
12001200

1201-
/// Recursively potentially multiple aliases from an expression.
1201+
/// Recursively removed potentially multiple aliases from an expression.
12021202
///
1203-
/// If the expression is not an alias, the expression is returned unchanged.
1204-
/// This method removes directly nested aliases, but not other nested
1205-
/// aliases.
1203+
/// This method removes nested aliases and returns [`Transformed`]
1204+
/// to signal if the expression was changed.
12061205
///
12071206
/// # Example
12081207
/// ```
12091208
/// # use datafusion_expr::col;
12101209
/// // `foo as "bar"` is unaliased to `foo`
12111210
/// let expr = col("foo").alias("bar");
1212-
/// assert_eq!(expr.unalias_nested(), col("foo"));
1211+
/// assert_eq!(expr.unalias_nested().data, col("foo"));
12131212
///
1214-
/// // `foo as "bar" + baz` is not unaliased
1213+
/// // `foo as "bar" + baz` is unaliased
12151214
/// let expr = col("foo").alias("bar") + col("baz");
1216-
/// assert_eq!(expr.clone().unalias_nested(), expr);
1215+
/// assert_eq!(expr.clone().unalias_nested().data, col("foo") + col("baz"));
12171216
///
12181217
/// // `foo as "bar" as "baz" is unalaised to foo
12191218
/// let expr = col("foo").alias("bar").alias("baz");
1220-
/// assert_eq!(expr.unalias_nested(), col("foo"));
1219+
/// assert_eq!(expr.unalias_nested().data, col("foo"));
12211220
/// ```
1222-
pub fn unalias_nested(self) -> Expr {
1223-
match self {
1224-
Expr::Alias(alias) => alias.expr.unalias_nested(),
1225-
_ => self,
1226-
}
1221+
pub fn unalias_nested(self) -> Transformed<Expr> {
1222+
self.transform_down_up(
1223+
|expr| {
1224+
// f_down: skip subqueries. Check in f_down to avoid recursing into them
1225+
let recursion = if matches!(
1226+
expr,
1227+
Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_)
1228+
) {
1229+
// subqueries could contain aliases so don't recurse into those
1230+
TreeNodeRecursion::Jump
1231+
} else {
1232+
TreeNodeRecursion::Continue
1233+
};
1234+
Ok(Transformed::new(expr, false, recursion))
1235+
},
1236+
|expr| {
1237+
// f_up: unalias on up so we can remove nested aliases like
1238+
// `(x as foo) as bar`
1239+
if let Expr::Alias(Alias { expr, .. }) = expr {
1240+
Ok(Transformed::yes(*expr))
1241+
} else {
1242+
Ok(Transformed::no(expr))
1243+
}
1244+
},
1245+
)
1246+
// unreachable code: internal closure doesn't return err
1247+
.unwrap()
12271248
}
12281249

12291250
/// Return `self IN <list>` if `negated` is false, otherwise

datafusion/expr/src/logical_plan/plan.rs

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -878,8 +878,7 @@ impl LogicalPlan {
878878
}
879879
LogicalPlan::Filter { .. } => {
880880
assert_eq!(1, expr.len());
881-
let predicate = expr.pop().unwrap();
882-
let predicate = Filter::remove_aliases(predicate)?.data;
881+
let predicate = expr.pop().unwrap().unalias_nested().data;
883882

884883
Filter::try_new(predicate, Arc::new(inputs.swap_remove(0)))
885884
.map(LogicalPlan::Filter)
@@ -2209,38 +2208,6 @@ impl Filter {
22092208
}
22102209
false
22112210
}
2212-
2213-
/// Remove aliases from a predicate for use in a `Filter`
2214-
///
2215-
/// filter predicates should not contain aliased expressions so we remove
2216-
/// any aliases.
2217-
///
2218-
/// before this logic was added we would have aliases within filters such as
2219-
/// for benchmark q6:
2220-
///
2221-
/// ```sql
2222-
/// lineitem.l_shipdate >= Date32(\"8766\")
2223-
/// AND lineitem.l_shipdate < Date32(\"9131\")
2224-
/// AND CAST(lineitem.l_discount AS Decimal128(30, 15)) AS lineitem.l_discount >=
2225-
/// Decimal128(Some(49999999999999),30,15)
2226-
/// AND CAST(lineitem.l_discount AS Decimal128(30, 15)) AS lineitem.l_discount <=
2227-
/// Decimal128(Some(69999999999999),30,15)
2228-
/// AND lineitem.l_quantity < Decimal128(Some(2400),15,2)
2229-
/// ```
2230-
pub fn remove_aliases(predicate: Expr) -> Result<Transformed<Expr>> {
2231-
predicate.transform_down(|expr| {
2232-
match expr {
2233-
Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_) => {
2234-
// subqueries could contain aliases so we don't recurse into those
2235-
Ok(Transformed::new(expr, false, TreeNodeRecursion::Jump))
2236-
}
2237-
Expr::Alias(Alias { expr, .. }) => {
2238-
Ok(Transformed::new(*expr, true, TreeNodeRecursion::Jump))
2239-
}
2240-
_ => Ok(Transformed::no(expr)),
2241-
}
2242-
})
2243-
}
22442211
}
22452212

22462213
/// Window its input based on a set of window spec and window function (e.g. SUM or RANK)

datafusion/optimizer/src/common_subexpr_eliminate.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,12 @@ impl CommonSubexprEliminate {
345345
self.try_unary_plan(expr, input, config)?
346346
.transform_data(|(mut new_expr, new_input)| {
347347
assert_eq!(new_expr.len(), 1); // passed in vec![predicate]
348-
let new_predicate = new_expr.pop().unwrap();
349-
Ok(Filter::remove_aliases(new_predicate)?
350-
.update_data(|new_predicate| (new_predicate, new_input)))
348+
let new_predicate = new_expr
349+
.pop()
350+
.unwrap()
351+
.unalias_nested()
352+
.update_data(|new_predicate| (new_predicate, new_input));
353+
Ok(new_predicate)
351354
})?
352355
.map_data(|(new_predicate, new_input)| {
353356
Filter::try_new(new_predicate, Arc::new(new_input))

datafusion/optimizer/src/optimize_projections/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ fn rewrite_expr(expr: Expr, input: &Projection) -> Result<Transformed<Expr>> {
600600
// * the current column is an expression "f"
601601
//
602602
// return the expression `d + e` (not `d + e` as f)
603-
let input_expr = input.expr[idx].clone().unalias_nested();
603+
let input_expr = input.expr[idx].clone().unalias_nested().data;
604604
Ok(Transformed::yes(input_expr))
605605
}
606606
// Unsupported type for consecutive projection merge analysis.

0 commit comments

Comments
 (0)