## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/expr/src/udf.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    //! [`ScalarUDF`]: Scalar User Defined Functions
    19
    20
    use crate::async_udf::AsyncScalarUDF;
    21
    use crate::expr::schema_name_from_exprs_comma_separated_without_space;
    22
    use crate::simplify::{ExprSimplifyResult, SimplifyInfo};
    23
    use crate::sort_properties::{ExprProperties, SortProperties};
    24
    use crate::udf_eq::UdfEq;
    25
    use crate::{ColumnarValue, Documentation, Expr, Signature};
    26
    use arrow::datatypes::{DataType, Field, FieldRef};
    27
    use datafusion_common::config::ConfigOptions;
    28
    use datafusion_common::{
    29
        assert_or_internal_err, not_impl_err, DataFusionError, ExprSchema, Result,
    30
        ScalarValue,
    31
    };
    32
    use datafusion_expr_common::dyn_eq::{DynEq, DynHash};
    33
    use datafusion_expr_common::interval_arithmetic::Interval;
    34
    use std::any::Any;
    35
    use std::cmp::Ordering;
    36
    use std::fmt::Debug;
    37
    use std::hash::{Hash, Hasher};
    38
    use std::sync::Arc;
    39
    40
    /// Logical representation of a Scalar User Defined Function.
    41
    ///
    42
    /// A scalar function produces a single row output for each row of input. This
    43
    /// struct contains the information DataFusion needs to plan and invoke
    44
    /// functions you supply such as name, type signature, return type, and actual
    45
    /// implementation.
    46
    ///
    47
    /// 1. For simple use cases, use [`create_udf`] (examples in [`simple_udf.rs`]).
    48
    ///
    49
    /// 2. For advanced use cases, use [`ScalarUDFImpl`] which provides full API
    50
    ///    access (examples in  [`advanced_udf.rs`]).
    51
    ///
    52
    /// See [`Self::call`] to create an `Expr` which invokes a `ScalarUDF` with arguments.
    53
    ///
    54
    /// # API Note
    55
    ///
    56
    /// This is a separate struct from [`ScalarUDFImpl`] to maintain backwards
    57
    /// compatibility with the older API.
    58
    ///
    59
    /// [`create_udf`]: crate::expr_fn::create_udf
    60
    /// [`simple_udf.rs`]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/simple_udf.rs
    61
    /// [`advanced_udf.rs`]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/advanced_udf.rs
    62
    #[derive(Debug, Clone)]
    63
    pub struct ScalarUDF {
    64
        inner: Arc<dyn ScalarUDFImpl>,
    65
    }
    66
    67
    impl PartialEq for ScalarUDF {
    68
    0
        fn eq(&self, other: &Self) -> bool {
    69
    0
            self.inner.dyn_eq(other.inner.as_any())
    70
    0
        }
    71
    }
    72
    73
    impl PartialOrd for ScalarUDF {
    74
    0
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
    75
    0
            let mut cmp = self.name().cmp(other.name());
    76
    0
            if cmp == Ordering::Equal {
    77
    0
                cmp = self.signature().partial_cmp(other.signature())?;
    78
    0
            }
    79
    0
            if cmp == Ordering::Equal {
    80
    0
                cmp = self.aliases().partial_cmp(other.aliases())?;
    81
    0
            }
    82
            // Contract for PartialOrd and PartialEq consistency requires that
    83
            // a == b if and only if partial_cmp(a, b) == Some(Equal).
    84
    0
            if cmp == Ordering::Equal && self != other {
    85
                // Functions may have other properties besides name and signature
    86
                // that differentiate two instances (e.g. type, or arbitrary parameters).
    87
                // We cannot return Some(Equal) in such case.
    88
    0
                return None;
    89
    0
            }
    90
    0
            debug_assert!(
    91
    0
                cmp == Ordering::Equal || self != other,
    92
    0
                "Detected incorrect implementation of PartialEq when comparing functions: '{}' and '{}'. \
    93
    0
                The functions compare as equal, but they are not equal based on general properties that \
    94
    0
                the PartialOrd implementation observes,",
    95
    0
                self.name(), other.name()
    96
            );
    97
    0
            Some(cmp)
    98
    0
        }
    99
    }
    100
    101
    impl Eq for ScalarUDF {}
    102
    103
    impl Hash for ScalarUDF {
    104
    0
        fn hash<H: Hasher>(&self, state: &mut H) {
    105
    0
            self.inner.dyn_hash(state)
    106
    0
        }
    107
    }
    108
    109
    impl ScalarUDF {
    110
        /// Create a new `ScalarUDF` from a `[ScalarUDFImpl]` trait object
    111
        ///
    112
        /// Note this is the same as using the `From` impl (`ScalarUDF::from`)
    113
    0
        pub fn new_from_impl<F>(fun: F) -> ScalarUDF
    114
    0
        where
    115
    0
            F: ScalarUDFImpl + 'static,
    116
        {
    117
    0
            Self::new_from_shared_impl(Arc::new(fun))
    118
    0
        }
    119
    120
        /// Create a new `ScalarUDF` from a `[ScalarUDFImpl]` trait object
    121
    0
        pub fn new_from_shared_impl(fun: Arc<dyn ScalarUDFImpl>) -> ScalarUDF {
    122
    0
            Self { inner: fun }
    123
    0
        }
    124
    125
        /// Return the underlying [`ScalarUDFImpl`] trait object for this function
    126
    0
        pub fn inner(&self) -> &Arc<dyn ScalarUDFImpl> {
    127
    0
            &self.inner
    128
    0
        }
    129
    130
        /// Adds additional names that can be used to invoke this function, in
    131
        /// addition to `name`
    132
        ///
    133
        /// If you implement [`ScalarUDFImpl`] directly you should return aliases directly.
    134
    0
        pub fn with_aliases(self, aliases: impl IntoIterator<Item = &'static str>) -> Self {
    135
    0
            Self::new_from_impl(AliasedScalarUDFImpl::new(Arc::clone(&self.inner), aliases))
    136
    0
        }
    137
    138
        /// Returns a [`Expr`] logical expression to call this UDF with specified
    139
        /// arguments.
    140
        ///
    141
        /// This utility allows easily calling UDFs
    142
        ///
    143
        /// # Example
    144
        /// ```no_run
    145
        /// use datafusion_expr::{col, lit, ScalarUDF};
    146
        /// # fn my_udf() -> ScalarUDF { unimplemented!() }
    147
        /// let my_func: ScalarUDF = my_udf();
    148
        /// // Create an expr for `my_func(a, 12.3)`
    149
        /// let expr = my_func.call(vec![col("a"), lit(12.3)]);
    150
        /// ```
    151
    0
        pub fn call(&self, args: Vec<Expr>) -> Expr {
    152
    0
            Expr::ScalarFunction(crate::expr::ScalarFunction::new_udf(
    153
    0
                Arc::new(self.clone()),
    154
    0
                args,
    155
    0
            ))
    156
    0
        }
    157
    158
        /// Returns this function's name.
    159
        ///
    160
        /// See [`ScalarUDFImpl::name`] for more details.
    161
    0
        pub fn name(&self) -> &str {
    162
    0
            self.inner.name()
    163
    0
        }
    164
    165
        /// Returns this function's display_name.
    166
        ///
    167
        /// See [`ScalarUDFImpl::display_name`] for more details
    168
        #[deprecated(
    169
            since = "50.0.0",
    170
            note = "This method is unused and will be removed in a future release"
    171
        )]
    172
    0
        pub fn display_name(&self, args: &[Expr]) -> Result<String> {
    173
            #[expect(deprecated)]
    174
    0
            self.inner.display_name(args)
    175
    0
        }
    176
    177
        /// Returns this function's schema_name.
    178
        ///
    179
        /// See [`ScalarUDFImpl::schema_name`] for more details
    180
    0
        pub fn schema_name(&self, args: &[Expr]) -> Result<String> {
    181
    0
            self.inner.schema_name(args)
    182
    0
        }
    183
    184
        /// Returns the aliases for this function.
    185
        ///
    186
        /// See [`ScalarUDF::with_aliases`] for more details
    187
    0
        pub fn aliases(&self) -> &[String] {
    188
    0
            self.inner.aliases()
    189
    0
        }
    190
    191
        /// Returns this function's [`Signature`] (what input types are accepted).
    192
        ///
    193
        /// See [`ScalarUDFImpl::signature`] for more details.
    194
    0
        pub fn signature(&self) -> &Signature {
    195
    0
            self.inner.signature()
    196
    0
        }
    197
    198
        /// The datatype this function returns given the input argument types.
    199
        /// This function is used when the input arguments are [`DataType`]s.
    200
        ///
    201
        ///  # Notes
    202
        ///
    203
        /// If a function implement [`ScalarUDFImpl::return_field_from_args`],
    204
        /// its [`ScalarUDFImpl::return_type`] should raise an error.
    205
        ///
    206
        /// See [`ScalarUDFImpl::return_type`] for more details.
    207
    0
        pub fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
    208
    0
            self.inner.return_type(arg_types)
    209
    0
        }
    210
    211
        /// Return the datatype this function returns given the input argument types.
    212
        ///
    213
        /// See [`ScalarUDFImpl::return_field_from_args`] for more details.
    214
    0
        pub fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
    215
    0
            self.inner.return_field_from_args(args)
    216
    0
        }
    217
    218
        /// Do the function rewrite
    219
        ///
    220
        /// See [`ScalarUDFImpl::simplify`] for more details.
    221
    0
        pub fn simplify(
    222
    0
            &self,
    223
    0
            args: Vec<Expr>,
    224
    0
            info: &dyn SimplifyInfo,
    225
    0
        ) -> Result<ExprSimplifyResult> {
    226
    0
            self.inner.simplify(args, info)
    227
    0
        }
    228
    229
        #[deprecated(since = "50.0.0", note = "Use `return_field_from_args` instead.")]
    230
    0
        pub fn is_nullable(&self, args: &[Expr], schema: &dyn ExprSchema) -> bool {
    231
            #[allow(deprecated)]
    232
    0
            self.inner.is_nullable(args, schema)
    233
    0
        }
    234
    235
        /// Invoke the function on `args`, returning the appropriate result.
    236
        ///
    237
        /// See [`ScalarUDFImpl::invoke_with_args`] for details.
    238
    0
        pub fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
    239
            #[cfg(debug_assertions)]
    240
    0
            let return_field = Arc::clone(&args.return_field);
    241
    0
            let result = self.inner.invoke_with_args(args)?;
    242
            // Maybe this could be enabled always?
    243
            // This doesn't use debug_assert!, but it's meant to run anywhere except on production. It's same in spirit, thus conditioning on debug_assertions.
    244
            #[cfg(debug_assertions)]
    245
            {
    246
    0
                let result_data_type = result.data_type();
    247
    0
                let expected_type = return_field.data_type();
    248
    0
                assert_or_internal_err!(
    249
    0
                    result_data_type == *expected_type,
    250
    0
                    "Function '{}' returned value of type '{:?}' while the following type was promised at planning time and expected: '{:?}'",
    251
    0
                    self.name(),
    252
                    result_data_type,
    253
                    expected_type
    254
                );
    255
                // TODO verify return data is non-null when it was promised to be?
    256
            }
    257
    0
            Ok(result)
    258
    0
        }
    259
    260
        /// Determines which of the arguments passed to this function are evaluated eagerly
    261
        /// and which may be evaluated lazily.
    262
        ///
    263
        /// See [ScalarUDFImpl::conditional_arguments] for more information.
    264
    0
        pub fn conditional_arguments<'a>(
    265
    0
            &self,
    266
    0
            args: &'a [Expr],
    267
    0
        ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
    268
    0
            self.inner.conditional_arguments(args)
    269
    0
        }
    270
    271
        /// Returns true if some of this `exprs` subexpressions may not be evaluated
    272
        /// and thus any side effects (like divide by zero) may not be encountered.
    273
        ///
    274
        /// See [ScalarUDFImpl::short_circuits] for more information.
    275
    0
        pub fn short_circuits(&self) -> bool {
    276
    0
            self.inner.short_circuits()
    277
    0
        }
    278
    279
        /// Computes the output interval for a [`ScalarUDF`], given the input
    280
        /// intervals.
    281
        ///
    282
        /// # Parameters
    283
        ///
    284
        /// * `inputs` are the intervals for the inputs (children) of this function.
    285
        ///
    286
        /// # Example
    287
        ///
    288
        /// If the function is `ABS(a)`, and the input interval is `a: [-3, 2]`,
    289
        /// then the output interval would be `[0, 3]`.
    290
    0
        pub fn evaluate_bounds(&self, inputs: &[&Interval]) -> Result<Interval> {
    291
    0
            self.inner.evaluate_bounds(inputs)
    292
    0
        }
    293
    294
        /// Updates bounds for child expressions, given a known interval for this
    295
        /// function. This is used to propagate constraints down through an expression
    296
        /// tree.
    297
        ///
    298
        /// # Parameters
    299
        ///
    300
        /// * `interval` is the currently known interval for this function.
    301
        /// * `inputs` are the current intervals for the inputs (children) of this function.
    302
        ///
    303
        /// # Returns
    304
        ///
    305
        /// A `Vec` of new intervals for the children, in order.
    306
        ///
    307
        /// If constraint propagation reveals an infeasibility for any child, returns
    308
        /// [`None`]. If none of the children intervals change as a result of
    309
        /// propagation, may return an empty vector instead of cloning `children`.
    310
        /// This is the default (and conservative) return value.
    311
        ///
    312
        /// # Example
    313
        ///
    314
        /// If the function is `ABS(a)`, the current `interval` is `[4, 5]` and the
    315
        /// input `a` is given as `[-7, 3]`, then propagation would return `[-5, 3]`.
    316
    0
        pub fn propagate_constraints(
    317
    0
            &self,
    318
    0
            interval: &Interval,
    319
    0
            inputs: &[&Interval],
    320
    0
        ) -> Result<Option<Vec<Interval>>> {
    321
    0
            self.inner.propagate_constraints(interval, inputs)
    322
    0
        }
    323
    324
        /// Calculates the [`SortProperties`] of this function based on its
    325
        /// children's properties.
    326
    0
        pub fn output_ordering(&self, inputs: &[ExprProperties]) -> Result<SortProperties> {
    327
    0
            self.inner.output_ordering(inputs)
    328
    0
        }
    329
    330
    0
        pub fn preserves_lex_ordering(&self, inputs: &[ExprProperties]) -> Result<bool> {
    331
    0
            self.inner.preserves_lex_ordering(inputs)
    332
    0
        }
    333
    334
        /// See [`ScalarUDFImpl::coerce_types`] for more details.
    335
    0
        pub fn coerce_types(&self, arg_types: &[DataType]) -> Result<Vec<DataType>> {
    336
    0
            self.inner.coerce_types(arg_types)
    337
    0
        }
    338
    339
        /// Returns the documentation for this Scalar UDF.
    340
        ///
    341
        /// Documentation can be accessed programmatically as well as
    342
        /// generating publicly facing documentation.
    343
    0
        pub fn documentation(&self) -> Option<&Documentation> {
    344
    0
            self.inner.documentation()
    345
    0
        }
    346
    347
        /// Return true if this function is an async function
    348
    0
        pub fn as_async(&self) -> Option<&AsyncScalarUDF> {
    349
    0
            self.inner().as_any().downcast_ref::<AsyncScalarUDF>()
    350
    0
        }
    351
    }
    352
    353
    impl<F> From<F> for ScalarUDF
    354
    where
    355
        F: ScalarUDFImpl + 'static,
    356
    {
    357
    0
        fn from(fun: F) -> Self {
    358
    0
            Self::new_from_impl(fun)
    359
    0
        }
    360
    }
    361
    362
    /// Arguments passed to [`ScalarUDFImpl::invoke_with_args`] when invoking a
    363
    /// scalar function.
    364
    #[derive(Debug, Clone)]
    365
    pub struct ScalarFunctionArgs {
    366
        /// The evaluated arguments to the function
    367
        pub args: Vec<ColumnarValue>,
    368
        /// Field associated with each arg, if it exists
    369
        pub arg_fields: Vec<FieldRef>,
    370
        /// The number of rows in record batch being evaluated
    371
        pub number_rows: usize,
    372
        /// The return field of the scalar function returned (from `return_type`
    373
        /// or `return_field_from_args`) when creating the physical expression
    374
        /// from the logical expression
    375
        pub return_field: FieldRef,
    376
        /// The config options at execution time
    377
        pub config_options: Arc<ConfigOptions>,
    378
    }
    379
    380
    impl ScalarFunctionArgs {
    381
        /// The return type of the function. See [`Self::return_field`] for more
    382
        /// details.
    383
    0
        pub fn return_type(&self) -> &DataType {
    384
    0
            self.return_field.data_type()
    385
    0
        }
    386
    }
    387
    388
    /// Information about arguments passed to the function
    389
    ///
    390
    /// This structure contains metadata about how the function was called
    391
    /// such as the type of the arguments, any scalar arguments and if the
    392
    /// arguments can (ever) be null
    393
    ///
    394
    /// See [`ScalarUDFImpl::return_field_from_args`] for more information
    395
    #[derive(Debug)]
    396
    pub struct ReturnFieldArgs<'a> {
    397
        /// The data types of the arguments to the function
    398
        pub arg_fields: &'a [FieldRef],
    399
        /// Is argument `i` to the function a scalar (constant)?
    400
        ///
    401
        /// If the argument `i` is not a scalar, it will be None
    402
        ///
    403
        /// For example, if a function is called like `my_function(column_a, 5)`
    404
        /// this field will be `[None, Some(ScalarValue::Int32(Some(5)))]`
    405
        pub scalar_arguments: &'a [Option<&'a ScalarValue>],
    406
    }
    407
    408
    /// Trait for implementing user defined scalar functions.
    409
    ///
    410
    /// This trait exposes the full API for implementing user defined functions and
    411
    /// can be used to implement any function.
    412
    ///
    413
    /// See [`advanced_udf.rs`] for a full example with complete implementation and
    414
    /// [`ScalarUDF`] for other available options.
    415
    ///
    416
    /// [`advanced_udf.rs`]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/advanced_udf.rs
    417
    ///
    418
    /// # Basic Example
    419
    /// ```
    420
    /// # use std::any::Any;
    421
    /// # use std::sync::LazyLock;
    422
    /// # use arrow::datatypes::DataType;
    423
    /// # use datafusion_common::{DataFusionError, plan_err, Result};
    424
    /// # use datafusion_expr::{col, ColumnarValue, Documentation, ScalarFunctionArgs, Signature, Volatility};
    425
    /// # use datafusion_expr::{ScalarUDFImpl, ScalarUDF};
    426
    /// # use datafusion_expr::scalar_doc_sections::DOC_SECTION_MATH;
    427
    /// /// This struct for a simple UDF that adds one to an int32
    428
    /// #[derive(Debug, PartialEq, Eq, Hash)]
    429
    /// struct AddOne {
    430
    ///   signature: Signature,
    431
    /// }
    432
    ///
    433
    /// impl AddOne {
    434
    ///   fn new() -> Self {
    435
    ///     Self {
    436
    ///       signature: Signature::uniform(1, vec![DataType::Int32], Volatility::Immutable),
    437
    ///      }
    438
    ///   }
    439
    /// }
    440
    ///
    441
    /// static DOCUMENTATION: LazyLock<Documentation> = LazyLock::new(|| {
    442
    ///         Documentation::builder(DOC_SECTION_MATH, "Add one to an int32", "add_one(2)")
    443
    ///             .with_argument("arg1", "The int32 number to add one to")
    444
    ///             .build()
    445
    ///     });
    446
    ///
    447
    /// fn get_doc() -> &'static Documentation {
    448
    ///     &DOCUMENTATION
    449
    /// }
    450
    ///
    451
    /// /// Implement the ScalarUDFImpl trait for AddOne
    452
    /// impl ScalarUDFImpl for AddOne {
    453
    ///    fn as_any(&self) -> &dyn Any { self }
    454
    ///    fn name(&self) -> &str { "add_one" }
    455
    ///    fn signature(&self) -> &Signature { &self.signature }
    456
    ///    fn return_type(&self, args: &[DataType]) -> Result<DataType> {
    457
    ///      if !matches!(args.get(0), Some(&DataType::Int32)) {
    458
    ///        return plan_err!("add_one only accepts Int32 arguments");
    459
    ///      }
    460
    ///      Ok(DataType::Int32)
    461
    ///    }
    462
    ///    // The actual implementation would add one to the argument
    463
    ///    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
    464
    ///         unimplemented!()
    465
    ///    }
    466
    ///    fn documentation(&self) -> Option<&Documentation> {
    467
    ///         Some(get_doc())
    468
    ///     }
    469
    /// }
    470
    ///
    471
    /// // Create a new ScalarUDF from the implementation
    472
    /// let add_one = ScalarUDF::from(AddOne::new());
    473
    ///
    474
    /// // Call the function `add_one(col)`
    475
    /// let expr = add_one.call(vec![col("a")]);
    476
    /// ```
    477
    pub trait ScalarUDFImpl: Debug + DynEq + DynHash + Send + Sync {
    478
        /// Returns this object as an [`Any`] trait object
    479
        fn as_any(&self) -> &dyn Any;
    480
    481
        /// Returns this function's name
    482
        fn name(&self) -> &str;
    483
    484
        /// Returns any aliases (alternate names) for this function.
    485
        ///
    486
        /// Aliases can be used to invoke the same function using different names.
    487
        /// For example in some databases `now()` and `current_timestamp()` are
    488
        /// aliases for the same function. This behavior can be obtained by
    489
        /// returning `current_timestamp` as an alias for the `now` function.
    490
        ///
    491
        /// Note: `aliases` should only include names other than [`Self::name`].
    492
        /// Defaults to `[]` (no aliases)
    493
    0
        fn aliases(&self) -> &[String] {
    494
    0
            &[]
    495
    0
        }
    496
    497
        /// Returns the user-defined display name of function, given the arguments
    498
        ///
    499
        /// This can be used to customize the output column name generated by this
    500
        /// function.
    501
        ///
    502
        /// Defaults to `name(args[0], args[1], ...)`
    503
        #[deprecated(
    504
            since = "50.0.0",
    505
            note = "This method is unused and will be removed in a future release"
    506
        )]
    507
    0
        fn display_name(&self, args: &[Expr]) -> Result<String> {
    508
    0
            let names: Vec<String> = args.iter().map(ToString::to_string).collect();
    509
            // TODO: join with ", " to standardize the formatting of Vec<Expr>, <https://github.com/apache/datafusion/issues/10364>
    510
    0
            Ok(format!("{}({})", self.name(), names.join(",")))
    511
    0
        }
    512
    513
        /// Returns the name of the column this expression would create
    514
        ///
    515
        /// See [`Expr::schema_name`] for details
    516
    0
        fn schema_name(&self, args: &[Expr]) -> Result<String> {
    517
    0
            Ok(format!(
    518
    0
                "{}({})",
    519
    0
                self.name(),
    520
    0
                schema_name_from_exprs_comma_separated_without_space(args)?
    521
            ))
    522
    0
        }
    523
    524
        /// Returns a [`Signature`] describing the argument types for which this
    525
        /// function has an implementation, and the function's [`Volatility`].
    526
        ///
    527
        /// See [`Signature`] for more details on argument type handling
    528
        /// and [`Self::return_type`] for computing the return type.
    529
        ///
    530
        /// [`Volatility`]: datafusion_expr_common::signature::Volatility
    531
        fn signature(&self) -> &Signature;
    532
    533
        /// [`DataType`] returned by this function, given the types of the
    534
        /// arguments.
    535
        ///
    536
        /// # Arguments
    537
        ///
    538
        /// `arg_types` Data types of the arguments. The implementation of
    539
        /// `return_type` can assume that some other part of the code has coerced
    540
        /// the actual argument types to match [`Self::signature`].
    541
        ///
    542
        /// # Notes
    543
        ///
    544
        /// If you provide an implementation for [`Self::return_field_from_args`],
    545
        /// DataFusion will not call `return_type` (this function). While it is
    546
        /// valid to to put [`unimplemented!()`] or [`unreachable!()`], it is
    547
        /// recommended to return [`DataFusionError::Internal`] instead, which
    548
        /// reduces the severity of symptoms if bugs occur (an error rather than a
    549
        /// panic).
    550
        ///
    551
        /// [`DataFusionError::Internal`]: datafusion_common::DataFusionError::Internal
    552
        fn return_type(&self, arg_types: &[DataType]) -> Result<DataType>;
    553
    554
        /// Create a new instance of this function with updated configuration.
    555
        ///
    556
        /// This method is called when configuration options change at runtime
    557
        /// (e.g., via `SET` statements) to allow functions that depend on
    558
        /// configuration to update themselves accordingly.
    559
        ///
    560
        /// Note the current [`ConfigOptions`] are also passed to [`Self::invoke_with_args`] so
    561
        /// this API is not needed for functions where the values may
    562
        /// depend on the current options.
    563
        ///
    564
        /// This API is useful for functions where the return
    565
        /// **type** depends on the configuration options, such as the `now()` function
    566
        /// which depends on the current timezone.
    567
        ///
    568
        /// # Arguments
    569
        ///
    570
        /// * `config` - The updated configuration options
    571
        ///
    572
        /// # Returns
    573
        ///
    574
        /// * `Some(ScalarUDF)` - A new instance of this function configured with the new settings
    575
        /// * `None` - If this function does not change with new configuration settings (the default)
    576
    0
        fn with_updated_config(&self, _config: &ConfigOptions) -> Option<ScalarUDF> {
    577
    0
            None
    578
    0
        }
    579
    580
        /// What type will be returned by this function, given the arguments?
    581
        ///
    582
        /// By default, this function calls [`Self::return_type`] with the
    583
        /// types of each argument.
    584
        ///
    585
        /// # Notes
    586
        ///
    587
        /// For the majority of UDFs, implementing [`Self::return_type`] is sufficient,
    588
        /// as the result type is typically a deterministic function of the input types
    589
        /// (e.g., `sqrt(f32)` consistently yields `f32`). Implementing this method directly
    590
        /// is generally unnecessary unless the return type depends on runtime values.
    591
        ///
    592
        /// This function can be used for more advanced cases such as:
    593
        ///
    594
        /// 1. specifying nullability
    595
        /// 2. return types based on the **values** of the arguments (rather than
    596
        ///    their **types**.
    597
        ///
    598
        /// # Example creating `Field`
    599
        ///
    600
        /// Note the name of the [`Field`] is ignored, except for structured types such as
    601
        /// `DataType::Struct`.
    602
        ///
    603
        /// ```rust
    604
        /// # use std::sync::Arc;
    605
        /// # use arrow::datatypes::{DataType, Field, FieldRef};
    606
        /// # use datafusion_common::Result;
    607
        /// # use datafusion_expr::ReturnFieldArgs;
    608
        /// # struct Example{}
    609
        /// # impl Example {
    610
        /// fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
    611
        ///     // report output is only nullable if any one of the arguments are nullable
    612
        ///     let nullable = args.arg_fields.iter().any(|f| f.is_nullable());
    613
        ///     let field = Arc::new(Field::new("ignored_name", DataType::Int32, true));
    614
        ///     Ok(field)
    615
        /// }
    616
        /// # }
    617
        /// ```
    618
        ///
    619
        /// # Output Type based on Values
    620
        ///
    621
        /// For example, the following two function calls get the same argument
    622
        /// types (something and a `Utf8` string) but return different types based
    623
        /// on the value of the second argument:
    624
        ///
    625
        /// * `arrow_cast(x, 'Int16')` --> `Int16`
    626
        /// * `arrow_cast(x, 'Float32')` --> `Float32`
    627
        ///
    628
        /// # Requirements
    629
        ///
    630
        /// This function **must** consistently return the same type for the same
    631
        /// logical input even if the input is simplified (e.g. it must return the same
    632
        /// value for `('foo' | 'bar')` as it does for ('foobar').
    633
    0
        fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
    634
    0
            let data_types = args
    635
    0
                .arg_fields
    636
    0
                .iter()
    637
    0
                .map(|f| f.data_type())
    638
    0
                .cloned()
    639
    0
                .collect::<Vec<_>>();
    640
    0
            let return_type = self.return_type(&data_types)?;
    641
    0
            Ok(Arc::new(Field::new(self.name(), return_type, true)))
    642
    0
        }
    643
    644
        #[deprecated(
    645
            since = "45.0.0",
    646
            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"
    647
        )]
    648
    0
        fn is_nullable(&self, _args: &[Expr], _schema: &dyn ExprSchema) -> bool {
    649
    0
            true
    650
    0
        }
    651
    652
        /// Invoke the function returning the appropriate result.
    653
        ///
    654
        /// # Performance
    655
        ///
    656
        /// For the best performance, the implementations should handle the common case
    657
        /// when one or more of their arguments are constant values (aka
    658
        /// [`ColumnarValue::Scalar`]).
    659
        ///
    660
        /// [`ColumnarValue::values_to_arrays`] can be used to convert the arguments
    661
        /// to arrays, which will likely be simpler code, but be slower.
    662
        fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue>;
    663
    664
        /// Optionally apply per-UDF simplification / rewrite rules.
    665
        ///
    666
        /// This can be used to apply function specific simplification rules during
    667
        /// optimization (e.g. `arrow_cast` --> `Expr::Cast`). The default
    668
        /// implementation does nothing.
    669
        ///
    670
        /// Note that DataFusion handles simplifying arguments and  "constant
    671
        /// folding" (replacing a function call with constant arguments such as
    672
        /// `my_add(1,2) --> 3` ). Thus, there is no need to implement such
    673
        /// optimizations manually for specific UDFs.
    674
        ///
    675
        /// # Arguments
    676
        /// * `args`: The arguments of the function
    677
        /// * `info`: The necessary information for simplification
    678
        ///
    679
        /// # Returns
    680
        /// [`ExprSimplifyResult`] indicating the result of the simplification NOTE
    681
        /// if the function cannot be simplified, the arguments *MUST* be returned
    682
        /// unmodified
    683
        ///
    684
        /// # Notes
    685
        ///
    686
        /// The returned expression must have the same schema as the original
    687
        /// expression, including both the data type and nullability. For example,
    688
        /// if the original expression is nullable, the returned expression must
    689
        /// also be nullable, otherwise it may lead to schema verification errors
    690
        /// later in query planning.
    691
    0
        fn simplify(
    692
    0
            &self,
    693
    0
            args: Vec<Expr>,
    694
    0
            _info: &dyn SimplifyInfo,
    695
    0
        ) -> Result<ExprSimplifyResult> {
    696
    0
            Ok(ExprSimplifyResult::Original(args))
    697
    0
        }
    698
    699
        /// Returns true if some of this `exprs` subexpressions may not be evaluated
    700
        /// and thus any side effects (like divide by zero) may not be encountered.
    701
        ///
    702
        /// Setting this to true prevents certain optimizations such as common
    703
        /// subexpression elimination
    704
        ///
    705
        /// When overriding this function to return `true`, [ScalarUDFImpl::conditional_arguments] can also be
    706
        /// overridden to report more accurately which arguments are eagerly evaluated and which ones
    707
        /// lazily.
    708
    0
        fn short_circuits(&self) -> bool {
    709
    0
            false
    710
    0
        }
    711
    712
        /// Determines which of the arguments passed to this function are evaluated eagerly
    713
        /// and which may be evaluated lazily.
    714
        ///
    715
        /// If this function returns `None`, all arguments are eagerly evaluated.
    716
        /// Returning `None` is a micro optimization that saves a needless `Vec`
    717
        /// allocation.
    718
        ///
    719
        /// If the function returns `Some`, returns (`eager`, `lazy`) where `eager`
    720
        /// are the arguments that are always evaluated, and `lazy` are the
    721
        /// arguments that may be evaluated lazily (i.e. may not be evaluated at all
    722
        /// in some cases).
    723
        ///
    724
        /// Implementations must ensure that the two returned `Vec`s are disjunct,
    725
        /// and that each argument from `args` is present in one the two `Vec`s.
    726
        ///
    727
        /// When overriding this function, [ScalarUDFImpl::short_circuits] must
    728
        /// be overridden to return `true`.
    729
    0
        fn conditional_arguments<'a>(
    730
    0
            &self,
    731
    0
            args: &'a [Expr],
    732
    0
        ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
    733
    0
            if self.short_circuits() {
    734
    0
                Some((vec![], args.iter().collect()))
    735
            } else {
    736
    0
                None
    737
            }
    738
    0
        }
    739
    740
        /// Computes the output [`Interval`] for a [`ScalarUDFImpl`], given the input
    741
        /// intervals.
    742
        ///
    743
        /// # Parameters
    744
        ///
    745
        /// * `children` are the intervals for the children (inputs) of this function.
    746
        ///
    747
        /// # Example
    748
        ///
    749
        /// If the function is `ABS(a)`, and the input interval is `a: [-3, 2]`,
    750
        /// then the output interval would be `[0, 3]`.
    751
    0
        fn evaluate_bounds(&self, _input: &[&Interval]) -> Result<Interval> {
    752
            // We cannot assume the input datatype is the same of output type.
    753
    0
            Interval::make_unbounded(&DataType::Null)
    754
    0
        }
    755
    756
        /// Updates bounds for child expressions, given a known [`Interval`]s for this
    757
        /// function.
    758
        ///
    759
        /// This function is used to propagate constraints down through an
    760
        /// expression tree.
    761
        ///
    762
        /// # Parameters
    763
        ///
    764
        /// * `interval` is the currently known interval for this function.
    765
        /// * `inputs` are the current intervals for the inputs (children) of this function.
    766
        ///
    767
        /// # Returns
    768
        ///
    769
        /// A `Vec` of new intervals for the children, in order.
    770
        ///
    771
        /// If constraint propagation reveals an infeasibility for any child, returns
    772
        /// [`None`]. If none of the children intervals change as a result of
    773
        /// propagation, may return an empty vector instead of cloning `children`.
    774
        /// This is the default (and conservative) return value.
    775
        ///
    776
        /// # Example
    777
        ///
    778
        /// If the function is `ABS(a)`, the current `interval` is `[4, 5]` and the
    779
        /// input `a` is given as `[-7, 3]`, then propagation would return `[-5, 3]`.
    780
    0
        fn propagate_constraints(
    781
    0
            &self,
    782
    0
            _interval: &Interval,
    783
    0
            _inputs: &[&Interval],
    784
    0
        ) -> Result<Option<Vec<Interval>>> {
    785
    0
            Ok(Some(vec![]))
    786
    0
        }
    787
    788
        /// Calculates the [`SortProperties`] of this function based on its children's properties.
    789
    0
        fn output_ordering(&self, inputs: &[ExprProperties]) -> Result<SortProperties> {
    790
    0
            if !self.preserves_lex_ordering(inputs)? {
    791
    0
                return Ok(SortProperties::Unordered);
    792
    0
            }
    793
    794
    0
            let Some(first_order) = inputs.first().map(|p| &p.sort_properties) else {
    795
    0
                return Ok(SortProperties::Singleton);
    796
            };
    797
    798
    0
            if inputs
    799
    0
                .iter()
    800
    0
                .skip(1)
    801
    0
                .all(|input| &input.sort_properties == first_order)
    802
            {
    803
    0
                Ok(*first_order)
    804
            } else {
    805
    0
                Ok(SortProperties::Unordered)
    806
            }
    807
    0
        }
    808
    809
        /// Returns true if the function preserves lexicographical ordering based on
    810
        /// the input ordering.
    811
        ///
    812
        /// For example, `concat(a || b)` preserves lexicographical ordering, but `abs(a)` does not.
    813
    0
        fn preserves_lex_ordering(&self, _inputs: &[ExprProperties]) -> Result<bool> {
    814
    0
            Ok(false)
    815
    0
        }
    816
    817
        /// Coerce arguments of a function call to types that the function can evaluate.
    818
        ///
    819
        /// This function is only called if [`ScalarUDFImpl::signature`] returns
    820
        /// [`crate::TypeSignature::UserDefined`]. Most UDFs should return one of
    821
        /// the other variants of [`TypeSignature`] which handle common cases.
    822
        ///
    823
        /// See the [type coercion module](crate::type_coercion)
    824
        /// documentation for more details on type coercion
    825
        ///
    826
        /// [`TypeSignature`]: crate::TypeSignature
    827
        ///
    828
        /// For example, if your function requires a floating point arguments, but the user calls
    829
        /// it like `my_func(1::int)` (i.e. with `1` as an integer), coerce_types can return `[DataType::Float64]`
    830
        /// to ensure the argument is converted to `1::double`
    831
        ///
    832
        /// # Parameters
    833
        /// * `arg_types`: The argument types of the arguments  this function with
    834
        ///
    835
        /// # Return value
    836
        /// A Vec the same length as `arg_types`. DataFusion will `CAST` the function call
    837
        /// arguments to these specific types.
    838
    0
        fn coerce_types(&self, _arg_types: &[DataType]) -> Result<Vec<DataType>> {
    839
    0
            not_impl_err!("Function {} does not implement coerce_types", self.name())
    840
    0
        }
    841
    842
        /// Returns the documentation for this Scalar UDF.
    843
        ///
    844
        /// Documentation can be accessed programmatically as well as generating
    845
        /// publicly facing documentation.
    846
    0
        fn documentation(&self) -> Option<&Documentation> {
    847
    0
            None
    848
    0
        }
    849
    }
    850
    851
    /// ScalarUDF that adds an alias to the underlying function. It is better to
    852
    /// implement [`ScalarUDFImpl`], which supports aliases, directly if possible.
    853
    #[derive(Debug, PartialEq, Eq, Hash)]
    854
    struct AliasedScalarUDFImpl {
    855
        inner: UdfEq<Arc<dyn ScalarUDFImpl>>,
    856
        aliases: Vec<String>,
    857
    }
    858
    859
    impl AliasedScalarUDFImpl {
    860
    0
        pub fn new(
    861
    0
            inner: Arc<dyn ScalarUDFImpl>,
    862
    0
            new_aliases: impl IntoIterator<Item = &'static str>,
    863
    0
        ) -> Self {
    864
    0
            let mut aliases = inner.aliases().to_vec();
    865
    0
            aliases.extend(new_aliases.into_iter().map(|s| s.to_string()));
    866
    0
            Self {
    867
    0
                inner: inner.into(),
    868
    0
                aliases,
    869
    0
            }
    870
    0
        }
    871
    }
    872
    873
    #[warn(clippy::missing_trait_methods)] // Delegates, so it should implement every single trait method
    874
    impl ScalarUDFImpl for AliasedScalarUDFImpl {
    875
    0
        fn as_any(&self) -> &dyn Any {
    876
    0
            self
    877
    0
        }
    878
    879
    0
        fn name(&self) -> &str {
    880
    0
            self.inner.name()
    881
    0
        }
    882
    883
    0
        fn display_name(&self, args: &[Expr]) -> Result<String> {
    884
            #[expect(deprecated)]
    885
    0
            self.inner.display_name(args)
    886
    0
        }
    887
    888
    0
        fn schema_name(&self, args: &[Expr]) -> Result<String> {
    889
    0
            self.inner.schema_name(args)
    890
    0
        }
    891
    892
    0
        fn signature(&self) -> &Signature {
    893
    0
            self.inner.signature()
    894
    0
        }
    895
    896
    0
        fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
    897
    0
            self.inner.return_type(arg_types)
    898
    0
        }
    899
    900
    0
        fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
    901
    0
            self.inner.return_field_from_args(args)
    902
    0
        }
    903
    904
    0
        fn is_nullable(&self, args: &[Expr], schema: &dyn ExprSchema) -> bool {
    905
            #[allow(deprecated)]
    906
    0
            self.inner.is_nullable(args, schema)
    907
    0
        }
    908
    909
    0
        fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
    910
    0
            self.inner.invoke_with_args(args)
    911
    0
        }
    912
    913
    0
        fn with_updated_config(&self, _config: &ConfigOptions) -> Option<ScalarUDF> {
    914
    0
            None
    915
    0
        }
    916
    917
    0
        fn aliases(&self) -> &[String] {
    918
    0
            &self.aliases
    919
    0
        }
    920
    921
    0
        fn simplify(
    922
    0
            &self,
    923
    0
            args: Vec<Expr>,
    924
    0
            info: &dyn SimplifyInfo,
    925
    0
        ) -> Result<ExprSimplifyResult> {
    926
    0
            self.inner.simplify(args, info)
    927
    0
        }
    928
    929
    0
        fn conditional_arguments<'a>(
    930
    0
            &self,
    931
    0
            args: &'a [Expr],
    932
    0
        ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
    933
    0
            self.inner.conditional_arguments(args)
    934
    0
        }
    935
    936
    0
        fn short_circuits(&self) -> bool {
    937
    0
            self.inner.short_circuits()
    938
    0
        }
    939
    940
    0
        fn evaluate_bounds(&self, input: &[&Interval]) -> Result<Interval> {
    941
    0
            self.inner.evaluate_bounds(input)
    942
    0
        }
    943
    944
    0
        fn propagate_constraints(
    945
    0
            &self,
    946
    0
            interval: &Interval,
    947
    0
            inputs: &[&Interval],
    948
    0
        ) -> Result<Option<Vec<Interval>>> {
    949
    0
            self.inner.propagate_constraints(interval, inputs)
    950
    0
        }
    951
    952
    0
        fn output_ordering(&self, inputs: &[ExprProperties]) -> Result<SortProperties> {
    953
    0
            self.inner.output_ordering(inputs)
    954
    0
        }
    955
    956
    0
        fn preserves_lex_ordering(&self, inputs: &[ExprProperties]) -> Result<bool> {
    957
    0
            self.inner.preserves_lex_ordering(inputs)
    958
    0
        }
    959
    960
    0
        fn coerce_types(&self, arg_types: &[DataType]) -> Result<Vec<DataType>> {
    961
    0
            self.inner.coerce_types(arg_types)
    962
    0
        }
    963
    964
    0
        fn documentation(&self) -> Option<&Documentation> {
    965
    0
            self.inner.documentation()
    966
    0
        }
    967
    }
    968
    969
    #[cfg(test)]
    970
    mod tests {
    971
        use super::*;
    972
        use datafusion_expr_common::signature::Volatility;
    973
        use std::hash::DefaultHasher;
    974
    975
        #[derive(Debug, PartialEq, Eq, Hash)]
    976
        struct TestScalarUDFImpl {
    977
            name: &'static str,
    978
            field: &'static str,
    979
            signature: Signature,
    980
        }
    981
        impl ScalarUDFImpl for TestScalarUDFImpl {
    982
            fn as_any(&self) -> &dyn Any {
    983
                self
    984
            }
    985
    986
            fn name(&self) -> &str {
    987
                self.name
    988
            }
    989
    990
            fn signature(&self) -> &Signature {
    991
                &self.signature
    992
            }
    993
    994
            fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
    995
                unimplemented!()
    996
            }
    997
    998
            fn invoke_with_args(&self, _args: ScalarFunctionArgs) -> Result<ColumnarValue> {
    999
                unimplemented!()
    1000
            }
    1001
        }
    1002
    1003
        // PartialEq and Hash must be consistent, and also PartialEq and PartialOrd
    1004
        // must be consistent, so they are tested together.
    1005
        #[test]
    1006
        fn test_partial_eq_hash_and_partial_ord() {
    1007
            // A parameterized function
    1008
            let f = test_func("foo", "a");
    1009
    1010
            // Same like `f`, different instance
    1011
            let f2 = test_func("foo", "a");
    1012
            assert_eq!(f, f2);
    1013
            assert_eq!(hash(&f), hash(&f2));
    1014
            assert_eq!(f.partial_cmp(&f2), Some(Ordering::Equal));
    1015
    1016
            // Different parameter
    1017
            let b = test_func("foo", "b");
    1018
            assert_ne!(f, b);
    1019
            assert_ne!(hash(&f), hash(&b)); // hash can collide for different values but does not collide in this test
    1020
            assert_eq!(f.partial_cmp(&b), None);
    1021
    1022
            // Different name
    1023
            let o = test_func("other", "a");
    1024
            assert_ne!(f, o);
    1025
            assert_ne!(hash(&f), hash(&o)); // hash can collide for different values but does not collide in this test
    1026
            assert_eq!(f.partial_cmp(&o), Some(Ordering::Less));
    1027
    1028
            // Different name and parameter
    1029
            assert_ne!(b, o);
    1030
            assert_ne!(hash(&b), hash(&o)); // hash can collide for different values but does not collide in this test
    1031
            assert_eq!(b.partial_cmp(&o), Some(Ordering::Less));
    1032
        }
    1033
    1034
        fn test_func(name: &'static str, parameter: &'static str) -> ScalarUDF {
    1035
            ScalarUDF::from(TestScalarUDFImpl {
    1036
                name,
    1037
                field: parameter,
    1038
                signature: Signature::any(1, Volatility::Immutable),
    1039
            })
    1040
        }
    1041
    1042
        fn hash<T: Hash>(value: &T) -> u64 {
    1043
            let hasher = &mut DefaultHasher::new();
    1044
            value.hash(hasher);
    1045
            hasher.finish()
    1046
        }
    1047
    }