This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new 7df085e672 Enable user defined display_name for ScalarUDF (#10417)
7df085e672 is described below
commit 7df085e6723d3e2c56b2164a5012c82199810ea9
Author: Junhao Liu <[email protected]>
AuthorDate: Wed May 8 11:09:10 2024 -0600
Enable user defined display_name for ScalarUDF (#10417)
* enable user defined display_name
* add display_name to get_field
* add physical name
---
datafusion/core/src/physical_planner.rs | 5 ++---
datafusion/expr/src/expr.rs | 4 ++--
datafusion/expr/src/udf.rs | 15 +++++++++++++++
datafusion/functions/src/core/getfield.rs | 21 +++++++++++++++++++++
4 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/datafusion/core/src/physical_planner.rs
b/datafusion/core/src/physical_planner.rs
index dfcda553af..132bc3953c 100644
--- a/datafusion/core/src/physical_planner.rs
+++ b/datafusion/core/src/physical_planner.rs
@@ -239,9 +239,7 @@ fn create_physical_name(e: &Expr, is_first_expr: bool) ->
Result<String> {
}
};
}
- Expr::ScalarFunction(fun) => {
- create_function_physical_name(fun.name(), false, &fun.args, None)
- }
+ Expr::ScalarFunction(fun) => fun.func.display_name(&fun.args),
Expr::WindowFunction(WindowFunction {
fun,
args,
@@ -491,6 +489,7 @@ impl PhysicalPlanner for DefaultPhysicalPlanner {
let plan = self
.create_initial_plan(logical_plan, session_state)
.await?;
+
self.optimize_internal(plan, session_state, |_, _| {})
}
}
diff --git a/datafusion/expr/src/expr.rs b/datafusion/expr/src/expr.rs
index 9789dd345f..01ef2571ea 100644
--- a/datafusion/expr/src/expr.rs
+++ b/datafusion/expr/src/expr.rs
@@ -1637,7 +1637,7 @@ fn create_function_name(fun: &str, distinct: bool, args:
&[Expr]) -> Result<Stri
/// Returns a readable name of an expression based on the input schema.
/// This function recursively transverses the expression for names such as
"CAST(a > 2)".
-fn create_name(e: &Expr) -> Result<String> {
+pub(crate) fn create_name(e: &Expr) -> Result<String> {
match e {
Expr::Alias(Alias { name, .. }) => Ok(name.clone()),
Expr::Column(c) => Ok(c.flat_name()),
@@ -1793,7 +1793,7 @@ fn create_name(e: &Expr) -> Result<String> {
let expr_name = create_name(expr)?;
Ok(format!("unnest({expr_name})"))
}
- Expr::ScalarFunction(fun) => create_function_name(fun.name(), false,
&fun.args),
+ Expr::ScalarFunction(fun) => fun.func.display_name(&fun.args),
Expr::WindowFunction(WindowFunction {
fun,
args,
diff --git a/datafusion/expr/src/udf.rs b/datafusion/expr/src/udf.rs
index c9c11a6bbf..29ee4a86e5 100644
--- a/datafusion/expr/src/udf.rs
+++ b/datafusion/expr/src/udf.rs
@@ -17,6 +17,7 @@
//! [`ScalarUDF`]: Scalar User Defined Functions
+use crate::expr::create_name;
use crate::simplify::{ExprSimplifyResult, SimplifyInfo};
use crate::{
ColumnarValue, Expr, FuncMonotonicity, ReturnTypeFunction,
@@ -133,6 +134,13 @@ impl ScalarUDF {
self.inner.name()
}
+ /// Returns this function's display_name.
+ ///
+ /// See [`ScalarUDFImpl::display_name`] for more details
+ pub fn display_name(&self, args: &[Expr]) -> Result<String> {
+ self.inner.display_name(args)
+ }
+
/// Returns the aliases for this function.
///
/// See [`ScalarUDF::with_aliases`] for more details
@@ -274,6 +282,13 @@ pub trait ScalarUDFImpl: Debug + Send + Sync {
/// Returns this function's name
fn name(&self) -> &str;
+ /// Returns the user-defined display name of the UDF given the arguments
+ ///
+ fn display_name(&self, args: &[Expr]) -> Result<String> {
+ let names: Vec<String> =
args.iter().map(create_name).collect::<Result<_>>()?;
+ Ok(format!("{}({})", self.name(), names.join(",")))
+ }
+
/// Returns the function's [`Signature`] for information about what input
/// types are accepted and the function's Volatility.
fn signature(&self) -> &Signature;
diff --git a/datafusion/functions/src/core/getfield.rs
b/datafusion/functions/src/core/getfield.rs
index a092aac159..50c917548d 100644
--- a/datafusion/functions/src/core/getfield.rs
+++ b/datafusion/functions/src/core/getfield.rs
@@ -50,10 +50,31 @@ impl ScalarUDFImpl for GetFieldFunc {
fn as_any(&self) -> &dyn Any {
self
}
+
fn name(&self) -> &str {
"get_field"
}
+ fn display_name(&self, args: &[Expr]) -> Result<String> {
+ if args.len() != 2 {
+ return exec_err!(
+ "get_field function requires 2 arguments, got {}",
+ args.len()
+ );
+ }
+
+ let name = match &args[1] {
+ Expr::Literal(name) => name,
+ _ => {
+ return exec_err!(
+ "get_field function requires the argument field_name to be
a string"
+ );
+ }
+ };
+
+ Ok(format!("{}[{}]", args[0].display_name()?, name))
+ }
+
fn signature(&self) -> &Signature {
&self.signature
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]