@@ -270,51 +270,58 @@ fn find_window_expr<'a>(
270270 . find ( |expr| expr. schema_name ( ) . to_string ( ) == column_name)
271271}
272272
273- /// Transforms a Column expression into the actual expression from aggregation or projection if found.
273+ /// Transforms all Column expressions in a sort expression into the actual expression from aggregation or projection if found.
274274/// This is required because if an ORDER BY expression is present in an Aggregate or Select, it is replaced
275275/// with a Column expression (e.g., "sum(catalog_returns.cr_net_loss)"). We need to transform it back to
276276/// the actual expression, such as sum("catalog_returns"."cr_net_loss").
277277pub ( crate ) fn unproject_sort_expr (
278- sort_expr : & SortExpr ,
278+ mut sort_expr : SortExpr ,
279279 agg : Option < & Aggregate > ,
280280 input : & LogicalPlan ,
281281) -> Result < SortExpr > {
282- let mut sort_expr = sort_expr. clone ( ) ;
283-
284- // Remove alias if present, because ORDER BY cannot use aliases
285- if let Expr :: Alias ( alias ) = & sort_expr . expr {
286- sort_expr . expr = * alias. expr . clone ( ) ;
287- }
288-
289- let Expr :: Column ( ref col_ref ) = sort_expr . expr else {
290- return Ok ( sort_expr ) ;
291- } ;
282+ sort_expr. expr = sort_expr
283+ . expr
284+ . transform ( |sub_expr| {
285+ match sub_expr {
286+ // Remove alias if present, because ORDER BY cannot use aliases
287+ Expr :: Alias ( alias ) => Ok ( Transformed :: yes ( * alias . expr ) ) ,
288+ Expr :: Column ( col ) => {
289+ if col . relation . is_some ( ) {
290+ return Ok ( Transformed :: no ( Expr :: Column ( col ) ) ) ;
291+ }
292292
293- if col_ref. relation . is_some ( ) {
294- return Ok ( sort_expr) ;
295- } ;
293+ // In case of aggregation there could be columns containing aggregation functions we need to unproject
294+ if let Some ( agg) = agg {
295+ if agg. schema . is_column_from_schema ( & col) {
296+ return Ok ( Transformed :: yes ( unproject_agg_exprs (
297+ Expr :: Column ( col) ,
298+ agg,
299+ None ,
300+ ) ?) ) ;
301+ }
302+ }
296303
297- // In case of aggregation there could be columns containing aggregation functions we need to unproject
298- if let Some ( agg) = agg {
299- if agg. schema . is_column_from_schema ( col_ref) {
300- let new_expr = unproject_agg_exprs ( sort_expr. expr , agg, None ) ?;
301- sort_expr. expr = new_expr;
302- return Ok ( sort_expr) ;
303- }
304- }
304+ // If SELECT and ORDER BY contain the same expression with a scalar function, the ORDER BY expression will
305+ // be replaced by a Column expression (e.g., "substr(customer.c_last_name, Int64(0), Int64(5))"), and we need
306+ // to transform it back to the actual expression.
307+ if let LogicalPlan :: Projection ( Projection { expr, schema, .. } ) =
308+ input
309+ {
310+ if let Ok ( idx) = schema. index_of_column ( & col) {
311+ if let Some ( Expr :: ScalarFunction ( scalar_fn) ) = expr. get ( idx) {
312+ return Ok ( Transformed :: yes ( Expr :: ScalarFunction (
313+ scalar_fn. clone ( ) ,
314+ ) ) ) ;
315+ }
316+ }
317+ }
305318
306- // If SELECT and ORDER BY contain the same expression with a scalar function, the ORDER BY expression will
307- // be replaced by a Column expression (e.g., "substr(customer.c_last_name, Int64(0), Int64(5))"), and we need
308- // to transform it back to the actual expression.
309- if let LogicalPlan :: Projection ( Projection { expr, schema, .. } ) = input {
310- if let Ok ( idx) = schema. index_of_column ( col_ref) {
311- if let Some ( Expr :: ScalarFunction ( scalar_fn) ) = expr. get ( idx) {
312- sort_expr. expr = Expr :: ScalarFunction ( scalar_fn. clone ( ) ) ;
319+ Ok ( Transformed :: no ( Expr :: Column ( col) ) )
320+ }
321+ _ => Ok ( Transformed :: no ( sub_expr) ) ,
313322 }
314- }
315- return Ok ( sort_expr) ;
316- }
317-
323+ } )
324+ . map ( |e| e. data ) ?;
318325 Ok ( sort_expr)
319326}
320327
0 commit comments