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