datafusion_expr_common/
signature.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//! Function signatures: [`Volatility`], [`Signature`] and [`TypeSignature`]
19
20use std::fmt::Display;
21use std::hash::Hash;
22
23use crate::type_coercion::aggregates::NUMERICS;
24use arrow::datatypes::{DataType, Decimal128Type, DecimalType, IntervalUnit, TimeUnit};
25use datafusion_common::types::{LogicalType, LogicalTypeRef, NativeType};
26use datafusion_common::utils::ListCoercion;
27use datafusion_common::{internal_err, plan_err, Result};
28use indexmap::IndexSet;
29use itertools::Itertools;
30
31/// Constant that is used as a placeholder for any valid timezone.
32/// This is used where a function can accept a timestamp type with any
33/// valid timezone, it exists to avoid the need to enumerate all possible
34/// timezones. See [`TypeSignature`] for more details.
35///
36/// Type coercion always ensures that functions will be executed using
37/// timestamp arrays that have a valid time zone. Functions must never
38/// return results with this timezone.
39pub const TIMEZONE_WILDCARD: &str = "+TZ";
40
41/// Constant that is used as a placeholder for any valid fixed size list.
42/// This is used where a function can accept a fixed size list type with any
43/// valid length. It exists to avoid the need to enumerate all possible fixed size list lengths.
44pub const FIXED_SIZE_LIST_WILDCARD: i32 = i32::MIN;
45
46/// How a function's output changes with respect to a fixed input
47///
48/// The volatility of a function determines eligibility for certain
49/// optimizations. You should always define your function to have the strictest
50/// possible volatility to maximize performance and avoid unexpected
51/// results.
52#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
53pub enum Volatility {
54    /// Always returns the same output when given the same input.
55    ///
56    /// DataFusion will inline immutable functions during planning.
57    ///
58    /// For example, the `abs` function is immutable, so `abs(-1)` will be
59    /// evaluated and replaced  with `1` during planning rather than invoking
60    /// the function at runtime.
61    Immutable,
62    /// May return different values given the same input across different
63    /// queries but must return the same value for a given input within a query.
64    ///
65    /// For example, the `now()` function is stable, because the query `select
66    /// col1, now() from t1`, will return different results each time it is run,
67    /// but within the same query, the output of the `now()` function has the
68    /// same value for each output row.
69    ///
70    /// DataFusion will inline `Stable` functions when possible. For example,
71    /// `Stable` functions are inlined when planning a query for execution, but
72    /// not in View definitions or prepared statements.
73    Stable,
74    /// May change the return value from evaluation to evaluation.
75    ///
76    /// Multiple invocations of a volatile function may return different results
77    /// when used in the same query on different rows. An example of this is the
78    /// `random()` function.
79    ///
80    /// DataFusion can not evaluate such functions during planning or push these
81    /// predicates into scans. In the query `select col1, random() from t1`,
82    /// `random()` function will be evaluated for each output row, resulting in
83    /// a unique random value for each row.
84    Volatile,
85}
86
87/// Represents the arity (number of arguments) of a function signature
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89pub enum Arity {
90    /// Fixed number of arguments
91    Fixed(usize),
92    /// Variable number of arguments (e.g., Variadic, VariadicAny, UserDefined)
93    Variable,
94}
95
96/// The types of arguments for which a function has implementations.
97///
98/// [`TypeSignature`] **DOES NOT** define the types that a user query could call the
99/// function with. DataFusion will automatically coerce (cast) argument types to
100/// one of the supported function signatures, if possible.
101///
102/// # Overview
103/// Functions typically provide implementations for a small number of different
104/// argument [`DataType`]s, rather than all possible combinations. If a user
105/// calls a function with arguments that do not match any of the declared types,
106/// DataFusion will attempt to automatically coerce (add casts to) function
107/// arguments so they match the [`TypeSignature`]. See the [`type_coercion`] module
108/// for more details
109///
110/// # Example: Numeric Functions
111/// For example, a function like `cos` may only provide an implementation for
112/// [`DataType::Float64`]. When users call `cos` with a different argument type,
113/// such as `cos(int_column)`, and type coercion automatically adds a cast such
114/// as `cos(CAST int_column AS DOUBLE)` during planning.
115///
116/// [`type_coercion`]: crate::type_coercion
117///
118/// ## Example: Strings
119///
120/// There are several different string types in Arrow, such as
121/// [`DataType::Utf8`], [`DataType::LargeUtf8`], and [`DataType::Utf8View`].
122///
123/// Some functions may have specialized implementations for these types, while others
124/// may be able to handle only one of them. For example, a function that
125/// only works with [`DataType::Utf8View`] would have the following signature:
126///
127/// ```
128/// # use arrow::datatypes::DataType;
129/// # use datafusion_expr_common::signature::{TypeSignature};
130/// // Declares the function must be invoked with a single argument of type `Utf8View`.
131/// // if a user calls the function with `Utf8` or `LargeUtf8`, DataFusion will
132/// // automatically add a cast to `Utf8View` during planning.
133/// let type_signature = TypeSignature::Exact(vec![DataType::Utf8View]);
134/// ```
135///
136/// # Example: Timestamps
137///
138/// Types to match are represented using Arrow's [`DataType`].  [`DataType::Timestamp`] has an optional variable
139/// timezone specification. To specify a function can handle a timestamp with *ANY* timezone, use
140/// the [`TIMEZONE_WILDCARD`]. For example:
141///
142/// ```
143/// # use arrow::datatypes::{DataType, TimeUnit};
144/// # use datafusion_expr_common::signature::{TIMEZONE_WILDCARD, TypeSignature};
145/// let type_signature = TypeSignature::Exact(vec![
146///     // A nanosecond precision timestamp with ANY timezone
147///     // matches  Timestamp(Nanosecond, Some("+0:00"))
148///     // matches  Timestamp(Nanosecond, Some("+5:00"))
149///     // does not match  Timestamp(Nanosecond, None)
150///     DataType::Timestamp(TimeUnit::Nanosecond, Some(TIMEZONE_WILDCARD.into())),
151/// ]);
152/// ```
153#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
154pub enum TypeSignature {
155    /// One or more arguments of a common type out of a list of valid types.
156    ///
157    /// For functions that take no arguments (e.g. `random()` see [`TypeSignature::Nullary`]).
158    ///
159    /// # Examples
160    ///
161    /// A function such as `concat` is `Variadic(vec![DataType::Utf8,
162    /// DataType::LargeUtf8])`
163    Variadic(Vec<DataType>),
164    /// The acceptable signature and coercions rules are special for this
165    /// function.
166    ///
167    /// If this signature is specified,
168    /// DataFusion will call [`ScalarUDFImpl::coerce_types`] to prepare argument types.
169    ///
170    /// [`ScalarUDFImpl::coerce_types`]: https://docs.rs/datafusion/latest/datafusion/logical_expr/trait.ScalarUDFImpl.html#method.coerce_types
171    UserDefined,
172    /// One or more arguments with arbitrary types
173    VariadicAny,
174    /// One or more arguments of an arbitrary but equal type out of a list of valid types.
175    ///
176    /// # Examples
177    ///
178    /// 1. A function of one argument of f64 is `Uniform(1, vec![DataType::Float64])`
179    /// 2. A function of one argument of f64 or f32 is `Uniform(1, vec![DataType::Float32, DataType::Float64])`
180    Uniform(usize, Vec<DataType>),
181    /// One or more arguments with exactly the specified types in order.
182    ///
183    /// For functions that take no arguments (e.g. `random()`) use [`TypeSignature::Nullary`].
184    Exact(Vec<DataType>),
185    /// One or more arguments belonging to the [`TypeSignatureClass`], in order.
186    ///
187    /// [`Coercion`] contains not only the desired type but also the allowed
188    /// casts. For example, if you expect a function has string type, but you
189    /// also allow it to be casted from binary type.
190    ///
191    /// For functions that take no arguments (e.g. `random()`) see [`TypeSignature::Nullary`].
192    Coercible(Vec<Coercion>),
193    /// One or more arguments coercible to a single, comparable type.
194    ///
195    /// Each argument will be coerced to a single type using the
196    /// coercion rules described in [`comparison_coercion_numeric`].
197    ///
198    /// # Examples
199    ///
200    /// If the `nullif(1, 2)` function is called with `i32` and `i64` arguments
201    /// the types will both be coerced to `i64` before the function is invoked.
202    ///
203    /// If the `nullif('1', 2)` function is called with `Utf8` and `i64` arguments
204    /// the types will both be coerced to `Utf8` before the function is invoked.
205    ///
206    /// Note:
207    /// - For functions that take no arguments (e.g. `random()` see [`TypeSignature::Nullary`]).
208    /// - If all arguments have type [`DataType::Null`], they are coerced to `Utf8`
209    ///
210    /// [`comparison_coercion_numeric`]: crate::type_coercion::binary::comparison_coercion_numeric
211    Comparable(usize),
212    /// One or more arguments of arbitrary types.
213    ///
214    /// For functions that take no arguments (e.g. `random()`) use [`TypeSignature::Nullary`].
215    Any(usize),
216    /// Matches exactly one of a list of [`TypeSignature`]s.
217    ///
218    /// Coercion is attempted to match the signatures in order, and stops after
219    /// the first success, if any.
220    ///
221    /// # Examples
222    ///
223    /// Since `make_array` takes 0 or more arguments with arbitrary types, its `TypeSignature`
224    /// is `OneOf(vec![Any(0), VariadicAny])`.
225    OneOf(Vec<TypeSignature>),
226    /// A function that has an [`ArrayFunctionSignature`]
227    ArraySignature(ArrayFunctionSignature),
228    /// One or more arguments of numeric types, coerced to a common numeric type.
229    ///
230    /// See [`NativeType::is_numeric`] to know which type is considered numeric
231    ///
232    /// For functions that take no arguments (e.g. `random()`) use [`TypeSignature::Nullary`].
233    ///
234    /// [`NativeType::is_numeric`]: datafusion_common::types::NativeType::is_numeric
235    Numeric(usize),
236    /// One or arguments of all the same string types.
237    ///
238    /// The precedence of type from high to low is Utf8View, LargeUtf8 and Utf8.
239    /// Null is considered as `Utf8` by default
240    /// Dictionary with string value type is also handled.
241    ///
242    /// For example, if a function is called with (utf8, large_utf8), all
243    /// arguments will be coerced to  `LargeUtf8`
244    ///
245    /// For functions that take no arguments (e.g. `random()` use [`TypeSignature::Nullary`]).
246    String(usize),
247    /// No arguments
248    Nullary,
249}
250
251impl TypeSignature {
252    #[inline]
253    pub fn is_one_of(&self) -> bool {
254        matches!(self, TypeSignature::OneOf(_))
255    }
256
257    /// Returns the arity (expected number of arguments) for this type signature.
258    ///
259    /// Returns `Arity::Fixed(n)` for signatures with a specific argument count,
260    /// or `Arity::Variable` for variable-arity signatures like `Variadic`, `VariadicAny`, `UserDefined`.
261    ///
262    /// # Examples
263    ///
264    /// ```
265    /// # use datafusion_expr_common::signature::{TypeSignature, Arity};
266    /// # use arrow::datatypes::DataType;
267    /// // Exact signature has fixed arity
268    /// let sig = TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]);
269    /// assert_eq!(sig.arity(), Arity::Fixed(2));
270    ///
271    /// // Variadic signature has variable arity
272    /// let sig = TypeSignature::VariadicAny;
273    /// assert_eq!(sig.arity(), Arity::Variable);
274    /// ```
275    pub fn arity(&self) -> Arity {
276        match self {
277            TypeSignature::Exact(types) => Arity::Fixed(types.len()),
278            TypeSignature::Uniform(count, _) => Arity::Fixed(*count),
279            TypeSignature::Numeric(count) => Arity::Fixed(*count),
280            TypeSignature::String(count) => Arity::Fixed(*count),
281            TypeSignature::Comparable(count) => Arity::Fixed(*count),
282            TypeSignature::Any(count) => Arity::Fixed(*count),
283            TypeSignature::Coercible(types) => Arity::Fixed(types.len()),
284            TypeSignature::Nullary => Arity::Fixed(0),
285            TypeSignature::ArraySignature(ArrayFunctionSignature::Array {
286                arguments,
287                ..
288            }) => Arity::Fixed(arguments.len()),
289            TypeSignature::ArraySignature(ArrayFunctionSignature::RecursiveArray) => {
290                Arity::Fixed(1)
291            }
292            TypeSignature::ArraySignature(ArrayFunctionSignature::MapArray) => {
293                Arity::Fixed(1)
294            }
295            TypeSignature::OneOf(variants) => {
296                // If any variant is Variable, the whole OneOf is Variable
297                let has_variable = variants.iter().any(|v| v.arity() == Arity::Variable);
298                if has_variable {
299                    return Arity::Variable;
300                }
301                // Otherwise, get max arity from all fixed arity variants
302                let max_arity = variants
303                    .iter()
304                    .filter_map(|v| match v.arity() {
305                        Arity::Fixed(n) => Some(n),
306                        Arity::Variable => None,
307                    })
308                    .max();
309                match max_arity {
310                    Some(n) => Arity::Fixed(n),
311                    None => Arity::Variable,
312                }
313            }
314            TypeSignature::Variadic(_)
315            | TypeSignature::VariadicAny
316            | TypeSignature::UserDefined => Arity::Variable,
317        }
318    }
319}
320
321/// Represents the class of types that can be used in a function signature.
322///
323/// This is used to specify what types are valid for function arguments in a more flexible way than
324/// just listing specific DataTypes. For example, TypeSignatureClass::Timestamp matches any timestamp
325/// type regardless of timezone or precision.
326///
327/// Used primarily with [`TypeSignature::Coercible`] to define function signatures that can accept
328/// arguments that can be coerced to a particular class of types.
329#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Hash)]
330pub enum TypeSignatureClass {
331    Timestamp,
332    Time,
333    Interval,
334    Duration,
335    Native(LogicalTypeRef),
336    Integer,
337    Float,
338    Decimal,
339    Numeric,
340    /// Encompasses both the native Binary as well as arbitrarily sized FixedSizeBinary types
341    Binary,
342}
343
344impl Display for TypeSignatureClass {
345    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
346        write!(f, "TypeSignatureClass::{self:?}")
347    }
348}
349
350impl TypeSignatureClass {
351    /// Get example acceptable types for this `TypeSignatureClass`
352    ///
353    /// This is used for `information_schema` and can be used to generate
354    /// documentation or error messages.
355    fn get_example_types(&self) -> Vec<DataType> {
356        match self {
357            TypeSignatureClass::Native(l) => get_data_types(l.native()),
358            TypeSignatureClass::Timestamp => {
359                vec![
360                    DataType::Timestamp(TimeUnit::Nanosecond, None),
361                    DataType::Timestamp(
362                        TimeUnit::Nanosecond,
363                        Some(TIMEZONE_WILDCARD.into()),
364                    ),
365                ]
366            }
367            TypeSignatureClass::Time => {
368                vec![DataType::Time64(TimeUnit::Nanosecond)]
369            }
370            TypeSignatureClass::Interval => {
371                vec![DataType::Interval(IntervalUnit::DayTime)]
372            }
373            TypeSignatureClass::Duration => {
374                vec![DataType::Duration(TimeUnit::Nanosecond)]
375            }
376            TypeSignatureClass::Integer => {
377                vec![DataType::Int64]
378            }
379            TypeSignatureClass::Binary => {
380                vec![DataType::Binary]
381            }
382            TypeSignatureClass::Decimal => vec![Decimal128Type::DEFAULT_TYPE],
383            TypeSignatureClass::Float => vec![DataType::Float64],
384            TypeSignatureClass::Numeric => vec![
385                DataType::Float64,
386                DataType::Int64,
387                Decimal128Type::DEFAULT_TYPE,
388            ],
389        }
390    }
391
392    /// Does the specified `NativeType` match this type signature class?
393    pub fn matches_native_type(&self, logical_type: &NativeType) -> bool {
394        if logical_type == &NativeType::Null {
395            return true;
396        }
397
398        match self {
399            TypeSignatureClass::Native(t) if t.native() == logical_type => true,
400            TypeSignatureClass::Timestamp if logical_type.is_timestamp() => true,
401            TypeSignatureClass::Time if logical_type.is_time() => true,
402            TypeSignatureClass::Interval if logical_type.is_interval() => true,
403            TypeSignatureClass::Duration if logical_type.is_duration() => true,
404            TypeSignatureClass::Integer if logical_type.is_integer() => true,
405            TypeSignatureClass::Binary if logical_type.is_binary() => true,
406            TypeSignatureClass::Decimal if logical_type.is_decimal() => true,
407            TypeSignatureClass::Float if logical_type.is_float() => true,
408            TypeSignatureClass::Numeric if logical_type.is_numeric() => true,
409            _ => false,
410        }
411    }
412
413    /// What type would `origin_type` be casted to when casting to the specified native type?
414    pub fn default_casted_type(
415        &self,
416        native_type: &NativeType,
417        origin_type: &DataType,
418    ) -> Result<DataType> {
419        match self {
420            TypeSignatureClass::Native(logical_type) => {
421                logical_type.native().default_cast_for(origin_type)
422            }
423            // If the given type is already a timestamp, we don't change the unit and timezone
424            TypeSignatureClass::Timestamp if native_type.is_timestamp() => {
425                Ok(origin_type.to_owned())
426            }
427            TypeSignatureClass::Time if native_type.is_time() => {
428                Ok(origin_type.to_owned())
429            }
430            TypeSignatureClass::Interval if native_type.is_interval() => {
431                Ok(origin_type.to_owned())
432            }
433            TypeSignatureClass::Duration if native_type.is_duration() => {
434                Ok(origin_type.to_owned())
435            }
436            TypeSignatureClass::Integer if native_type.is_integer() => {
437                Ok(origin_type.to_owned())
438            }
439            TypeSignatureClass::Binary if native_type.is_binary() => {
440                Ok(origin_type.to_owned())
441            }
442            TypeSignatureClass::Decimal if native_type.is_decimal() => {
443                Ok(origin_type.to_owned())
444            }
445            TypeSignatureClass::Float if native_type.is_float() => {
446                Ok(origin_type.to_owned())
447            }
448            TypeSignatureClass::Numeric if native_type.is_numeric() => {
449                Ok(origin_type.to_owned())
450            }
451            _ if native_type.is_null() => Ok(origin_type.to_owned()),
452            _ => internal_err!("May miss the matching logic in `matches_native_type`"),
453        }
454    }
455}
456
457#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
458pub enum ArrayFunctionSignature {
459    /// A function takes at least one List/LargeList/FixedSizeList argument.
460    Array {
461        /// A full list of the arguments accepted by this function.
462        arguments: Vec<ArrayFunctionArgument>,
463        /// Additional information about how array arguments should be coerced.
464        array_coercion: Option<ListCoercion>,
465    },
466    /// A function takes a single argument that must be a List/LargeList/FixedSizeList
467    /// which gets coerced to List, with element type recursively coerced to List too if it is list-like.
468    RecursiveArray,
469    /// Specialized Signature for MapArray
470    /// The function takes a single argument that must be a MapArray
471    MapArray,
472}
473
474impl Display for ArrayFunctionSignature {
475    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
476        match self {
477            ArrayFunctionSignature::Array { arguments, .. } => {
478                for (idx, argument) in arguments.iter().enumerate() {
479                    write!(f, "{argument}")?;
480                    if idx != arguments.len() - 1 {
481                        write!(f, ", ")?;
482                    }
483                }
484                Ok(())
485            }
486            ArrayFunctionSignature::RecursiveArray => {
487                write!(f, "recursive_array")
488            }
489            ArrayFunctionSignature::MapArray => {
490                write!(f, "map_array")
491            }
492        }
493    }
494}
495
496#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
497pub enum ArrayFunctionArgument {
498    /// A non-list or list argument. The list dimensions should be one less than the Array's list
499    /// dimensions.
500    Element,
501    /// An Int64 index argument.
502    Index,
503    /// An argument of type List/LargeList/FixedSizeList. All Array arguments must be coercible
504    /// to the same type.
505    Array,
506    // A Utf8 argument.
507    String,
508}
509
510impl Display for ArrayFunctionArgument {
511    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
512        match self {
513            ArrayFunctionArgument::Element => {
514                write!(f, "element")
515            }
516            ArrayFunctionArgument::Index => {
517                write!(f, "index")
518            }
519            ArrayFunctionArgument::Array => {
520                write!(f, "array")
521            }
522            ArrayFunctionArgument::String => {
523                write!(f, "string")
524            }
525        }
526    }
527}
528
529impl TypeSignature {
530    pub fn to_string_repr(&self) -> Vec<String> {
531        match self {
532            TypeSignature::Nullary => {
533                vec!["NullAry()".to_string()]
534            }
535            TypeSignature::Variadic(types) => {
536                vec![format!("{}, ..", Self::join_types(types, "/"))]
537            }
538            TypeSignature::Uniform(arg_count, valid_types) => {
539                vec![
540                    std::iter::repeat_n(Self::join_types(valid_types, "/"), *arg_count)
541                        .collect::<Vec<String>>()
542                        .join(", "),
543                ]
544            }
545            TypeSignature::String(num) => {
546                vec![format!("String({num})")]
547            }
548            TypeSignature::Numeric(num) => {
549                vec![format!("Numeric({num})")]
550            }
551            TypeSignature::Comparable(num) => {
552                vec![format!("Comparable({num})")]
553            }
554            TypeSignature::Coercible(coercions) => {
555                vec![Self::join_types(coercions, ", ")]
556            }
557            TypeSignature::Exact(types) => {
558                vec![Self::join_types(types, ", ")]
559            }
560            TypeSignature::Any(arg_count) => {
561                vec![std::iter::repeat_n("Any", *arg_count)
562                    .collect::<Vec<&str>>()
563                    .join(", ")]
564            }
565            TypeSignature::UserDefined => {
566                vec!["UserDefined".to_string()]
567            }
568            TypeSignature::VariadicAny => vec!["Any, .., Any".to_string()],
569            TypeSignature::OneOf(sigs) => {
570                sigs.iter().flat_map(|s| s.to_string_repr()).collect()
571            }
572            TypeSignature::ArraySignature(array_signature) => {
573                vec![array_signature.to_string()]
574            }
575        }
576    }
577
578    /// Return string representation of the function signature with parameter names.
579    ///
580    /// This method is similar to [`Self::to_string_repr`] but uses parameter names
581    /// instead of types when available. This is useful for generating more helpful
582    /// error messages.
583    ///
584    /// # Arguments
585    /// * `parameter_names` - Optional slice of parameter names. When provided, these
586    ///   names will be used instead of type names in the output.
587    ///
588    /// # Examples
589    /// ```
590    /// # use datafusion_expr_common::signature::TypeSignature;
591    /// # use arrow::datatypes::DataType;
592    /// let sig = TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]);
593    ///
594    /// // Without names: shows types only
595    /// assert_eq!(sig.to_string_repr_with_names(None), vec!["Int32, Utf8"]);
596    ///
597    /// // With names: shows parameter names with types
598    /// assert_eq!(
599    ///     sig.to_string_repr_with_names(Some(&["id".to_string(), "name".to_string()])),
600    ///     vec!["id: Int32, name: Utf8"]
601    /// );
602    /// ```
603    pub fn to_string_repr_with_names(
604        &self,
605        parameter_names: Option<&[String]>,
606    ) -> Vec<String> {
607        match self {
608            TypeSignature::Exact(types) => {
609                if let Some(names) = parameter_names {
610                    vec![names
611                        .iter()
612                        .zip(types.iter())
613                        .map(|(name, typ)| format!("{name}: {typ}"))
614                        .collect::<Vec<_>>()
615                        .join(", ")]
616                } else {
617                    vec![Self::join_types(types, ", ")]
618                }
619            }
620            TypeSignature::Any(count) => {
621                if let Some(names) = parameter_names {
622                    vec![names
623                        .iter()
624                        .take(*count)
625                        .map(|name| format!("{name}: Any"))
626                        .collect::<Vec<_>>()
627                        .join(", ")]
628                } else {
629                    vec![std::iter::repeat_n("Any", *count)
630                        .collect::<Vec<&str>>()
631                        .join(", ")]
632                }
633            }
634            TypeSignature::Uniform(count, types) => {
635                if let Some(names) = parameter_names {
636                    let type_str = Self::join_types(types, "/");
637                    vec![names
638                        .iter()
639                        .take(*count)
640                        .map(|name| format!("{name}: {type_str}"))
641                        .collect::<Vec<_>>()
642                        .join(", ")]
643                } else {
644                    self.to_string_repr()
645                }
646            }
647            TypeSignature::Coercible(coercions) => {
648                if let Some(names) = parameter_names {
649                    vec![names
650                        .iter()
651                        .zip(coercions.iter())
652                        .map(|(name, coercion)| format!("{name}: {coercion}"))
653                        .collect::<Vec<_>>()
654                        .join(", ")]
655                } else {
656                    vec![Self::join_types(coercions, ", ")]
657                }
658            }
659            TypeSignature::Comparable(count) => {
660                if let Some(names) = parameter_names {
661                    vec![names
662                        .iter()
663                        .take(*count)
664                        .map(|name| format!("{name}: Comparable"))
665                        .collect::<Vec<_>>()
666                        .join(", ")]
667                } else {
668                    self.to_string_repr()
669                }
670            }
671            TypeSignature::Numeric(count) => {
672                if let Some(names) = parameter_names {
673                    vec![names
674                        .iter()
675                        .take(*count)
676                        .map(|name| format!("{name}: Numeric"))
677                        .collect::<Vec<_>>()
678                        .join(", ")]
679                } else {
680                    self.to_string_repr()
681                }
682            }
683            TypeSignature::String(count) => {
684                if let Some(names) = parameter_names {
685                    vec![names
686                        .iter()
687                        .take(*count)
688                        .map(|name| format!("{name}: String"))
689                        .collect::<Vec<_>>()
690                        .join(", ")]
691                } else {
692                    self.to_string_repr()
693                }
694            }
695            TypeSignature::Nullary => self.to_string_repr(),
696            TypeSignature::ArraySignature(array_sig) => {
697                if let Some(names) = parameter_names {
698                    match array_sig {
699                        ArrayFunctionSignature::Array { arguments, .. } => {
700                            vec![names
701                                .iter()
702                                .zip(arguments.iter())
703                                .map(|(name, arg_type)| format!("{name}: {arg_type}"))
704                                .collect::<Vec<_>>()
705                                .join(", ")]
706                        }
707                        ArrayFunctionSignature::RecursiveArray => {
708                            vec![names
709                                .iter()
710                                .take(1)
711                                .map(|name| format!("{name}: recursive_array"))
712                                .collect::<Vec<_>>()
713                                .join(", ")]
714                        }
715                        ArrayFunctionSignature::MapArray => {
716                            vec![names
717                                .iter()
718                                .take(1)
719                                .map(|name| format!("{name}: map_array"))
720                                .collect::<Vec<_>>()
721                                .join(", ")]
722                        }
723                    }
724                } else {
725                    self.to_string_repr()
726                }
727            }
728            TypeSignature::OneOf(sigs) => sigs
729                .iter()
730                .flat_map(|s| s.to_string_repr_with_names(parameter_names))
731                .collect(),
732            TypeSignature::UserDefined => {
733                if let Some(names) = parameter_names {
734                    vec![names.join(", ")]
735                } else {
736                    self.to_string_repr()
737                }
738            }
739            // Variable arity signatures cannot use parameter names
740            TypeSignature::Variadic(_) | TypeSignature::VariadicAny => {
741                self.to_string_repr()
742            }
743        }
744    }
745
746    /// Helper function to join types with specified delimiter.
747    pub fn join_types<T: Display>(types: &[T], delimiter: &str) -> String {
748        types
749            .iter()
750            .map(|t| t.to_string())
751            .collect::<Vec<String>>()
752            .join(delimiter)
753    }
754
755    /// Check whether 0 input argument is valid for given `TypeSignature`
756    pub fn supports_zero_argument(&self) -> bool {
757        match &self {
758            TypeSignature::Exact(vec) => vec.is_empty(),
759            TypeSignature::Nullary => true,
760            TypeSignature::OneOf(types) => types
761                .iter()
762                .any(|type_sig| type_sig.supports_zero_argument()),
763            _ => false,
764        }
765    }
766
767    /// Returns true if the signature currently supports or used to supported 0
768    /// input arguments in a previous version of DataFusion.
769    pub fn used_to_support_zero_arguments(&self) -> bool {
770        match &self {
771            TypeSignature::Any(num) => *num == 0,
772            _ => self.supports_zero_argument(),
773        }
774    }
775
776    #[deprecated(since = "46.0.0", note = "See get_example_types instead")]
777    pub fn get_possible_types(&self) -> Vec<Vec<DataType>> {
778        self.get_example_types()
779    }
780
781    /// Return example acceptable types for this `TypeSignature`'
782    ///
783    /// Returns a `Vec<DataType>` for each argument to the function
784    ///
785    /// This is used for `information_schema` and can be used to generate
786    /// documentation or error messages.
787    pub fn get_example_types(&self) -> Vec<Vec<DataType>> {
788        match self {
789            TypeSignature::Exact(types) => vec![types.clone()],
790            TypeSignature::OneOf(types) => types
791                .iter()
792                .flat_map(|type_sig| type_sig.get_example_types())
793                .collect(),
794            TypeSignature::Uniform(arg_count, types) => types
795                .iter()
796                .cloned()
797                .map(|data_type| vec![data_type; *arg_count])
798                .collect(),
799            TypeSignature::Coercible(coercions) => coercions
800                .iter()
801                .map(|c| {
802                    let mut all_types: IndexSet<DataType> =
803                        c.desired_type().get_example_types().into_iter().collect();
804
805                    if let Some(implicit_coercion) = c.implicit_coercion() {
806                        let allowed_casts: Vec<DataType> = implicit_coercion
807                            .allowed_source_types
808                            .iter()
809                            .flat_map(|t| t.get_example_types())
810                            .collect();
811                        all_types.extend(allowed_casts);
812                    }
813
814                    all_types.into_iter().collect::<Vec<_>>()
815                })
816                .multi_cartesian_product()
817                .collect(),
818            TypeSignature::Variadic(types) => types
819                .iter()
820                .cloned()
821                .map(|data_type| vec![data_type])
822                .collect(),
823            TypeSignature::Numeric(arg_count) => NUMERICS
824                .iter()
825                .cloned()
826                .map(|numeric_type| vec![numeric_type; *arg_count])
827                .collect(),
828            TypeSignature::String(arg_count) => get_data_types(&NativeType::String)
829                .into_iter()
830                .map(|dt| vec![dt; *arg_count])
831                .collect::<Vec<_>>(),
832            // TODO: Implement for other types
833            TypeSignature::Any(_)
834            | TypeSignature::Comparable(_)
835            | TypeSignature::Nullary
836            | TypeSignature::VariadicAny
837            | TypeSignature::ArraySignature(_)
838            | TypeSignature::UserDefined => vec![],
839        }
840    }
841}
842
843fn get_data_types(native_type: &NativeType) -> Vec<DataType> {
844    match native_type {
845        NativeType::Null => vec![DataType::Null],
846        NativeType::Boolean => vec![DataType::Boolean],
847        NativeType::Int8 => vec![DataType::Int8],
848        NativeType::Int16 => vec![DataType::Int16],
849        NativeType::Int32 => vec![DataType::Int32],
850        NativeType::Int64 => vec![DataType::Int64],
851        NativeType::UInt8 => vec![DataType::UInt8],
852        NativeType::UInt16 => vec![DataType::UInt16],
853        NativeType::UInt32 => vec![DataType::UInt32],
854        NativeType::UInt64 => vec![DataType::UInt64],
855        NativeType::Float16 => vec![DataType::Float16],
856        NativeType::Float32 => vec![DataType::Float32],
857        NativeType::Float64 => vec![DataType::Float64],
858        NativeType::Date => vec![DataType::Date32, DataType::Date64],
859        NativeType::Binary => vec![
860            DataType::Binary,
861            DataType::LargeBinary,
862            DataType::BinaryView,
863        ],
864        NativeType::String => {
865            vec![DataType::Utf8, DataType::LargeUtf8, DataType::Utf8View]
866        }
867        // TODO: support other native types
868        _ => vec![],
869    }
870}
871
872/// Represents type coercion rules for function arguments, specifying both the desired type
873/// and optional implicit coercion rules for source types.
874///
875/// # Examples
876///
877/// ```
878/// use datafusion_common::types::{logical_binary, logical_string, NativeType};
879/// use datafusion_expr_common::signature::{Coercion, TypeSignatureClass};
880///
881/// // Exact coercion that only accepts timestamp types
882/// let exact = Coercion::new_exact(TypeSignatureClass::Timestamp);
883///
884/// // Implicit coercion that accepts string types but can coerce from binary types
885/// let implicit = Coercion::new_implicit(
886///     TypeSignatureClass::Native(logical_string()),
887///     vec![TypeSignatureClass::Native(logical_binary())],
888///     NativeType::String,
889/// );
890/// ```
891///
892/// There are two variants:
893///
894/// * `Exact` - Only accepts arguments that exactly match the desired type
895/// * `Implicit` - Accepts the desired type and can coerce from specified source types
896#[derive(Debug, Clone, Eq, PartialOrd)]
897pub enum Coercion {
898    /// Coercion that only accepts arguments exactly matching the desired type.
899    Exact {
900        /// The required type for the argument
901        desired_type: TypeSignatureClass,
902    },
903
904    /// Coercion that accepts the desired type and can implicitly coerce from other types.
905    Implicit {
906        /// The primary desired type for the argument
907        desired_type: TypeSignatureClass,
908        /// Rules for implicit coercion from other types
909        implicit_coercion: ImplicitCoercion,
910    },
911}
912
913impl Coercion {
914    pub fn new_exact(desired_type: TypeSignatureClass) -> Self {
915        Self::Exact { desired_type }
916    }
917
918    /// Create a new coercion with implicit coercion rules.
919    ///
920    /// `allowed_source_types` defines the possible types that can be coerced to `desired_type`.
921    /// `default_casted_type` is the default type to be used for coercion if we cast from other types via `allowed_source_types`.
922    pub fn new_implicit(
923        desired_type: TypeSignatureClass,
924        allowed_source_types: Vec<TypeSignatureClass>,
925        default_casted_type: NativeType,
926    ) -> Self {
927        Self::Implicit {
928            desired_type,
929            implicit_coercion: ImplicitCoercion {
930                allowed_source_types,
931                default_casted_type,
932            },
933        }
934    }
935
936    pub fn allowed_source_types(&self) -> &[TypeSignatureClass] {
937        match self {
938            Coercion::Exact { .. } => &[],
939            Coercion::Implicit {
940                implicit_coercion, ..
941            } => implicit_coercion.allowed_source_types.as_slice(),
942        }
943    }
944
945    pub fn default_casted_type(&self) -> Option<&NativeType> {
946        match self {
947            Coercion::Exact { .. } => None,
948            Coercion::Implicit {
949                implicit_coercion, ..
950            } => Some(&implicit_coercion.default_casted_type),
951        }
952    }
953
954    pub fn desired_type(&self) -> &TypeSignatureClass {
955        match self {
956            Coercion::Exact { desired_type } => desired_type,
957            Coercion::Implicit { desired_type, .. } => desired_type,
958        }
959    }
960
961    pub fn implicit_coercion(&self) -> Option<&ImplicitCoercion> {
962        match self {
963            Coercion::Exact { .. } => None,
964            Coercion::Implicit {
965                implicit_coercion, ..
966            } => Some(implicit_coercion),
967        }
968    }
969}
970
971impl Display for Coercion {
972    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
973        write!(f, "Coercion({}", self.desired_type())?;
974        if let Some(implicit_coercion) = self.implicit_coercion() {
975            write!(f, ", implicit_coercion={implicit_coercion}",)
976        } else {
977            write!(f, ")")
978        }
979    }
980}
981
982impl PartialEq for Coercion {
983    fn eq(&self, other: &Self) -> bool {
984        self.desired_type() == other.desired_type()
985            && self.implicit_coercion() == other.implicit_coercion()
986    }
987}
988
989impl Hash for Coercion {
990    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
991        self.desired_type().hash(state);
992        self.implicit_coercion().hash(state);
993    }
994}
995
996/// Defines rules for implicit type coercion, specifying which source types can be
997/// coerced and the default type to use when coercing.
998///
999/// This is used by functions to specify which types they can accept via implicit
1000/// coercion in addition to their primary desired type.
1001///
1002/// # Examples
1003///
1004/// ```
1005/// use arrow::datatypes::TimeUnit;
1006///
1007/// use datafusion_expr_common::signature::{Coercion, ImplicitCoercion, TypeSignatureClass};
1008/// use datafusion_common::types::{NativeType, logical_binary};
1009///
1010/// // Allow coercing from binary types to timestamp, coerce to specific timestamp unit and timezone
1011/// let implicit = Coercion::new_implicit(
1012///     TypeSignatureClass::Timestamp,
1013///     vec![TypeSignatureClass::Native(logical_binary())],
1014///     NativeType::Timestamp(TimeUnit::Second, None),
1015/// );
1016/// ```
1017#[derive(Debug, Clone, Eq, PartialOrd)]
1018pub struct ImplicitCoercion {
1019    /// The types that can be coerced from via implicit casting
1020    allowed_source_types: Vec<TypeSignatureClass>,
1021
1022    /// The default type to use when coercing from allowed source types.
1023    /// This is particularly important for types like Timestamp that have multiple
1024    /// possible configurations (different time units and timezones).
1025    default_casted_type: NativeType,
1026}
1027
1028impl Display for ImplicitCoercion {
1029    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1030        write!(
1031            f,
1032            "ImplicitCoercion({:?}, default_type={:?})",
1033            self.allowed_source_types, self.default_casted_type
1034        )
1035    }
1036}
1037
1038impl PartialEq for ImplicitCoercion {
1039    fn eq(&self, other: &Self) -> bool {
1040        self.allowed_source_types == other.allowed_source_types
1041            && self.default_casted_type == other.default_casted_type
1042    }
1043}
1044
1045impl Hash for ImplicitCoercion {
1046    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1047        self.allowed_source_types.hash(state);
1048        self.default_casted_type.hash(state);
1049    }
1050}
1051
1052/// Provides  information necessary for calling a function.
1053///
1054/// - [`TypeSignature`] defines the argument types that a function has implementations
1055///   for.
1056///
1057/// - [`Volatility`] defines how the output of the function changes with the input.
1058#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
1059pub struct Signature {
1060    /// The data types that the function accepts. See [TypeSignature] for more information.
1061    pub type_signature: TypeSignature,
1062    /// The volatility of the function. See [Volatility] for more information.
1063    pub volatility: Volatility,
1064    /// Optional parameter names for the function arguments.
1065    ///
1066    /// If provided, enables named argument notation for function calls (e.g., `func(a => 1, b => 2)`).
1067    /// The length must match the number of arguments defined by `type_signature`.
1068    ///
1069    /// Defaults to `None`, meaning only positional arguments are supported.
1070    pub parameter_names: Option<Vec<String>>,
1071}
1072
1073impl Signature {
1074    /// Creates a new Signature from a given type signature and volatility.
1075    pub fn new(type_signature: TypeSignature, volatility: Volatility) -> Self {
1076        Signature {
1077            type_signature,
1078            volatility,
1079            parameter_names: None,
1080        }
1081    }
1082    /// An arbitrary number of arguments with the same type, from those listed in `common_types`.
1083    pub fn variadic(common_types: Vec<DataType>, volatility: Volatility) -> Self {
1084        Self {
1085            type_signature: TypeSignature::Variadic(common_types),
1086            volatility,
1087            parameter_names: None,
1088        }
1089    }
1090    /// User-defined coercion rules for the function.
1091    pub fn user_defined(volatility: Volatility) -> Self {
1092        Self {
1093            type_signature: TypeSignature::UserDefined,
1094            volatility,
1095            parameter_names: None,
1096        }
1097    }
1098
1099    /// A specified number of numeric arguments
1100    pub fn numeric(arg_count: usize, volatility: Volatility) -> Self {
1101        Self {
1102            type_signature: TypeSignature::Numeric(arg_count),
1103            volatility,
1104            parameter_names: None,
1105        }
1106    }
1107
1108    /// A specified number of string arguments
1109    pub fn string(arg_count: usize, volatility: Volatility) -> Self {
1110        Self {
1111            type_signature: TypeSignature::String(arg_count),
1112            volatility,
1113            parameter_names: None,
1114        }
1115    }
1116
1117    /// An arbitrary number of arguments of any type.
1118    pub fn variadic_any(volatility: Volatility) -> Self {
1119        Self {
1120            type_signature: TypeSignature::VariadicAny,
1121            volatility,
1122            parameter_names: None,
1123        }
1124    }
1125    /// A fixed number of arguments of the same type, from those listed in `valid_types`.
1126    pub fn uniform(
1127        arg_count: usize,
1128        valid_types: Vec<DataType>,
1129        volatility: Volatility,
1130    ) -> Self {
1131        Self {
1132            type_signature: TypeSignature::Uniform(arg_count, valid_types),
1133            volatility,
1134            parameter_names: None,
1135        }
1136    }
1137    /// Exactly matches the types in `exact_types`, in order.
1138    pub fn exact(exact_types: Vec<DataType>, volatility: Volatility) -> Self {
1139        Signature {
1140            type_signature: TypeSignature::Exact(exact_types),
1141            volatility,
1142            parameter_names: None,
1143        }
1144    }
1145
1146    /// Target coerce types in order
1147    pub fn coercible(target_types: Vec<Coercion>, volatility: Volatility) -> Self {
1148        Self {
1149            type_signature: TypeSignature::Coercible(target_types),
1150            volatility,
1151            parameter_names: None,
1152        }
1153    }
1154
1155    /// Used for function that expects comparable data types, it will try to coerced all the types into single final one.
1156    pub fn comparable(arg_count: usize, volatility: Volatility) -> Self {
1157        Self {
1158            type_signature: TypeSignature::Comparable(arg_count),
1159            volatility,
1160            parameter_names: None,
1161        }
1162    }
1163
1164    pub fn nullary(volatility: Volatility) -> Self {
1165        Signature {
1166            type_signature: TypeSignature::Nullary,
1167            volatility,
1168            parameter_names: None,
1169        }
1170    }
1171
1172    /// A specified number of arguments of any type
1173    pub fn any(arg_count: usize, volatility: Volatility) -> Self {
1174        Signature {
1175            type_signature: TypeSignature::Any(arg_count),
1176            volatility,
1177            parameter_names: None,
1178        }
1179    }
1180
1181    /// Any one of a list of [TypeSignature]s.
1182    pub fn one_of(type_signatures: Vec<TypeSignature>, volatility: Volatility) -> Self {
1183        Signature {
1184            type_signature: TypeSignature::OneOf(type_signatures),
1185            volatility,
1186            parameter_names: None,
1187        }
1188    }
1189
1190    /// Specialized [Signature] for ArrayAppend and similar functions.
1191    pub fn array_and_element(volatility: Volatility) -> Self {
1192        Signature {
1193            type_signature: TypeSignature::ArraySignature(
1194                ArrayFunctionSignature::Array {
1195                    arguments: vec![
1196                        ArrayFunctionArgument::Array,
1197                        ArrayFunctionArgument::Element,
1198                    ],
1199                    array_coercion: Some(ListCoercion::FixedSizedListToList),
1200                },
1201            ),
1202            volatility,
1203            parameter_names: None,
1204        }
1205    }
1206
1207    /// Specialized [Signature] for ArrayPrepend and similar functions.
1208    pub fn element_and_array(volatility: Volatility) -> Self {
1209        Signature {
1210            type_signature: TypeSignature::ArraySignature(
1211                ArrayFunctionSignature::Array {
1212                    arguments: vec![
1213                        ArrayFunctionArgument::Element,
1214                        ArrayFunctionArgument::Array,
1215                    ],
1216                    array_coercion: Some(ListCoercion::FixedSizedListToList),
1217                },
1218            ),
1219            volatility,
1220            parameter_names: None,
1221        }
1222    }
1223
1224    /// Specialized [Signature] for functions that take a fixed number of arrays.
1225    pub fn arrays(
1226        n: usize,
1227        coercion: Option<ListCoercion>,
1228        volatility: Volatility,
1229    ) -> Self {
1230        Signature {
1231            type_signature: TypeSignature::ArraySignature(
1232                ArrayFunctionSignature::Array {
1233                    arguments: vec![ArrayFunctionArgument::Array; n],
1234                    array_coercion: coercion,
1235                },
1236            ),
1237            volatility,
1238            parameter_names: None,
1239        }
1240    }
1241
1242    /// Specialized [Signature] for Array functions with an optional index.
1243    pub fn array_and_element_and_optional_index(volatility: Volatility) -> Self {
1244        Signature {
1245            type_signature: TypeSignature::OneOf(vec![
1246                TypeSignature::ArraySignature(ArrayFunctionSignature::Array {
1247                    arguments: vec![
1248                        ArrayFunctionArgument::Array,
1249                        ArrayFunctionArgument::Element,
1250                    ],
1251                    array_coercion: Some(ListCoercion::FixedSizedListToList),
1252                }),
1253                TypeSignature::ArraySignature(ArrayFunctionSignature::Array {
1254                    arguments: vec![
1255                        ArrayFunctionArgument::Array,
1256                        ArrayFunctionArgument::Element,
1257                        ArrayFunctionArgument::Index,
1258                    ],
1259                    array_coercion: Some(ListCoercion::FixedSizedListToList),
1260                }),
1261            ]),
1262            volatility,
1263            parameter_names: None,
1264        }
1265    }
1266
1267    /// Specialized [Signature] for ArrayElement and similar functions.
1268    pub fn array_and_index(volatility: Volatility) -> Self {
1269        Signature {
1270            type_signature: TypeSignature::ArraySignature(
1271                ArrayFunctionSignature::Array {
1272                    arguments: vec![
1273                        ArrayFunctionArgument::Array,
1274                        ArrayFunctionArgument::Index,
1275                    ],
1276                    array_coercion: Some(ListCoercion::FixedSizedListToList),
1277                },
1278            ),
1279            volatility,
1280            parameter_names: None,
1281        }
1282    }
1283
1284    /// Specialized [Signature] for ArrayEmpty and similar functions.
1285    pub fn array(volatility: Volatility) -> Self {
1286        Signature::arrays(1, Some(ListCoercion::FixedSizedListToList), volatility)
1287    }
1288
1289    /// Add parameter names to this signature, enabling named argument notation.
1290    ///
1291    /// # Example
1292    /// ```
1293    /// # use datafusion_expr_common::signature::{Signature, Volatility};
1294    /// # use arrow::datatypes::DataType;
1295    /// let sig =
1296    ///     Signature::exact(vec![DataType::Int32, DataType::Utf8], Volatility::Immutable)
1297    ///         .with_parameter_names(vec!["count".to_string(), "name".to_string()]);
1298    /// ```
1299    ///
1300    /// # Errors
1301    /// Returns an error if the number of parameter names doesn't match the signature's arity.
1302    /// For signatures with variable arity (e.g., `Variadic`, `VariadicAny`), parameter names
1303    /// cannot be specified.
1304    pub fn with_parameter_names(mut self, names: Vec<impl Into<String>>) -> Result<Self> {
1305        let names = names.into_iter().map(Into::into).collect::<Vec<String>>();
1306        // Validate that the number of names matches the signature
1307        self.validate_parameter_names(&names)?;
1308        self.parameter_names = Some(names);
1309        Ok(self)
1310    }
1311
1312    /// Validate that parameter names are compatible with this signature
1313    fn validate_parameter_names(&self, names: &[String]) -> Result<()> {
1314        match self.type_signature.arity() {
1315            Arity::Fixed(expected) => {
1316                if names.len() != expected {
1317                    return plan_err!(
1318                        "Parameter names count ({}) does not match signature arity ({})",
1319                        names.len(),
1320                        expected
1321                    );
1322                }
1323            }
1324            Arity::Variable => {
1325                // For UserDefined signatures, allow parameter names
1326                // The function implementer is responsible for validating the names match the actual arguments
1327                if !matches!(self.type_signature, TypeSignature::UserDefined) {
1328                    return plan_err!(
1329                        "Cannot specify parameter names for variable arity signature: {:?}",
1330                        self.type_signature
1331                    );
1332                }
1333            }
1334        }
1335
1336        let mut seen = std::collections::HashSet::new();
1337        for name in names {
1338            if !seen.insert(name) {
1339                return plan_err!("Duplicate parameter name: '{}'", name);
1340            }
1341        }
1342
1343        Ok(())
1344    }
1345}
1346
1347#[cfg(test)]
1348mod tests {
1349    use datafusion_common::types::{logical_int32, logical_int64, logical_string};
1350
1351    use super::*;
1352    use crate::signature::{
1353        ArrayFunctionArgument, ArrayFunctionSignature, Coercion, TypeSignatureClass,
1354    };
1355
1356    #[test]
1357    fn supports_zero_argument_tests() {
1358        // Testing `TypeSignature`s which supports 0 arg
1359        let positive_cases = vec![
1360            TypeSignature::Exact(vec![]),
1361            TypeSignature::OneOf(vec![
1362                TypeSignature::Exact(vec![DataType::Int8]),
1363                TypeSignature::Nullary,
1364                TypeSignature::Uniform(1, vec![DataType::Int8]),
1365            ]),
1366            TypeSignature::Nullary,
1367        ];
1368
1369        for case in positive_cases {
1370            assert!(
1371                case.supports_zero_argument(),
1372                "Expected {case:?} to support zero arguments"
1373            );
1374        }
1375
1376        // Testing `TypeSignature`s which doesn't support 0 arg
1377        let negative_cases = vec![
1378            TypeSignature::Exact(vec![DataType::Utf8]),
1379            TypeSignature::Uniform(1, vec![DataType::Float64]),
1380            TypeSignature::Any(1),
1381            TypeSignature::VariadicAny,
1382            TypeSignature::OneOf(vec![
1383                TypeSignature::Exact(vec![DataType::Int8]),
1384                TypeSignature::Uniform(1, vec![DataType::Int8]),
1385            ]),
1386        ];
1387
1388        for case in negative_cases {
1389            assert!(
1390                !case.supports_zero_argument(),
1391                "Expected {case:?} not to support zero arguments"
1392            );
1393        }
1394    }
1395
1396    #[test]
1397    fn type_signature_partial_ord() {
1398        // Test validates that partial ord is defined for TypeSignature and Signature.
1399        assert!(TypeSignature::UserDefined < TypeSignature::VariadicAny);
1400        assert!(TypeSignature::UserDefined < TypeSignature::Any(1));
1401
1402        assert!(
1403            TypeSignature::Uniform(1, vec![DataType::Null])
1404                < TypeSignature::Uniform(1, vec![DataType::Boolean])
1405        );
1406        assert!(
1407            TypeSignature::Uniform(1, vec![DataType::Null])
1408                < TypeSignature::Uniform(2, vec![DataType::Null])
1409        );
1410        assert!(
1411            TypeSignature::Uniform(usize::MAX, vec![DataType::Null])
1412                < TypeSignature::Exact(vec![DataType::Null])
1413        );
1414    }
1415
1416    #[test]
1417    fn test_get_possible_types() {
1418        let type_signature = TypeSignature::Exact(vec![DataType::Int32, DataType::Int64]);
1419        let possible_types = type_signature.get_example_types();
1420        assert_eq!(possible_types, vec![vec![DataType::Int32, DataType::Int64]]);
1421
1422        let type_signature = TypeSignature::OneOf(vec![
1423            TypeSignature::Exact(vec![DataType::Int32, DataType::Int64]),
1424            TypeSignature::Exact(vec![DataType::Float32, DataType::Float64]),
1425        ]);
1426        let possible_types = type_signature.get_example_types();
1427        assert_eq!(
1428            possible_types,
1429            vec![
1430                vec![DataType::Int32, DataType::Int64],
1431                vec![DataType::Float32, DataType::Float64]
1432            ]
1433        );
1434
1435        let type_signature = TypeSignature::OneOf(vec![
1436            TypeSignature::Exact(vec![DataType::Int32, DataType::Int64]),
1437            TypeSignature::Exact(vec![DataType::Float32, DataType::Float64]),
1438            TypeSignature::Exact(vec![DataType::Utf8]),
1439        ]);
1440        let possible_types = type_signature.get_example_types();
1441        assert_eq!(
1442            possible_types,
1443            vec![
1444                vec![DataType::Int32, DataType::Int64],
1445                vec![DataType::Float32, DataType::Float64],
1446                vec![DataType::Utf8]
1447            ]
1448        );
1449
1450        let type_signature =
1451            TypeSignature::Uniform(2, vec![DataType::Float32, DataType::Int64]);
1452        let possible_types = type_signature.get_example_types();
1453        assert_eq!(
1454            possible_types,
1455            vec![
1456                vec![DataType::Float32, DataType::Float32],
1457                vec![DataType::Int64, DataType::Int64]
1458            ]
1459        );
1460
1461        let type_signature = TypeSignature::Coercible(vec![
1462            Coercion::new_exact(TypeSignatureClass::Native(logical_string())),
1463            Coercion::new_exact(TypeSignatureClass::Native(logical_int64())),
1464        ]);
1465        let possible_types = type_signature.get_example_types();
1466        assert_eq!(
1467            possible_types,
1468            vec![
1469                vec![DataType::Utf8, DataType::Int64],
1470                vec![DataType::LargeUtf8, DataType::Int64],
1471                vec![DataType::Utf8View, DataType::Int64]
1472            ]
1473        );
1474
1475        let type_signature =
1476            TypeSignature::Variadic(vec![DataType::Int32, DataType::Int64]);
1477        let possible_types = type_signature.get_example_types();
1478        assert_eq!(
1479            possible_types,
1480            vec![vec![DataType::Int32], vec![DataType::Int64]]
1481        );
1482
1483        let type_signature = TypeSignature::Numeric(2);
1484        let possible_types = type_signature.get_example_types();
1485        assert_eq!(
1486            possible_types,
1487            vec![
1488                vec![DataType::Int8, DataType::Int8],
1489                vec![DataType::Int16, DataType::Int16],
1490                vec![DataType::Int32, DataType::Int32],
1491                vec![DataType::Int64, DataType::Int64],
1492                vec![DataType::UInt8, DataType::UInt8],
1493                vec![DataType::UInt16, DataType::UInt16],
1494                vec![DataType::UInt32, DataType::UInt32],
1495                vec![DataType::UInt64, DataType::UInt64],
1496                vec![DataType::Float32, DataType::Float32],
1497                vec![DataType::Float64, DataType::Float64]
1498            ]
1499        );
1500
1501        let type_signature = TypeSignature::String(2);
1502        let possible_types = type_signature.get_example_types();
1503        assert_eq!(
1504            possible_types,
1505            vec![
1506                vec![DataType::Utf8, DataType::Utf8],
1507                vec![DataType::LargeUtf8, DataType::LargeUtf8],
1508                vec![DataType::Utf8View, DataType::Utf8View]
1509            ]
1510        );
1511    }
1512
1513    #[test]
1514    fn test_signature_with_parameter_names() {
1515        let sig = Signature::exact(
1516            vec![DataType::Int32, DataType::Utf8],
1517            Volatility::Immutable,
1518        )
1519        .with_parameter_names(vec!["count".to_string(), "name".to_string()])
1520        .unwrap();
1521
1522        assert_eq!(
1523            sig.parameter_names,
1524            Some(vec!["count".to_string(), "name".to_string()])
1525        );
1526        assert_eq!(
1527            sig.type_signature,
1528            TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8])
1529        );
1530    }
1531
1532    #[test]
1533    fn test_signature_parameter_names_wrong_count() {
1534        let result = Signature::exact(
1535            vec![DataType::Int32, DataType::Utf8],
1536            Volatility::Immutable,
1537        )
1538        .with_parameter_names(vec!["count".to_string()]); // Only 1 name for 2 args
1539
1540        assert!(result.is_err());
1541        assert!(result
1542            .unwrap_err()
1543            .to_string()
1544            .contains("does not match signature arity"));
1545    }
1546
1547    #[test]
1548    fn test_signature_parameter_names_duplicate() {
1549        let result = Signature::exact(
1550            vec![DataType::Int32, DataType::Int32],
1551            Volatility::Immutable,
1552        )
1553        .with_parameter_names(vec!["count".to_string(), "count".to_string()]);
1554
1555        assert!(result.is_err());
1556        assert!(result
1557            .unwrap_err()
1558            .to_string()
1559            .contains("Duplicate parameter name"));
1560    }
1561
1562    #[test]
1563    fn test_signature_parameter_names_variadic() {
1564        let result = Signature::variadic(vec![DataType::Int32], Volatility::Immutable)
1565            .with_parameter_names(vec!["arg".to_string()]);
1566
1567        assert!(result.is_err());
1568        assert!(result
1569            .unwrap_err()
1570            .to_string()
1571            .contains("variable arity signature"));
1572    }
1573
1574    #[test]
1575    fn test_signature_without_parameter_names() {
1576        let sig = Signature::exact(
1577            vec![DataType::Int32, DataType::Utf8],
1578            Volatility::Immutable,
1579        );
1580
1581        assert_eq!(sig.parameter_names, None);
1582    }
1583
1584    #[test]
1585    fn test_signature_uniform_with_parameter_names() {
1586        let sig = Signature::uniform(3, vec![DataType::Float64], Volatility::Immutable)
1587            .with_parameter_names(vec!["x".to_string(), "y".to_string(), "z".to_string()])
1588            .unwrap();
1589
1590        assert_eq!(
1591            sig.parameter_names,
1592            Some(vec!["x".to_string(), "y".to_string(), "z".to_string()])
1593        );
1594    }
1595
1596    #[test]
1597    fn test_signature_numeric_with_parameter_names() {
1598        let sig = Signature::numeric(2, Volatility::Immutable)
1599            .with_parameter_names(vec!["a".to_string(), "b".to_string()])
1600            .unwrap();
1601
1602        assert_eq!(
1603            sig.parameter_names,
1604            Some(vec!["a".to_string(), "b".to_string()])
1605        );
1606    }
1607
1608    #[test]
1609    fn test_signature_nullary_with_empty_names() {
1610        let sig = Signature::nullary(Volatility::Immutable)
1611            .with_parameter_names(Vec::<String>::new())
1612            .unwrap();
1613
1614        assert_eq!(sig.parameter_names, Some(vec![]));
1615    }
1616
1617    #[test]
1618    fn test_to_string_repr_with_names_exact() {
1619        let sig = TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]);
1620
1621        assert_eq!(sig.to_string_repr_with_names(None), vec!["Int32, Utf8"]);
1622
1623        let names = vec!["id".to_string(), "name".to_string()];
1624        assert_eq!(
1625            sig.to_string_repr_with_names(Some(&names)),
1626            vec!["id: Int32, name: Utf8"]
1627        );
1628    }
1629
1630    #[test]
1631    fn test_to_string_repr_with_names_any() {
1632        let sig = TypeSignature::Any(3);
1633
1634        assert_eq!(sig.to_string_repr_with_names(None), vec!["Any, Any, Any"]);
1635
1636        let names = vec!["x".to_string(), "y".to_string(), "z".to_string()];
1637        assert_eq!(
1638            sig.to_string_repr_with_names(Some(&names)),
1639            vec!["x: Any, y: Any, z: Any"]
1640        );
1641    }
1642
1643    #[test]
1644    fn test_to_string_repr_with_names_one_of() {
1645        let sig =
1646            TypeSignature::OneOf(vec![TypeSignature::Any(2), TypeSignature::Any(3)]);
1647
1648        assert_eq!(
1649            sig.to_string_repr_with_names(None),
1650            vec!["Any, Any", "Any, Any, Any"]
1651        );
1652
1653        let names = vec![
1654            "str".to_string(),
1655            "start_pos".to_string(),
1656            "length".to_string(),
1657        ];
1658        assert_eq!(
1659            sig.to_string_repr_with_names(Some(&names)),
1660            vec![
1661                "str: Any, start_pos: Any",
1662                "str: Any, start_pos: Any, length: Any"
1663            ]
1664        );
1665    }
1666
1667    #[test]
1668    fn test_to_string_repr_with_names_partial() {
1669        // This simulates providing max arity names for a OneOf signature
1670        let sig = TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]);
1671
1672        // Provide 3 names for 2-parameter signature (extra name is ignored via zip)
1673        let names = vec!["a".to_string(), "b".to_string(), "c".to_string()];
1674        assert_eq!(
1675            sig.to_string_repr_with_names(Some(&names)),
1676            vec!["a: Int32, b: Utf8"]
1677        );
1678    }
1679
1680    #[test]
1681    fn test_to_string_repr_with_names_uniform() {
1682        let sig = TypeSignature::Uniform(2, vec![DataType::Float64]);
1683
1684        assert_eq!(
1685            sig.to_string_repr_with_names(None),
1686            vec!["Float64, Float64"]
1687        );
1688
1689        let names = vec!["x".to_string(), "y".to_string()];
1690        assert_eq!(
1691            sig.to_string_repr_with_names(Some(&names)),
1692            vec!["x: Float64, y: Float64"]
1693        );
1694    }
1695
1696    #[test]
1697    fn test_to_string_repr_with_names_coercible() {
1698        let sig = TypeSignature::Coercible(vec![
1699            Coercion::new_exact(TypeSignatureClass::Native(logical_int32())),
1700            Coercion::new_exact(TypeSignatureClass::Native(logical_int32())),
1701        ]);
1702
1703        let names = vec!["a".to_string(), "b".to_string()];
1704        let result = sig.to_string_repr_with_names(Some(&names));
1705        // Check that it contains the parameter names with type annotations
1706        assert_eq!(result.len(), 1);
1707        assert!(result[0].starts_with("a: "));
1708        assert!(result[0].contains(", b: "));
1709    }
1710
1711    #[test]
1712    fn test_to_string_repr_with_names_comparable_numeric_string() {
1713        let comparable = TypeSignature::Comparable(3);
1714        let numeric = TypeSignature::Numeric(2);
1715        let string_sig = TypeSignature::String(2);
1716
1717        let names = vec!["a".to_string(), "b".to_string(), "c".to_string()];
1718
1719        // All should show parameter names with type annotations
1720        assert_eq!(
1721            comparable.to_string_repr_with_names(Some(&names)),
1722            vec!["a: Comparable, b: Comparable, c: Comparable"]
1723        );
1724        assert_eq!(
1725            numeric.to_string_repr_with_names(Some(&names)),
1726            vec!["a: Numeric, b: Numeric"]
1727        );
1728        assert_eq!(
1729            string_sig.to_string_repr_with_names(Some(&names)),
1730            vec!["a: String, b: String"]
1731        );
1732    }
1733
1734    #[test]
1735    fn test_to_string_repr_with_names_variadic_fallback() {
1736        let variadic = TypeSignature::Variadic(vec![DataType::Utf8, DataType::LargeUtf8]);
1737        let names = vec!["x".to_string()];
1738        assert_eq!(
1739            variadic.to_string_repr_with_names(Some(&names)),
1740            variadic.to_string_repr()
1741        );
1742
1743        let variadic_any = TypeSignature::VariadicAny;
1744        assert_eq!(
1745            variadic_any.to_string_repr_with_names(Some(&names)),
1746            variadic_any.to_string_repr()
1747        );
1748
1749        // UserDefined now shows parameter names when available
1750        let user_defined = TypeSignature::UserDefined;
1751        assert_eq!(
1752            user_defined.to_string_repr_with_names(Some(&names)),
1753            vec!["x"]
1754        );
1755        assert_eq!(
1756            user_defined.to_string_repr_with_names(None),
1757            user_defined.to_string_repr()
1758        );
1759    }
1760
1761    #[test]
1762    fn test_to_string_repr_with_names_nullary() {
1763        let sig = TypeSignature::Nullary;
1764        let names = vec!["x".to_string()];
1765
1766        // Should return empty representation, names don't apply
1767        assert_eq!(
1768            sig.to_string_repr_with_names(Some(&names)),
1769            vec!["NullAry()"]
1770        );
1771        assert_eq!(sig.to_string_repr_with_names(None), vec!["NullAry()"]);
1772    }
1773
1774    #[test]
1775    fn test_to_string_repr_with_names_array_signature() {
1776        let sig = TypeSignature::ArraySignature(ArrayFunctionSignature::Array {
1777            arguments: vec![
1778                ArrayFunctionArgument::Array,
1779                ArrayFunctionArgument::Index,
1780                ArrayFunctionArgument::Element,
1781            ],
1782            array_coercion: None,
1783        });
1784
1785        assert_eq!(
1786            sig.to_string_repr_with_names(None),
1787            vec!["array, index, element"]
1788        );
1789
1790        let names = vec!["arr".to_string(), "idx".to_string(), "val".to_string()];
1791        assert_eq!(
1792            sig.to_string_repr_with_names(Some(&names)),
1793            vec!["arr: array, idx: index, val: element"]
1794        );
1795
1796        let recursive =
1797            TypeSignature::ArraySignature(ArrayFunctionSignature::RecursiveArray);
1798        let names = vec!["array".to_string()];
1799        assert_eq!(
1800            recursive.to_string_repr_with_names(Some(&names)),
1801            vec!["array: recursive_array"]
1802        );
1803
1804        // Test MapArray (1 argument)
1805        let map_array = TypeSignature::ArraySignature(ArrayFunctionSignature::MapArray);
1806        let names = vec!["map".to_string()];
1807        assert_eq!(
1808            map_array.to_string_repr_with_names(Some(&names)),
1809            vec!["map: map_array"]
1810        );
1811    }
1812
1813    #[test]
1814    fn test_type_signature_arity_exact() {
1815        let sig = TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]);
1816        assert_eq!(sig.arity(), Arity::Fixed(2));
1817
1818        let sig = TypeSignature::Exact(vec![]);
1819        assert_eq!(sig.arity(), Arity::Fixed(0));
1820    }
1821
1822    #[test]
1823    fn test_type_signature_arity_uniform() {
1824        let sig = TypeSignature::Uniform(3, vec![DataType::Float64]);
1825        assert_eq!(sig.arity(), Arity::Fixed(3));
1826
1827        let sig = TypeSignature::Uniform(1, vec![DataType::Int32]);
1828        assert_eq!(sig.arity(), Arity::Fixed(1));
1829    }
1830
1831    #[test]
1832    fn test_type_signature_arity_numeric() {
1833        let sig = TypeSignature::Numeric(2);
1834        assert_eq!(sig.arity(), Arity::Fixed(2));
1835    }
1836
1837    #[test]
1838    fn test_type_signature_arity_string() {
1839        let sig = TypeSignature::String(3);
1840        assert_eq!(sig.arity(), Arity::Fixed(3));
1841    }
1842
1843    #[test]
1844    fn test_type_signature_arity_comparable() {
1845        let sig = TypeSignature::Comparable(2);
1846        assert_eq!(sig.arity(), Arity::Fixed(2));
1847    }
1848
1849    #[test]
1850    fn test_type_signature_arity_any() {
1851        let sig = TypeSignature::Any(4);
1852        assert_eq!(sig.arity(), Arity::Fixed(4));
1853    }
1854
1855    #[test]
1856    fn test_type_signature_arity_coercible() {
1857        let sig = TypeSignature::Coercible(vec![
1858            Coercion::new_exact(TypeSignatureClass::Native(logical_int32())),
1859            Coercion::new_exact(TypeSignatureClass::Native(logical_string())),
1860        ]);
1861        assert_eq!(sig.arity(), Arity::Fixed(2));
1862    }
1863
1864    #[test]
1865    fn test_type_signature_arity_nullary() {
1866        let sig = TypeSignature::Nullary;
1867        assert_eq!(sig.arity(), Arity::Fixed(0));
1868    }
1869
1870    #[test]
1871    fn test_type_signature_arity_array_signature() {
1872        // Test Array variant with 2 arguments
1873        let sig = TypeSignature::ArraySignature(ArrayFunctionSignature::Array {
1874            arguments: vec![ArrayFunctionArgument::Array, ArrayFunctionArgument::Index],
1875            array_coercion: None,
1876        });
1877        assert_eq!(sig.arity(), Arity::Fixed(2));
1878
1879        // Test Array variant with 3 arguments
1880        let sig = TypeSignature::ArraySignature(ArrayFunctionSignature::Array {
1881            arguments: vec![
1882                ArrayFunctionArgument::Array,
1883                ArrayFunctionArgument::Element,
1884                ArrayFunctionArgument::Index,
1885            ],
1886            array_coercion: None,
1887        });
1888        assert_eq!(sig.arity(), Arity::Fixed(3));
1889
1890        // Test RecursiveArray variant
1891        let sig = TypeSignature::ArraySignature(ArrayFunctionSignature::RecursiveArray);
1892        assert_eq!(sig.arity(), Arity::Fixed(1));
1893
1894        // Test MapArray variant
1895        let sig = TypeSignature::ArraySignature(ArrayFunctionSignature::MapArray);
1896        assert_eq!(sig.arity(), Arity::Fixed(1));
1897    }
1898
1899    #[test]
1900    fn test_type_signature_arity_one_of_fixed() {
1901        // OneOf with all fixed arity variants should return max arity
1902        let sig = TypeSignature::OneOf(vec![
1903            TypeSignature::Exact(vec![DataType::Int32]),
1904            TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]),
1905            TypeSignature::Exact(vec![
1906                DataType::Int32,
1907                DataType::Utf8,
1908                DataType::Float64,
1909            ]),
1910        ]);
1911        assert_eq!(sig.arity(), Arity::Fixed(3));
1912    }
1913
1914    #[test]
1915    fn test_type_signature_arity_one_of_variable() {
1916        // OneOf with variable arity variant should return Variable
1917        let sig = TypeSignature::OneOf(vec![
1918            TypeSignature::Exact(vec![DataType::Int32]),
1919            TypeSignature::VariadicAny,
1920        ]);
1921        assert_eq!(sig.arity(), Arity::Variable);
1922    }
1923
1924    #[test]
1925    fn test_type_signature_arity_variadic() {
1926        let sig = TypeSignature::Variadic(vec![DataType::Int32]);
1927        assert_eq!(sig.arity(), Arity::Variable);
1928
1929        let sig = TypeSignature::VariadicAny;
1930        assert_eq!(sig.arity(), Arity::Variable);
1931    }
1932
1933    #[test]
1934    fn test_type_signature_arity_user_defined() {
1935        let sig = TypeSignature::UserDefined;
1936        assert_eq!(sig.arity(), Arity::Variable);
1937    }
1938}