You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/08/25 21:24:03 UTC
(datafusion) 01/01: chore: remove deprecated ScalarUDF / ScalarUDFImpl methods past the API health policy (#24561)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-24561-6e66a853b664b231737699d6704bdf721d44e92e
in repository https://gitbox.apache.org/repos/asf/datafusion.git
commit 1f5be0e70d0ea9705544b74f7ad83bd2130bbcb4
Author: Parman Mohammadalizadeh <pr...@gmail.com>
AuthorDate: Tue Aug 25 21:23:40 2026 +0000
chore: remove deprecated ScalarUDF / ScalarUDFImpl methods past the API health policy (#24561)
## Which issue does this PR close?
- Closes #24535.
## Rationale for this change
The [API health policy deprecation guidelines] keep a deprecated API for
6 major versions or 6 months, whichever is longer. `main` is at
`55.0.0`, so anything deprecated in `50.0.0` or earlier can now be
removed.
[API health policy deprecation guidelines]:
https://datafusion.apache.org/contributor-guide/api-health.html#deprecation-guidelines
## What changes are included in this PR?
The four methods named in the issue, all in
`datafusion/expr/src/udf.rs`:
| Item | Deprecated in |
| --- | --- |
| `ScalarUDFImpl::is_nullable` | 45.0.0 |
| `ScalarUDF::display_name` | 50.0.0 |
| `ScalarUDF::is_nullable` | 50.0.0 |
| `ScalarUDFImpl::display_name` | 50.0.0 |
Removing them takes five more sites with them, which is worth spelling
out since only one of the five is in the same file.
Two are the matching delegates on `AliasedScalarUDFImpl`, in `udf.rs`.
That impl is annotated `#[warn(clippy::missing_trait_methods)]` and
deliberately mirrors every `ScalarUDFImpl` method, so the pair has to go
at the same time.
Three are `display_name` overrides in other crates, on `ArrayElement`
and `ArraySlice` in `datafusion/functions-nested/src/extract.rs`, and on
`GetFieldFunc` in `datafusion/functions/src/core/getfield.rs`. Rust
fires the deprecation lint at call sites rather than at `impl` blocks,
so these three carried no `#[expect(deprecated)]` marker and produced no
warning before this change. Each of them also defines its own
`schema_name`, which is the method that actually names output columns,
so removing `display_name` changes no query output.
`ExprSchema` has no remaining use in `udf.rs` and comes out of the
import list. That is the only added line in the diff; everything else is
deletion.
No `56.0.0` upgrade guide note, per the issue.
## Are these changes tested?
Covered by existing tests. The removed code was unreachable, so there is
no new behaviour to add a test for.
Run locally on `1.97.0`:
```
cargo fmt --all -- --check clean
cargo clippy --all-targets --all-features -- -D warnings clean
./dev/rust_lint.sh clean (taplo, hawkeye, typos, prettier, rust_docs, workflow check)
```
Extended test suite, per `AGENTS.md`:
```
RUST_BACKTRACE=1 cargo test --profile ci \
--exclude datafusion-examples --exclude datafusion-benchmarks --exclude datafusion-cli \
--workspace --lib --tests --bins \
--features avro,json,backtrace,extended_tests,recursive_protection,parquet_encryption
```
68 test binaries, 10702 passed, 0 failed, 8 ignored (the 8 are
pre-existing `#[ignore]` tests, untouched here).
## Are there any user-facing changes?
Yes. This removes public Rust API, so the `api change` label applies.
Downstream implementors of `ScalarUDFImpl` that override `display_name`
or `is_nullable` will get a compile error naming the method. Callers of
`ScalarUDF::display_name` or `ScalarUDF::is_nullable` were already
getting a deprecation warning and will now get a compile error.
`is_nullable` is replaced by `return_field_from_args`; `display_name`
has no replacement because nothing in the codebase called it.
---
datafusion/expr/src/udf.rs | 54 +-----------------------------
datafusion/functions-nested/src/extract.rs | 18 ----------
datafusion/functions/src/core/getfield.rs | 20 -----------
3 files changed, 1 insertion(+), 91 deletions(-)
diff --git a/datafusion/expr/src/udf.rs b/datafusion/expr/src/udf.rs
index 2de3be4c10..e6acea173c 100644
--- a/datafusion/expr/src/udf.rs
+++ b/datafusion/expr/src/udf.rs
@@ -28,7 +28,7 @@ use arrow::datatypes::{DataType, Field, FieldRef};
#[cfg(debug_assertions)]
use datafusion_common::assert_or_internal_err;
use datafusion_common::config::ConfigOptions;
-use datafusion_common::{ExprSchema, Result, ScalarValue, not_impl_err};
+use datafusion_common::{Result, ScalarValue, not_impl_err};
use datafusion_expr_common::dyn_eq::{DynEq, DynHash};
use datafusion_expr_common::interval_arithmetic::Interval;
use datafusion_expr_common::placement::ExpressionPlacement;
@@ -183,18 +183,6 @@ impl ScalarUDF {
self.inner.name()
}
- /// Returns this function's display_name.
- ///
- /// See [`ScalarUDFImpl::display_name`] for more details
- #[deprecated(
- since = "50.0.0",
- note = "This method is unused and will be removed in a future release"
- )]
- pub fn display_name(&self, args: &[Expr]) -> Result<String> {
- #[expect(deprecated)]
- self.inner.display_name(args)
- }
-
/// Returns this function's schema_name.
///
/// See [`ScalarUDFImpl::schema_name`] for more details
@@ -255,12 +243,6 @@ impl ScalarUDF {
self.inner.simplify(args, info)
}
- #[deprecated(since = "50.0.0", note = "Use `return_field_from_args` instead.")]
- pub fn is_nullable(&self, args: &[Expr], schema: &dyn ExprSchema) -> bool {
- #[expect(deprecated)]
- self.inner.is_nullable(args, schema)
- }
-
/// Return a preimage
///
/// See [`ScalarUDFImpl::preimage`] for more details.
@@ -551,22 +533,6 @@ pub trait ScalarUDFImpl: Debug + DynEq + DynHash + Send + Sync + Any {
&[]
}
- /// Returns the user-defined display name of function, given the arguments
- ///
- /// This can be used to customize the output column name generated by this
- /// function.
- ///
- /// Defaults to `name(args[0], args[1], ...)`
- #[deprecated(
- since = "50.0.0",
- note = "This method is unused and will be removed in a future release"
- )]
- fn display_name(&self, args: &[Expr]) -> Result<String> {
- let names: Vec<String> = args.iter().map(ToString::to_string).collect();
- // TODO: join with ", " to standardize the formatting of Vec<Expr>, <https://github.com/apache/datafusion/issues/10364>
- Ok(format!("{}({})", self.name(), names.join(",")))
- }
-
/// Returns the name of the column this expression would create
///
/// See [`Expr::schema_name`] for details
@@ -698,14 +664,6 @@ pub trait ScalarUDFImpl: Debug + DynEq + DynHash + Send + Sync + Any {
Ok(Arc::new(Field::new(self.name(), return_type, true)))
}
- #[deprecated(
- since = "45.0.0",
- note = "Use `return_field_from_args` instead. if you use `is_nullable` that returns non-nullable with `return_type`, you would need to switch to `return_field_from_args`, you might have error"
- )]
- fn is_nullable(&self, _args: &[Expr], _schema: &dyn ExprSchema) -> bool {
- true
- }
-
/// Returns true if this function always returns NULL when any argument is
/// NULL.
///
@@ -1112,11 +1070,6 @@ impl ScalarUDFImpl for AliasedScalarUDFImpl {
self.inner.name()
}
- fn display_name(&self, args: &[Expr]) -> Result<String> {
- #[expect(deprecated)]
- self.inner.display_name(args)
- }
-
fn schema_name(&self, args: &[Expr]) -> Result<String> {
self.inner.schema_name(args)
}
@@ -1133,11 +1086,6 @@ impl ScalarUDFImpl for AliasedScalarUDFImpl {
self.inner.return_field_from_args(args)
}
- fn is_nullable(&self, args: &[Expr], schema: &dyn ExprSchema) -> bool {
- #[expect(deprecated)]
- self.inner.is_nullable(args, schema)
- }
-
fn is_strict(&self) -> bool {
self.inner.is_strict()
}
diff --git a/datafusion/functions-nested/src/extract.rs b/datafusion/functions-nested/src/extract.rs
index 52023e83bd..aa0d5f80d1 100644
--- a/datafusion/functions-nested/src/extract.rs
+++ b/datafusion/functions-nested/src/extract.rs
@@ -135,15 +135,6 @@ impl ScalarUDFImpl for ArrayElement {
"array_element"
}
- fn display_name(&self, args: &[Expr]) -> Result<String> {
- let args_name = args.iter().map(ToString::to_string).collect::<Vec<_>>();
- if args_name.len() != 2 {
- return exec_err!("expect 2 args, got {}", args_name.len());
- }
-
- Ok(format!("{}[{}]", args_name[0], args_name[1]))
- }
-
fn schema_name(&self, args: &[Expr]) -> Result<String> {
let args_name = args
.iter()
@@ -351,15 +342,6 @@ impl ArraySlice {
}
impl ScalarUDFImpl for ArraySlice {
- fn display_name(&self, args: &[Expr]) -> Result<String> {
- let args_name = args.iter().map(ToString::to_string).collect::<Vec<_>>();
- if let Some((arr, indexes)) = args_name.split_first() {
- Ok(format!("{arr}[{}]", indexes.join(":")))
- } else {
- exec_err!("no argument")
- }
- }
-
fn schema_name(&self, args: &[Expr]) -> Result<String> {
let args_name = args
.iter()
diff --git a/datafusion/functions/src/core/getfield.rs b/datafusion/functions/src/core/getfield.rs
index 6ec874fb67..388daa32bf 100644
--- a/datafusion/functions/src/core/getfield.rs
+++ b/datafusion/functions/src/core/getfield.rs
@@ -380,26 +380,6 @@ impl ScalarUDFImpl for GetFieldFunc {
"get_field"
}
- fn display_name(&self, args: &[Expr]) -> Result<String> {
- if args.len() < 2 {
- return exec_err!(
- "get_field requires at least 2 arguments, got {}",
- args.len()
- );
- }
-
- let base = &args[0];
- let field_names: Vec<String> = args[1..]
- .iter()
- .map(|f| match f {
- Expr::Literal(name, _) => name.to_string(),
- other => other.schema_name().to_string(),
- })
- .collect();
-
- Ok(format!("{}[{}]", base, field_names.join("][")))
- }
-
fn schema_name(&self, args: &[Expr]) -> Result<String> {
if args.len() < 2 {
return exec_err!(
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org