MCPcopy Create free account
hub / github.com/apache/datafusion / unproject_sort_expr

Function unproject_sort_expr

datafusion/sql/src/unparser/utils.rs:306–353  ·  view source on GitHub ↗

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,
)

Source from the content-addressed store, hash-verified

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").
306pub(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.

Callers 1

Calls 9

unproject_agg_exprsFunction · 0.85
ScalarFunctionClass · 0.85
is_column_from_schemaMethod · 0.80
index_of_columnMethod · 0.80
ColumnClass · 0.50
mapMethod · 0.45
transformMethod · 0.45
getMethod · 0.45
cloneMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…