Transforms all Column expressions in a sort expression into the actual expression from aggregation or projection if found. This is required because if an ORDER BY expression is present in an Aggregate or Select, it is replaced with a Column expression (e.g., "sum(catalog_returns.cr_net_loss)"). We need to transform it back to the actual expression, such as sum("catalog_returns"."cr_net_loss").
(
mut sort_expr: SortExpr,
agg: Option<&Aggregate>,
input: &LogicalPlan,
)
| 304 | /// with a Column expression (e.g., "sum(catalog_returns.cr_net_loss)"). We need to transform it back to |
| 305 | /// the actual expression, such as sum("catalog_returns"."cr_net_loss"). |
| 306 | pub(crate) fn unproject_sort_expr( |
| 307 | mut sort_expr: SortExpr, |
| 308 | agg: Option<&Aggregate>, |
| 309 | input: &LogicalPlan, |
| 310 | ) -> Result<SortExpr> { |
| 311 | sort_expr.expr = sort_expr |
| 312 | .expr |
| 313 | .transform(|sub_expr| { |
| 314 | match sub_expr { |
| 315 | // Remove alias if present, because ORDER BY cannot use aliases |
| 316 | Expr::Alias(alias) => Ok(Transformed::yes(*alias.expr)), |
| 317 | Expr::Column(col) => { |
| 318 | if col.relation.is_some() { |
| 319 | return Ok(Transformed::no(Expr::Column(col))); |
| 320 | } |
| 321 | |
| 322 | // In case of aggregation there could be columns containing aggregation functions we need to unproject |
| 323 | if let Some(agg) = agg |
| 324 | && agg.schema.is_column_from_schema(&col) |
| 325 | { |
| 326 | return Ok(Transformed::yes(unproject_agg_exprs( |
| 327 | Expr::Column(col), |
| 328 | agg, |
| 329 | None, |
| 330 | )?)); |
| 331 | } |
| 332 | |
| 333 | // If SELECT and ORDER BY contain the same expression with a scalar function, the ORDER BY expression will |
| 334 | // be replaced by a Column expression (e.g., "substr(customer.c_last_name, Int64(0), Int64(5))"), and we need |
| 335 | // to transform it back to the actual expression. |
| 336 | if let LogicalPlan::Projection(Projection { expr, schema, .. }) = |
| 337 | input |
| 338 | && let Ok(idx) = schema.index_of_column(&col) |
| 339 | && let Some(Expr::ScalarFunction(scalar_fn)) = expr.get(idx) |
| 340 | { |
| 341 | return Ok(Transformed::yes(Expr::ScalarFunction( |
| 342 | scalar_fn.clone(), |
| 343 | ))); |
| 344 | } |
| 345 | |
| 346 | Ok(Transformed::no(Expr::Column(col))) |
| 347 | } |
| 348 | _ => Ok(Transformed::no(sub_expr)), |
| 349 | } |
| 350 | }) |
| 351 | .map(|e| e.data)?; |
| 352 | Ok(sort_expr) |
| 353 | } |
| 354 | |
| 355 | /// Iterates through the children of a [LogicalPlan] to find a TableScan node before encountering |
| 356 | /// a Projection or any unexpected node that indicates the presence of a Projection (SELECT) in the plan. |
no test coverage detected
searching dependent graphs…