Skip to main content

datafusion_expr/
udf.rs

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
20use crate::async_udf::AsyncScalarUDF;
21use crate::expr::schema_name_from_exprs_comma_separated_without_space;
22use crate::preimage::PreimageResult;
23use crate::simplify::{ExprSimplifyResult, SimplifyContext};
24use crate::sort_properties::{ExprProperties, SortProperties};
25use crate::udf_eq::UdfEq;
26use crate::{ColumnarValue, Documentation, Expr, Signature};
27use arrow::datatypes::{DataType, Field, FieldRef};
28#[cfg(debug_assertions)]
29use datafusion_common::assert_or_internal_err;
30use datafusion_common::config::ConfigOptions;
31use datafusion_common::{ExprSchema, Result, ScalarValue, not_impl_err};
32use datafusion_expr_common::dyn_eq::{DynEq, DynHash};
33use datafusion_expr_common::interval_arithmetic::Interval;
34use datafusion_expr_common::placement::ExpressionPlacement;
35use std::any::Any;
36use std::cmp::Ordering;
37use std::fmt::Debug;
38use std::hash::{Hash, Hasher};
39use std::sync::Arc;
40
41/// Describes how a struct-producing UDF's output fields correspond to its
42/// input arguments. This enables the optimizer to propagate orderings
43/// through struct projections (e.g., so that sorting by a struct field
44/// can be recognized as equivalent to sorting by the source column).
45///
46/// See [`ScalarUDFImpl::struct_field_mapping`] for details.
47pub struct StructFieldMapping {
48    /// The UDF used to construct field access expressions on the output.
49    /// For example, the `get_field` UDF for accessing struct fields.
50    pub field_accessor: Arc<ScalarUDF>,
51    /// For each output field: the literal arguments to pass to the
52    /// `field_accessor` UDF (after the base expression), and the index
53    /// of the corresponding input argument that produces the field's value.
54    ///
55    /// For `named_struct('a', col1, 'b', col2)`, this would be:
56    /// `[(["a"], 1), (["b"], 3)]` — field `"a"` comes from arg index 1.
57    pub fields: Vec<(Vec<ScalarValue>, usize)>,
58}
59
60/// Logical representation of a Scalar User Defined Function.
61///
62/// A scalar function produces a single row output for each row of input. This
63/// struct contains the information DataFusion needs to plan and invoke
64/// functions you supply such as name, type signature, return type, and actual
65/// implementation.
66///
67/// 1. For simple use cases, use [`create_udf`] (examples in [`simple_udf.rs`]).
68///
69/// 2. For advanced use cases, use [`ScalarUDFImpl`] which provides full API
70///    access (examples in  [`advanced_udf.rs`]).
71///
72/// See [`Self::call`] to create an `Expr` which invokes a `ScalarUDF` with arguments.
73///
74/// # API Note
75///
76/// This is a separate struct from [`ScalarUDFImpl`] to maintain backwards
77/// compatibility with the older API.
78///
79/// [`create_udf`]: crate::expr_fn::create_udf
80/// [`simple_udf.rs`]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/udf/simple_udf.rs
81/// [`advanced_udf.rs`]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/udf/advanced_udf.rs
82#[derive(Debug, Clone)]
83pub struct ScalarUDF {
84    inner: Arc<dyn ScalarUDFImpl>,
85}
86
87impl PartialEq for ScalarUDF {
88    fn eq(&self, other: &Self) -> bool {
89        self.inner.as_ref().dyn_eq(other.inner.as_ref() as &dyn Any)
90    }
91}
92
93impl PartialOrd for ScalarUDF {
94    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
95        let mut cmp = self.name().cmp(other.name());
96        if cmp == Ordering::Equal {
97            cmp = self.signature().partial_cmp(other.signature())?;
98        }
99        if cmp == Ordering::Equal {
100            cmp = self.aliases().partial_cmp(other.aliases())?;
101        }
102        // Contract for PartialOrd and PartialEq consistency requires that
103        // a == b if and only if partial_cmp(a, b) == Some(Equal).
104        if cmp == Ordering::Equal && self != other {
105            // Functions may have other properties besides name and signature
106            // that differentiate two instances (e.g. type, or arbitrary parameters).
107            // We cannot return Some(Equal) in such case.
108            return None;
109        }
110        debug_assert!(
111            cmp == Ordering::Equal || self != other,
112            "Detected incorrect implementation of PartialEq when comparing functions: '{}' and '{}'. \
113            The functions compare as equal, but they are not equal based on general properties that \
114            the PartialOrd implementation observes,",
115            self.name(),
116            other.name()
117        );
118        Some(cmp)
119    }
120}
121
122impl Eq for ScalarUDF {}
123
124impl Hash for ScalarUDF {
125    fn hash<H: Hasher>(&self, state: &mut H) {
126        self.inner.dyn_hash(state)
127    }
128}
129
130impl ScalarUDF {
131    /// Create a new `ScalarUDF` from a `[ScalarUDFImpl]` trait object
132    ///
133    /// Note this is the same as using the `From` impl (`ScalarUDF::from`)
134    pub fn new_from_impl<F>(fun: F) -> ScalarUDF
135    where
136        F: ScalarUDFImpl + 'static,
137    {
138        Self::new_from_shared_impl(Arc::new(fun))
139    }
140
141    /// Create a new `ScalarUDF` from a `[ScalarUDFImpl]` trait object
142    pub fn new_from_shared_impl(fun: Arc<dyn ScalarUDFImpl>) -> ScalarUDF {
143        Self { inner: fun }
144    }
145
146    /// Return the underlying [`ScalarUDFImpl`] trait object for this function
147    pub fn inner(&self) -> &Arc<dyn ScalarUDFImpl> {
148        &self.inner
149    }
150
151    /// Adds additional names that can be used to invoke this function, in
152    /// addition to `name`
153    ///
154    /// If you implement [`ScalarUDFImpl`] directly you should return aliases directly.
155    pub fn with_aliases(self, aliases: impl IntoIterator<Item = &'static str>) -> Self {
156        Self::new_from_impl(AliasedScalarUDFImpl::new(Arc::clone(&self.inner), aliases))
157    }
158
159    /// Returns a [`Expr`] logical expression to call this UDF with specified
160    /// arguments.
161    ///
162    /// This utility allows easily calling UDFs
163    ///
164    /// # Example
165    /// ```no_run
166    /// use datafusion_expr::{col, lit, ScalarUDF};
167    /// # fn my_udf() -> ScalarUDF { unimplemented!() }
168    /// let my_func: ScalarUDF = my_udf();
169    /// // Create an expr for `my_func(a, 12.3)`
170    /// let expr = my_func.call(vec![col("a"), lit(12.3)]);
171    /// ```
172    pub fn call(&self, args: Vec<Expr>) -> Expr {
173        Expr::ScalarFunction(crate::expr::ScalarFunction::new_udf(
174            Arc::new(self.clone()),
175            args,
176        ))
177    }
178
179    /// Returns this function's name.
180    ///
181    /// See [`ScalarUDFImpl::name`] for more details.
182    pub fn name(&self) -> &str {
183        self.inner.name()
184    }
185
186    /// Returns this function's display_name.
187    ///
188    /// See [`ScalarUDFImpl::display_name`] for more details
189    #[deprecated(
190        since = "50.0.0",
191        note = "This method is unused and will be removed in a future release"
192    )]
193    pub fn display_name(&self, args: &[Expr]) -> Result<String> {
194        #[expect(deprecated)]
195        self.inner.display_name(args)
196    }
197
198    /// Returns this function's schema_name.
199    ///
200    /// See [`ScalarUDFImpl::schema_name`] for more details
201    pub fn schema_name(&self, args: &[Expr]) -> Result<String> {
202        self.inner.schema_name(args)
203    }
204
205    /// Returns the aliases for this function.
206    ///
207    /// See [`ScalarUDF::with_aliases`] for more details
208    pub fn aliases(&self) -> &[String] {
209        self.inner.aliases()
210    }
211
212    /// Returns true if this function always returns NULL when any argument is
213    /// NULL.
214    ///
215    /// See [`ScalarUDFImpl::is_strict`] for more details.
216    pub fn is_strict(&self) -> bool {
217        self.inner.is_strict()
218    }
219
220    /// Returns this function's [`Signature`] (what input types are accepted).
221    ///
222    /// See [`ScalarUDFImpl::signature`] for more details.
223    pub fn signature(&self) -> &Signature {
224        self.inner.signature()
225    }
226
227    /// The datatype this function returns given the input argument types.
228    /// This function is used when the input arguments are [`DataType`]s.
229    ///
230    ///  # Notes
231    ///
232    /// If a function implement [`ScalarUDFImpl::return_field_from_args`],
233    /// its [`ScalarUDFImpl::return_type`] should raise an error.
234    ///
235    /// See [`ScalarUDFImpl::return_type`] for more details.
236    pub fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
237        self.inner.return_type(arg_types)
238    }
239
240    /// Return the datatype this function returns given the input argument types.
241    ///
242    /// See [`ScalarUDFImpl::return_field_from_args`] for more details.
243    pub fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
244        self.inner.return_field_from_args(args)
245    }
246
247    /// Returns this scalar function's simplification result.
248    ///
249    /// See [`ScalarUDFImpl::simplify`] for more details.
250    pub fn simplify(
251        &self,
252        args: Vec<Expr>,
253        info: &SimplifyContext,
254    ) -> Result<ExprSimplifyResult> {
255        self.inner.simplify(args, info)
256    }
257
258    #[deprecated(since = "50.0.0", note = "Use `return_field_from_args` instead.")]
259    pub fn is_nullable(&self, args: &[Expr], schema: &dyn ExprSchema) -> bool {
260        #[expect(deprecated)]
261        self.inner.is_nullable(args, schema)
262    }
263
264    /// Return a preimage
265    ///
266    /// See [`ScalarUDFImpl::preimage`] for more details.
267    pub fn preimage(
268        &self,
269        args: &[Expr],
270        lit_expr: &Expr,
271        info: &SimplifyContext,
272    ) -> Result<PreimageResult> {
273        self.inner.preimage(args, lit_expr, info)
274    }
275
276    /// Invoke the function on `args`, returning the appropriate result.
277    ///
278    /// See [`ScalarUDFImpl::invoke_with_args`] for details.
279    pub fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
280        #[cfg(debug_assertions)]
281        let return_field = Arc::clone(&args.return_field);
282        let result = self.inner.invoke_with_args(args)?;
283        // Maybe this could be enabled always?
284        // 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.
285        #[cfg(debug_assertions)]
286        {
287            let result_data_type = result.data_type();
288            let expected_type = return_field.data_type();
289            assert_or_internal_err!(
290                result_data_type == *expected_type,
291                "Function '{}' returned value of type '{}' while the following type was promised at planning time and expected: '{}'",
292                self.name(),
293                result_data_type,
294                expected_type
295            );
296            // TODO verify return data is non-null when it was promised to be?
297        }
298        Ok(result)
299    }
300
301    /// Determines which of the arguments passed to this function are evaluated eagerly
302    /// and which may be evaluated lazily.
303    ///
304    /// See [ScalarUDFImpl::conditional_arguments] for more information.
305    pub fn conditional_arguments<'a>(
306        &self,
307        args: &'a [Expr],
308    ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
309        self.inner.conditional_arguments(args)
310    }
311
312    /// Returns true if some of this `exprs` subexpressions may not be evaluated
313    /// and thus any side effects (like divide by zero) may not be encountered.
314    ///
315    /// See [ScalarUDFImpl::short_circuits] for more information.
316    pub fn short_circuits(&self) -> bool {
317        self.inner.short_circuits()
318    }
319
320    /// Computes the output interval for a [`ScalarUDF`], given the input
321    /// intervals.
322    ///
323    /// # Parameters
324    ///
325    /// * `inputs` are the intervals for the inputs (children) of this function.
326    ///
327    /// # Example
328    ///
329    /// If the function is `ABS(a)`, and the input interval is `a: [-3, 2]`,
330    /// then the output interval would be `[0, 3]`.
331    pub fn evaluate_bounds(&self, inputs: &[&Interval]) -> Result<Interval> {
332        self.inner.evaluate_bounds(inputs)
333    }
334
335    /// See [`ScalarUDFImpl::struct_field_mapping`] for more details.
336    pub fn struct_field_mapping(
337        &self,
338        literal_args: &[Option<ScalarValue>],
339    ) -> Option<StructFieldMapping> {
340        self.inner.struct_field_mapping(literal_args)
341    }
342
343    /// Updates bounds for child expressions, given a known interval for this
344    /// function. This is used to propagate constraints down through an expression
345    /// tree.
346    ///
347    /// # Parameters
348    ///
349    /// * `interval` is the currently known interval for this function.
350    /// * `inputs` are the current intervals for the inputs (children) of this function.
351    ///
352    /// # Returns
353    ///
354    /// A `Vec` of new intervals for the children, in order.
355    ///
356    /// If constraint propagation reveals an infeasibility for any child, returns
357    /// [`None`]. If none of the children intervals change as a result of
358    /// propagation, may return an empty vector instead of cloning `children`.
359    /// This is the default (and conservative) return value.
360    ///
361    /// # Example
362    ///
363    /// If the function is `ABS(a)`, the current `interval` is `[4, 5]` and the
364    /// input `a` is given as `[-7, 3]`, then propagation would return `[-5, 3]`.
365    pub fn propagate_constraints(
366        &self,
367        interval: &Interval,
368        inputs: &[&Interval],
369    ) -> Result<Option<Vec<Interval>>> {
370        self.inner.propagate_constraints(interval, inputs)
371    }
372
373    /// Calculates the [`SortProperties`] of this function based on its
374    /// children's properties.
375    pub fn output_ordering(&self, inputs: &[ExprProperties]) -> Result<SortProperties> {
376        self.inner.output_ordering(inputs)
377    }
378
379    pub fn preserves_lex_ordering(&self, inputs: &[ExprProperties]) -> Result<bool> {
380        self.inner.preserves_lex_ordering(inputs)
381    }
382
383    /// See [`ScalarUDFImpl::strictly_order_preserving`] for more details.
384    pub fn strictly_order_preserving(&self, inputs: &[ExprProperties]) -> Result<bool> {
385        self.inner.strictly_order_preserving(inputs)
386    }
387
388    /// See [`ScalarUDFImpl::coerce_types`] for more details.
389    pub fn coerce_types(&self, arg_types: &[DataType]) -> Result<Vec<DataType>> {
390        self.inner.coerce_types(arg_types)
391    }
392
393    /// Returns the documentation for this Scalar UDF.
394    ///
395    /// Documentation can be accessed programmatically as well as
396    /// generating publicly facing documentation.
397    pub fn documentation(&self) -> Option<&Documentation> {
398        self.inner.documentation()
399    }
400
401    /// Return true if this function is an async function
402    pub fn as_async(&self) -> Option<&AsyncScalarUDF> {
403        self.inner().downcast_ref::<AsyncScalarUDF>()
404    }
405
406    /// Returns placement information for this function.
407    ///
408    /// See [`ScalarUDFImpl::placement`] for more details.
409    pub fn placement(&self, args: &[ExpressionPlacement]) -> ExpressionPlacement {
410        self.inner.placement(args)
411    }
412}
413
414impl<F> From<F> for ScalarUDF
415where
416    F: ScalarUDFImpl + 'static,
417{
418    fn from(fun: F) -> Self {
419        Self::new_from_impl(fun)
420    }
421}
422
423/// Arguments passed to [`ScalarUDFImpl::invoke_with_args`] when invoking a
424/// scalar function.
425#[derive(Debug, Clone)]
426pub struct ScalarFunctionArgs {
427    /// The evaluated arguments to the function
428    pub args: Vec<ColumnarValue>,
429    /// Field associated with each arg, if it exists
430    pub arg_fields: Vec<FieldRef>,
431    /// The number of rows in record batch being evaluated
432    pub number_rows: usize,
433    /// The return field of the scalar function returned (from `return_type`
434    /// or `return_field_from_args`) when creating the physical expression
435    /// from the logical expression
436    pub return_field: FieldRef,
437    /// The config options at execution time
438    pub config_options: Arc<ConfigOptions>,
439}
440
441impl ScalarFunctionArgs {
442    /// The return type of the function. See [`Self::return_field`] for more
443    /// details.
444    pub fn return_type(&self) -> &DataType {
445        self.return_field.data_type()
446    }
447}
448
449/// Information about arguments passed to the function
450///
451/// This structure contains metadata about how the function was called
452/// such as the type of the arguments, any scalar arguments and if the
453/// arguments can (ever) be null
454///
455/// See [`ScalarUDFImpl::return_field_from_args`] for more information
456#[derive(Debug)]
457pub struct ReturnFieldArgs<'a> {
458    /// The data types of the arguments to the function
459    pub arg_fields: &'a [FieldRef],
460    /// Is argument `i` to the function a scalar (constant)?
461    ///
462    /// If the argument `i` is not a scalar, it will be None
463    ///
464    /// For example, if a function is called like `my_function(column_a, 5)`
465    /// this field will be `[None, Some(ScalarValue::Int32(Some(5)))]`
466    pub scalar_arguments: &'a [Option<&'a ScalarValue>],
467}
468
469/// Trait for implementing user defined scalar functions.
470///
471/// This trait exposes the full API for implementing user defined functions and
472/// can be used to implement any function.
473///
474/// See [`advanced_udf.rs`] for a full example with complete implementation and
475/// [`ScalarUDF`] for other available options.
476///
477/// [`advanced_udf.rs`]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/udf/advanced_udf.rs
478///
479/// # Basic Example
480/// ```
481/// # use std::any::Any;
482/// # use std::sync::LazyLock;
483/// # use arrow::datatypes::DataType;
484/// # use datafusion_common::{DataFusionError, plan_err, Result};
485/// # use datafusion_expr::{col, ColumnarValue, Documentation, ScalarFunctionArgs, Signature, Volatility};
486/// # use datafusion_expr::{ScalarUDFImpl, ScalarUDF};
487/// # use datafusion_expr::scalar_doc_sections::DOC_SECTION_MATH;
488/// /// This struct for a simple UDF that adds one to an int32
489/// #[derive(Debug, PartialEq, Eq, Hash)]
490/// struct AddOne {
491///   signature: Signature,
492/// }
493///
494/// impl AddOne {
495///   fn new() -> Self {
496///     Self {
497///       signature: Signature::uniform(1, vec![DataType::Int32], Volatility::Immutable),
498///      }
499///   }
500/// }
501///
502/// static DOCUMENTATION: LazyLock<Documentation> = LazyLock::new(|| {
503///         Documentation::builder(DOC_SECTION_MATH, "Add one to an int32", "add_one(2)")
504///             .with_argument("arg1", "The int32 number to add one to")
505///             .build()
506///     });
507///
508/// fn get_doc() -> &'static Documentation {
509///     &DOCUMENTATION
510/// }
511///
512/// /// Implement the ScalarUDFImpl trait for AddOne
513/// impl ScalarUDFImpl for AddOne {
514///    fn name(&self) -> &str { "add_one" }
515///    fn signature(&self) -> &Signature { &self.signature }
516///    fn return_type(&self, args: &[DataType]) -> Result<DataType> {
517///      if !matches!(args.get(0), Some(&DataType::Int32)) {
518///        return plan_err!("add_one only accepts Int32 arguments");
519///      }
520///      Ok(DataType::Int32)
521///    }
522///    // The actual implementation would add one to the argument
523///    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
524///         unimplemented!()
525///    }
526///    fn documentation(&self) -> Option<&Documentation> {
527///         Some(get_doc())
528///     }
529/// }
530///
531/// // Create a new ScalarUDF from the implementation
532/// let add_one = ScalarUDF::from(AddOne::new());
533///
534/// // Call the function `add_one(col)`
535/// let expr = add_one.call(vec![col("a")]);
536/// ```
537pub trait ScalarUDFImpl: Debug + DynEq + DynHash + Send + Sync + Any {
538    /// Returns this function's name
539    fn name(&self) -> &str;
540
541    /// Returns any aliases (alternate names) for this function.
542    ///
543    /// Aliases can be used to invoke the same function using different names.
544    /// For example in some databases `now()` and `current_timestamp()` are
545    /// aliases for the same function. This behavior can be obtained by
546    /// returning `current_timestamp` as an alias for the `now` function.
547    ///
548    /// Note: `aliases` should only include names other than [`Self::name`].
549    /// Defaults to `[]` (no aliases)
550    fn aliases(&self) -> &[String] {
551        &[]
552    }
553
554    /// Returns the user-defined display name of function, given the arguments
555    ///
556    /// This can be used to customize the output column name generated by this
557    /// function.
558    ///
559    /// Defaults to `name(args[0], args[1], ...)`
560    #[deprecated(
561        since = "50.0.0",
562        note = "This method is unused and will be removed in a future release"
563    )]
564    fn display_name(&self, args: &[Expr]) -> Result<String> {
565        let names: Vec<String> = args.iter().map(ToString::to_string).collect();
566        // TODO: join with ", " to standardize the formatting of Vec<Expr>, <https://github.com/apache/datafusion/issues/10364>
567        Ok(format!("{}({})", self.name(), names.join(",")))
568    }
569
570    /// Returns the name of the column this expression would create
571    ///
572    /// See [`Expr::schema_name`] for details
573    fn schema_name(&self, args: &[Expr]) -> Result<String> {
574        Ok(format!(
575            "{}({})",
576            self.name(),
577            schema_name_from_exprs_comma_separated_without_space(args)?
578        ))
579    }
580
581    /// Returns a [`Signature`] describing the argument types for which this
582    /// function has an implementation, and the function's [`Volatility`].
583    ///
584    /// See [`Signature`] for more details on argument type handling
585    /// and [`Self::return_type`] for computing the return type.
586    ///
587    /// [`Volatility`]: datafusion_expr_common::signature::Volatility
588    fn signature(&self) -> &Signature;
589
590    /// [`DataType`] returned by this function, given the types of the
591    /// arguments.
592    ///
593    /// # Arguments
594    ///
595    /// `arg_types` Data types of the arguments. The implementation of
596    /// `return_type` can assume that some other part of the code has coerced
597    /// the actual argument types to match [`Self::signature`].
598    ///
599    /// # Notes
600    ///
601    /// If you provide an implementation for [`Self::return_field_from_args`],
602    /// DataFusion will not call `return_type` (this function). While it is
603    /// valid to put [`unimplemented!()`] or [`unreachable!()`], it is
604    /// recommended to return [`DataFusionError::Internal`] instead, which
605    /// reduces the severity of symptoms if bugs occur (an error rather than a
606    /// panic).
607    ///
608    /// [`DataFusionError::Internal`]: datafusion_common::DataFusionError::Internal
609    fn return_type(&self, arg_types: &[DataType]) -> Result<DataType>;
610
611    /// Create a new instance of this function with updated configuration.
612    ///
613    /// This method is called when configuration options change at runtime
614    /// (e.g., via `SET` statements) to allow functions that depend on
615    /// configuration to update themselves accordingly.
616    ///
617    /// Note the current [`ConfigOptions`] are also passed to [`Self::invoke_with_args`] so
618    /// this API is not needed for functions where the values may
619    /// depend on the current options.
620    ///
621    /// This API is useful for functions where the return
622    /// **type** depends on the configuration options, such as the `now()` function
623    /// which depends on the current timezone.
624    ///
625    /// # Arguments
626    ///
627    /// * `config` - The updated configuration options
628    ///
629    /// # Returns
630    ///
631    /// * `Some(ScalarUDF)` - A new instance of this function configured with the new settings
632    /// * `None` - If this function does not change with new configuration settings (the default)
633    fn with_updated_config(&self, _config: &ConfigOptions) -> Option<ScalarUDF> {
634        None
635    }
636
637    /// What type will be returned by this function, given the arguments?
638    ///
639    /// By default, this function calls [`Self::return_type`] with the
640    /// types of each argument.
641    ///
642    /// # Notes
643    ///
644    /// For the majority of UDFs, implementing [`Self::return_type`] is sufficient,
645    /// as the result type is typically a deterministic function of the input types
646    /// (e.g., `sqrt(f32)` consistently yields `f32`). Implementing this method directly
647    /// is generally unnecessary unless the return type depends on runtime values.
648    ///
649    /// This function can be used for more advanced cases such as:
650    ///
651    /// 1. specifying nullability
652    /// 2. return types based on the **values** of the arguments (rather than
653    ///    their **types**.
654    ///
655    /// # Example creating `Field`
656    ///
657    /// Note the name of the [`Field`] is ignored, except for structured types such as
658    /// `DataType::Struct`.
659    ///
660    /// ```rust
661    /// # use std::sync::Arc;
662    /// # use arrow::datatypes::{DataType, Field, FieldRef};
663    /// # use datafusion_common::Result;
664    /// # use datafusion_expr::ReturnFieldArgs;
665    /// # struct Example{}
666    /// # impl Example {
667    /// fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
668    ///     // report output is only nullable if any one of the arguments are nullable
669    ///     let nullable = args.arg_fields.iter().any(|f| f.is_nullable());
670    ///     let field = Arc::new(Field::new("ignored_name", DataType::Int32, nullable));
671    ///     Ok(field)
672    /// }
673    /// # }
674    /// ```
675    ///
676    /// # Output Type based on Values
677    ///
678    /// For example, the following two function calls get the same argument
679    /// types (something and a `Utf8` string) but return different types based
680    /// on the value of the second argument:
681    ///
682    /// * `arrow_cast(x, 'Int16')` --> `Int16`
683    /// * `arrow_cast(x, 'Float32')` --> `Float32`
684    ///
685    /// # Requirements
686    ///
687    /// This function **must** consistently return the same type for the same
688    /// logical input even if the input is simplified (e.g. it must return the same
689    /// value for `('foo' | 'bar')` as it does for ('foobar').
690    fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
691        let data_types = args
692            .arg_fields
693            .iter()
694            .map(|f| f.data_type())
695            .cloned()
696            .collect::<Vec<_>>();
697        let return_type = self.return_type(&data_types)?;
698        Ok(Arc::new(Field::new(self.name(), return_type, true)))
699    }
700
701    #[deprecated(
702        since = "45.0.0",
703        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"
704    )]
705    fn is_nullable(&self, _args: &[Expr], _schema: &dyn ExprSchema) -> bool {
706        true
707    }
708
709    /// Returns true if this function always returns NULL when any argument is
710    /// NULL.
711    ///
712    /// Strict functions are NULL-propagating: if any argument evaluates to
713    /// NULL, the function result is guaranteed to be NULL. Optimizer rules can
714    /// use this property when reasoning about expression nullability and
715    /// null-rejecting filters.
716    ///
717    /// Defaults to `false` because user-defined functions may choose to accept
718    /// NULL inputs and produce non-NULL results.
719    fn is_strict(&self) -> bool {
720        false
721    }
722
723    /// Invoke the function returning the appropriate result.
724    ///
725    /// # Performance
726    ///
727    /// For the best performance, the implementations should handle the common case
728    /// when one or more of their arguments are constant values (aka
729    /// [`ColumnarValue::Scalar`]).
730    ///
731    /// [`ColumnarValue::values_to_arrays`] can be used to convert the arguments
732    /// to arrays, which will likely be simpler code, but be slower.
733    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue>;
734
735    /// Optionally apply per-UDF simplification / rewrite rules.
736    ///
737    /// This can be used to apply function specific simplification rules during
738    /// optimization (e.g. `arrow_cast` --> `Expr::Cast`). The default
739    /// implementation does nothing.
740    ///
741    /// Note that DataFusion handles simplifying arguments and  "constant
742    /// folding" (replacing a function call with constant arguments such as
743    /// `my_add(1,2) --> 3` ). Thus, there is no need to implement such
744    /// optimizations manually for specific UDFs.
745    ///
746    /// # Arguments
747    /// * `args`: The arguments of the function
748    /// * `info`: The necessary information for simplification
749    ///
750    /// # Returns
751    /// [`ExprSimplifyResult`] indicating the result of the simplification NOTE
752    /// if the function cannot be simplified, the arguments *MUST* be returned
753    /// unmodified
754    ///
755    /// # Notes
756    ///
757    /// The returned expression must have the same schema as the original
758    /// expression, including both the data type and nullability. For example,
759    /// if the original expression is nullable, the returned expression must
760    /// also be nullable, otherwise it may lead to schema verification errors
761    /// later in query planning.
762    fn simplify(
763        &self,
764        args: Vec<Expr>,
765        _info: &SimplifyContext,
766    ) -> Result<ExprSimplifyResult> {
767        Ok(ExprSimplifyResult::Original(args))
768    }
769
770    /// Returns a single contiguous preimage for this function and the specified
771    /// scalar expression, if any.
772    ///
773    /// Currently only applies to `=, !=, >, >=, <, <=, is distinct from, is not distinct from` predicates
774    /// # Return Value
775    ///
776    /// Implementations should return a half-open interval: inclusive lower
777    /// bound and exclusive upper bound. This is slightly different from normal
778    /// [`Interval`] semantics where the upper bound is closed (inclusive).
779    /// Typically this means the upper endpoint must be adjusted to the next
780    /// value not included in the preimage. See the Half-Open Intervals section
781    /// below for more details.
782    ///
783    /// # Background
784    ///
785    /// Inspired by the [ClickHouse Paper], a "preimage rewrite" transforms a
786    /// predicate containing a function call into a predicate containing an
787    /// equivalent set of input literal (constant) values. The resulting
788    /// predicate can often be further optimized by other rewrites (see
789    /// Examples).
790    ///
791    /// From the paper:
792    ///
793    /// > some functions can compute the preimage of a given function result.
794    /// > This is used to replace comparisons of constants with function calls
795    /// > on the key columns by comparing the key column value with the preimage.
796    /// > For example, `toYear(k) = 2024` can be replaced by
797    /// > `k >= 2024-01-01 && k < 2025-01-01`
798    ///
799    /// For example, given an expression like
800    /// ```sql
801    /// date_part('YEAR', k) = 2024
802    /// ```
803    ///
804    /// The interval `[2024-01-01, 2025-12-31`]` contains all possible input
805    /// values (preimage values) for which the function `date_part(YEAR, k)`
806    /// produces the output value `2024` (image value). Returning the interval
807    /// (note upper bound adjusted up) `[2024-01-01, 2025-01-01]` the expression
808    /// can be rewritten to
809    ///
810    /// ```sql
811    /// k >= '2024-01-01' AND k < '2025-01-01'
812    /// ```
813    ///
814    /// which is a simpler and a more canonical form, making it easier for other
815    /// optimizer passes to recognize and apply further transformations.
816    ///
817    /// # Examples
818    ///
819    /// Case 1:
820    ///
821    /// Original:
822    /// ```sql
823    /// date_part('YEAR', k) = 2024 AND k >= '2024-06-01'
824    /// ```
825    ///
826    /// After preimage rewrite:
827    /// ```sql
828    /// k >= '2024-01-01' AND k < '2025-01-01' AND k >= '2024-06-01'
829    /// ```
830    ///
831    /// Since this form is much simpler, the optimizer can combine and simplify
832    /// sub-expressions further into:
833    /// ```sql
834    /// k >= '2024-06-01' AND k < '2025-01-01'
835    /// ```
836    ///
837    /// Case 2:
838    ///
839    /// For min/max pruning, simpler predicates such as:
840    /// ```sql
841    /// k >= '2024-01-01' AND k < '2025-01-01'
842    /// ```
843    /// are much easier for the pruner to reason about. See [PruningPredicate]
844    /// for the backgrounds of predicate pruning.
845    ///
846    /// The trade-off with the preimage rewrite is that evaluating the rewritten
847    /// form might be slightly more expensive than evaluating the original
848    /// expression. In practice, this cost is usually outweighed by the more
849    /// aggressive optimization opportunities it enables.
850    ///
851    /// # Half-Open Intervals
852    ///
853    /// The preimage API uses half-open intervals, which makes the rewrite
854    /// easier to implement by avoiding calculations to adjust the upper bound.
855    /// For example, if a function returns its input unchanged and the desired
856    /// output is the single value `5`, a closed interval could be represented
857    /// as `[5, 5]`, but then the rewrite would require adjusting the upper
858    /// bound to `6` to create a proper range predicate. With a half-open
859    /// interval, the same range is represented as `[5, 6)`, which already
860    /// forms a valid predicate.
861    ///
862    /// [PruningPredicate]: https://docs.rs/datafusion/latest/datafusion/physical_optimizer/pruning/struct.PruningPredicate.html
863    /// [ClickHouse Paper]:  https://www.vldb.org/pvldb/vol17/p3731-schulze.pdf
864    /// [image]: https://en.wikipedia.org/wiki/Image_(mathematics)#Image_of_an_element
865    /// [preimage]: https://en.wikipedia.org/wiki/Image_(mathematics)#Inverse_image
866    fn preimage(
867        &self,
868        _args: &[Expr],
869        _lit_expr: &Expr,
870        _info: &SimplifyContext,
871    ) -> Result<PreimageResult> {
872        Ok(PreimageResult::None)
873    }
874
875    /// Returns true if some of this `exprs` subexpressions may not be evaluated
876    /// and thus any side effects (like divide by zero) may not be encountered.
877    ///
878    /// Setting this to true prevents certain optimizations such as common
879    /// subexpression elimination
880    ///
881    /// When overriding this function to return `true`, [ScalarUDFImpl::conditional_arguments] can also be
882    /// overridden to report more accurately which arguments are eagerly evaluated and which ones
883    /// lazily.
884    fn short_circuits(&self) -> bool {
885        false
886    }
887
888    /// Determines which of the arguments passed to this function are evaluated eagerly
889    /// and which may be evaluated lazily.
890    ///
891    /// If this function returns `None`, all arguments are eagerly evaluated.
892    /// Returning `None` is a micro optimization that saves a needless `Vec`
893    /// allocation.
894    ///
895    /// If the function returns `Some`, returns (`eager`, `lazy`) where `eager`
896    /// are the arguments that are always evaluated, and `lazy` are the
897    /// arguments that may be evaluated lazily (i.e. may not be evaluated at all
898    /// in some cases).
899    ///
900    /// Implementations must ensure that the two returned `Vec`s are disjunct,
901    /// and that each argument from `args` is present in one the two `Vec`s.
902    ///
903    /// When overriding this function, [ScalarUDFImpl::short_circuits] must
904    /// be overridden to return `true`.
905    fn conditional_arguments<'a>(
906        &self,
907        args: &'a [Expr],
908    ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
909        if self.short_circuits() {
910            Some((vec![], args.iter().collect()))
911        } else {
912            None
913        }
914    }
915
916    /// Computes the output [`Interval`] for a [`ScalarUDFImpl`], given the input
917    /// intervals.
918    ///
919    /// # Parameters
920    ///
921    /// * `children` are the intervals for the children (inputs) of this function.
922    ///
923    /// # Example
924    ///
925    /// If the function is `ABS(a)`, and the input interval is `a: [-3, 2]`,
926    /// then the output interval would be `[0, 3]`.
927    fn evaluate_bounds(&self, _input: &[&Interval]) -> Result<Interval> {
928        // We cannot assume the input datatype is the same of output type.
929        Interval::make_unbounded(&DataType::Null)
930    }
931
932    /// Updates bounds for child expressions, given a known [`Interval`]s for this
933    /// function.
934    ///
935    /// This function is used to propagate constraints down through an
936    /// expression tree.
937    ///
938    /// # Parameters
939    ///
940    /// * `interval` is the currently known interval for this function.
941    /// * `inputs` are the current intervals for the inputs (children) of this function.
942    ///
943    /// # Returns
944    ///
945    /// A `Vec` of new intervals for the children, in order.
946    ///
947    /// If constraint propagation reveals an infeasibility for any child, returns
948    /// [`None`]. If none of the children intervals change as a result of
949    /// propagation, may return an empty vector instead of cloning `children`.
950    /// This is the default (and conservative) return value.
951    ///
952    /// # Example
953    ///
954    /// If the function is `ABS(a)`, the current `interval` is `[4, 5]` and the
955    /// input `a` is given as `[-7, 3]`, then propagation would return `[-5, 3]`.
956    fn propagate_constraints(
957        &self,
958        _interval: &Interval,
959        _inputs: &[&Interval],
960    ) -> Result<Option<Vec<Interval>>> {
961        Ok(Some(vec![]))
962    }
963
964    /// Calculates the [`SortProperties`] of this function based on its children's properties.
965    fn output_ordering(&self, inputs: &[ExprProperties]) -> Result<SortProperties> {
966        if !self.preserves_lex_ordering(inputs)? {
967            return Ok(SortProperties::Unordered);
968        }
969
970        let Some(first_order) = inputs.first().map(|p| &p.sort_properties) else {
971            return Ok(SortProperties::Singleton);
972        };
973
974        if inputs
975            .iter()
976            .skip(1)
977            .all(|input| &input.sort_properties == first_order)
978        {
979            Ok(*first_order)
980        } else {
981            Ok(SortProperties::Unordered)
982        }
983    }
984
985    /// Returns true if the function preserves lexicographical ordering based on
986    /// the input ordering.
987    ///
988    /// See [`ExprProperties::preserves_lex_ordering`] for more details
989    fn preserves_lex_ordering(&self, _inputs: &[ExprProperties]) -> Result<bool> {
990        Ok(false)
991    }
992
993    /// Returns true if the function is strictly order-preserving with respect
994    /// to its `Ordered` inputs, i.e. `a.cmp(b) == f(a).cmp(f(b))`.
995    ///
996    /// See [`ExprProperties::strictly_order_preserving`] for more details
997    fn strictly_order_preserving(&self, _inputs: &[ExprProperties]) -> Result<bool> {
998        Ok(false)
999    }
1000
1001    /// Coerce arguments of a function call to types that the function can evaluate.
1002    ///
1003    /// This function is only called if [`ScalarUDFImpl::signature`] returns
1004    /// [`crate::TypeSignature::UserDefined`]. Most UDFs should return one of
1005    /// the other variants of [`TypeSignature`] which handle common cases.
1006    ///
1007    /// See the [type coercion module](crate::type_coercion)
1008    /// documentation for more details on type coercion
1009    ///
1010    /// [`TypeSignature`]: crate::TypeSignature
1011    ///
1012    /// For example, if your function requires a floating point arguments, but the user calls
1013    /// it like `my_func(1::int)` (i.e. with `1` as an integer), coerce_types can return `[DataType::Float64]`
1014    /// to ensure the argument is converted to `1::double`
1015    ///
1016    /// # Parameters
1017    /// * `arg_types`: The argument types of the arguments  this function with
1018    ///
1019    /// # Return value
1020    /// A Vec the same length as `arg_types`. DataFusion will `CAST` the function call
1021    /// arguments to these specific types.
1022    fn coerce_types(&self, _arg_types: &[DataType]) -> Result<Vec<DataType>> {
1023        not_impl_err!("Function {} does not implement coerce_types", self.name())
1024    }
1025
1026    /// For struct-producing functions, return how output fields map to input
1027    /// arguments. This enables the optimizer to propagate orderings through
1028    /// struct projections.
1029    ///
1030    /// `literal_args[i]` is `Some(value)` if argument `i` is a known literal,
1031    /// allowing extraction of field names from arguments like
1032    /// `named_struct('field_name', value, ...)`.
1033    ///
1034    /// For example, `named_struct('a', col1, 'b', col2)` would return a
1035    /// mapping indicating that output field `'a'` (accessed via
1036    /// `get_field(output, 'a')`) corresponds to input argument `col1` at
1037    /// index 1, and field `'b'` corresponds to `col2` at index 3.
1038    fn struct_field_mapping(
1039        &self,
1040        _literal_args: &[Option<ScalarValue>],
1041    ) -> Option<StructFieldMapping> {
1042        None
1043    }
1044
1045    /// Returns the documentation for this Scalar UDF.
1046    ///
1047    /// Documentation can be accessed programmatically as well as generating
1048    /// publicly facing documentation.
1049    fn documentation(&self) -> Option<&Documentation> {
1050        None
1051    }
1052
1053    /// Returns placement information for this function.
1054    ///
1055    /// This is used by optimizers to make decisions about expression placement,
1056    /// such as whether to push expressions down through projections.
1057    ///
1058    /// The default implementation returns [`ExpressionPlacement::KeepInPlace`],
1059    /// meaning the expression should be kept where it is in the plan.
1060    ///
1061    /// Override this method to indicate that the function can be pushed down
1062    /// closer to the data source.
1063    fn placement(&self, _args: &[ExpressionPlacement]) -> ExpressionPlacement {
1064        ExpressionPlacement::KeepInPlace
1065    }
1066}
1067
1068impl dyn ScalarUDFImpl {
1069    /// Returns `true` if the implementation is of type `T`.
1070    ///
1071    /// Works correctly when called on `Arc<dyn ScalarUDFImpl>` via auto-deref.
1072    pub fn is<T: ScalarUDFImpl>(&self) -> bool {
1073        (self as &dyn Any).is::<T>()
1074    }
1075
1076    /// Attempts to downcast to a concrete type `T`, returning `None` if the
1077    /// implementation is not of that type.
1078    ///
1079    /// Works correctly when called on `Arc<dyn ScalarUDFImpl>` via auto-deref,
1080    /// unlike `(&arc as &dyn Any).downcast_ref::<T>()` which would attempt to
1081    /// downcast the `Arc` itself.
1082    pub fn downcast_ref<T: ScalarUDFImpl>(&self) -> Option<&T> {
1083        (self as &dyn Any).downcast_ref()
1084    }
1085}
1086
1087/// ScalarUDF that adds an alias to the underlying function. It is better to
1088/// implement [`ScalarUDFImpl`], which supports aliases, directly if possible.
1089#[derive(Debug, PartialEq, Eq, Hash)]
1090struct AliasedScalarUDFImpl {
1091    inner: UdfEq<Arc<dyn ScalarUDFImpl>>,
1092    aliases: Vec<String>,
1093}
1094
1095impl AliasedScalarUDFImpl {
1096    pub fn new(
1097        inner: Arc<dyn ScalarUDFImpl>,
1098        new_aliases: impl IntoIterator<Item = &'static str>,
1099    ) -> Self {
1100        let mut aliases = inner.aliases().to_vec();
1101        aliases.extend(new_aliases.into_iter().map(|s| s.to_string()));
1102        Self {
1103            inner: inner.into(),
1104            aliases,
1105        }
1106    }
1107}
1108
1109#[warn(clippy::missing_trait_methods)] // Delegates, so it should implement every single trait method
1110impl ScalarUDFImpl for AliasedScalarUDFImpl {
1111    fn name(&self) -> &str {
1112        self.inner.name()
1113    }
1114
1115    fn display_name(&self, args: &[Expr]) -> Result<String> {
1116        #[expect(deprecated)]
1117        self.inner.display_name(args)
1118    }
1119
1120    fn schema_name(&self, args: &[Expr]) -> Result<String> {
1121        self.inner.schema_name(args)
1122    }
1123
1124    fn signature(&self) -> &Signature {
1125        self.inner.signature()
1126    }
1127
1128    fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
1129        self.inner.return_type(arg_types)
1130    }
1131
1132    fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
1133        self.inner.return_field_from_args(args)
1134    }
1135
1136    fn is_nullable(&self, args: &[Expr], schema: &dyn ExprSchema) -> bool {
1137        #[expect(deprecated)]
1138        self.inner.is_nullable(args, schema)
1139    }
1140
1141    fn is_strict(&self) -> bool {
1142        self.inner.is_strict()
1143    }
1144
1145    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
1146        self.inner.invoke_with_args(args)
1147    }
1148
1149    fn with_updated_config(&self, _config: &ConfigOptions) -> Option<ScalarUDF> {
1150        None
1151    }
1152
1153    fn aliases(&self) -> &[String] {
1154        &self.aliases
1155    }
1156
1157    fn simplify(
1158        &self,
1159        args: Vec<Expr>,
1160        info: &SimplifyContext,
1161    ) -> Result<ExprSimplifyResult> {
1162        self.inner.simplify(args, info)
1163    }
1164
1165    fn preimage(
1166        &self,
1167        args: &[Expr],
1168        lit_expr: &Expr,
1169        info: &SimplifyContext,
1170    ) -> Result<PreimageResult> {
1171        self.inner.preimage(args, lit_expr, info)
1172    }
1173
1174    fn conditional_arguments<'a>(
1175        &self,
1176        args: &'a [Expr],
1177    ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
1178        self.inner.conditional_arguments(args)
1179    }
1180
1181    fn short_circuits(&self) -> bool {
1182        self.inner.short_circuits()
1183    }
1184
1185    fn evaluate_bounds(&self, input: &[&Interval]) -> Result<Interval> {
1186        self.inner.evaluate_bounds(input)
1187    }
1188
1189    fn propagate_constraints(
1190        &self,
1191        interval: &Interval,
1192        inputs: &[&Interval],
1193    ) -> Result<Option<Vec<Interval>>> {
1194        self.inner.propagate_constraints(interval, inputs)
1195    }
1196
1197    fn struct_field_mapping(
1198        &self,
1199        literal_args: &[Option<ScalarValue>],
1200    ) -> Option<StructFieldMapping> {
1201        self.inner.struct_field_mapping(literal_args)
1202    }
1203
1204    fn output_ordering(&self, inputs: &[ExprProperties]) -> Result<SortProperties> {
1205        self.inner.output_ordering(inputs)
1206    }
1207
1208    fn preserves_lex_ordering(&self, inputs: &[ExprProperties]) -> Result<bool> {
1209        self.inner.preserves_lex_ordering(inputs)
1210    }
1211
1212    fn strictly_order_preserving(&self, inputs: &[ExprProperties]) -> Result<bool> {
1213        self.inner.strictly_order_preserving(inputs)
1214    }
1215
1216    fn coerce_types(&self, arg_types: &[DataType]) -> Result<Vec<DataType>> {
1217        self.inner.coerce_types(arg_types)
1218    }
1219
1220    fn documentation(&self) -> Option<&Documentation> {
1221        self.inner.documentation()
1222    }
1223
1224    fn placement(&self, args: &[ExpressionPlacement]) -> ExpressionPlacement {
1225        self.inner.placement(args)
1226    }
1227}
1228
1229#[cfg(test)]
1230mod tests {
1231    use super::*;
1232    use datafusion_expr_common::signature::Volatility;
1233    use std::hash::DefaultHasher;
1234
1235    #[derive(Debug, PartialEq, Eq, Hash)]
1236    struct TestScalarUDFImpl {
1237        name: &'static str,
1238        field: &'static str,
1239        signature: Signature,
1240    }
1241    impl ScalarUDFImpl for TestScalarUDFImpl {
1242        fn name(&self) -> &str {
1243            self.name
1244        }
1245
1246        fn signature(&self) -> &Signature {
1247            &self.signature
1248        }
1249
1250        fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
1251            unimplemented!()
1252        }
1253
1254        fn invoke_with_args(&self, _args: ScalarFunctionArgs) -> Result<ColumnarValue> {
1255            unimplemented!()
1256        }
1257    }
1258
1259    // PartialEq and Hash must be consistent, and also PartialEq and PartialOrd
1260    // must be consistent, so they are tested together.
1261    #[test]
1262    fn test_partial_eq_hash_and_partial_ord() {
1263        // A parameterized function
1264        let f = test_func("foo", "a");
1265
1266        // Same like `f`, different instance
1267        let f2 = test_func("foo", "a");
1268        assert_eq!(f, f2);
1269        assert_eq!(hash(&f), hash(&f2));
1270        assert_eq!(f.partial_cmp(&f2), Some(Ordering::Equal));
1271
1272        // Different parameter
1273        let b = test_func("foo", "b");
1274        assert_ne!(f, b);
1275        assert_ne!(hash(&f), hash(&b)); // hash can collide for different values but does not collide in this test
1276        assert_eq!(f.partial_cmp(&b), None);
1277
1278        // Different name
1279        let o = test_func("other", "a");
1280        assert_ne!(f, o);
1281        assert_ne!(hash(&f), hash(&o)); // hash can collide for different values but does not collide in this test
1282        assert_eq!(f.partial_cmp(&o), Some(Ordering::Less));
1283
1284        // Different name and parameter
1285        assert_ne!(b, o);
1286        assert_ne!(hash(&b), hash(&o)); // hash can collide for different values but does not collide in this test
1287        assert_eq!(b.partial_cmp(&o), Some(Ordering::Less));
1288    }
1289
1290    fn test_func(name: &'static str, parameter: &'static str) -> ScalarUDF {
1291        ScalarUDF::from(TestScalarUDFImpl {
1292            name,
1293            field: parameter,
1294            signature: Signature::any(1, Volatility::Immutable),
1295        })
1296    }
1297
1298    fn hash<T: Hash>(value: &T) -> u64 {
1299        let hasher = &mut DefaultHasher::new();
1300        value.hash(hasher);
1301        hasher.finish()
1302    }
1303}