Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions datafusion/core/tests/user_defined/user_defined_window_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,22 +145,22 @@ async fn test_udwf_with_alias() {
.await
.unwrap();

insta::assert_snapshot!(batches_to_string(&actual), @r###"
+---+---+-----+-----------------------------------------------------------------------------------------------------------------------+
| x | y | val | odd_counter(t.val) PARTITION BY [t.x] ORDER BY [t.y ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW |
+---+---+-----+-----------------------------------------------------------------------------------------------------------------------+
| 1 | a | 0 | 1 |
| 1 | b | 1 | 1 |
| 1 | c | 2 | 1 |
| 2 | d | 3 | 2 |
| 2 | e | 4 | 2 |
| 2 | f | 5 | 2 |
| 2 | g | 6 | 2 |
| 2 | h | 6 | 2 |
| 2 | i | 6 | 2 |
| 2 | j | 6 | 2 |
+---+---+-----+-----------------------------------------------------------------------------------------------------------------------+
"###);
insta::assert_snapshot!(batches_to_string(&actual), @r"
+---+---+-----+--------------------------+
| x | y | val | odd_counter_alias(t.val) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it inconsistent how having a function alias also removes the PARTITION BY... compared to the non-alias version 🤔

(For reference I do like how it looks without that long column name)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jefffrey,

You've pointed out the exact inconsistency that I also came across in my last PR!

I had a discussion about this with @alamb (you can see the conversation here: #17469 (comment)), and we agreed the best plan was to fix the alias naming first in this PR, and then create a new issue for normalizing output column names of window functions.

I've already created that follow-up issue at #17790.

So, this PR just brings the alias behavior in line with the other function types, and we can address the rest of the cleanup in the new issue. Thanks for the review!

+---+---+-----+--------------------------+
| 1 | a | 0 | 1 |
| 1 | b | 1 | 1 |
| 1 | c | 2 | 1 |
| 2 | d | 3 | 2 |
| 2 | e | 4 | 2 |
| 2 | f | 5 | 2 |
| 2 | g | 6 | 2 |
| 2 | h | 6 | 2 |
| 2 | i | 6 | 2 |
| 2 | j | 6 | 2 |
+---+---+-----+--------------------------+
");
}

/// Basic user defined window function with bounded window
Expand Down
22 changes: 19 additions & 3 deletions datafusion/sql/src/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
distinct,
} = window_expr;

let expr = Expr::from(WindowFunction {
let inner = WindowFunction {
fun: func_def,
params: expr::WindowFunctionParams {
args,
Expand All @@ -409,9 +409,25 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
null_treatment,
distinct,
},
});
};

return Ok(expr);
if name.eq_ignore_ascii_case(inner.fun.name()) {
return Ok(Expr::WindowFunction(Box::new(inner)));
} else {
// If the function is called by an alias, a verbose string representation is created
// (e.g., "my_alias(arg1, arg2)") and the expression is wrapped in an `Alias`
// to ensure the output column name matches the user's query.
let arg_names = inner
.params
.args
.iter()
.map(|arg| arg.to_string())
.collect::<Vec<_>>()
.join(",");
let verbose_alias = format!("{name}({arg_names})");

return Ok(Expr::WindowFunction(Box::new(inner)).alias(verbose_alias));
}
}
} else {
// User defined aggregate functions (UDAF) have precedence in case it has the same name as a scalar built-in function
Expand Down