1use 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
31pub const TIMEZONE_WILDCARD: &str = "+TZ";
40
41pub const FIXED_SIZE_LIST_WILDCARD: i32 = i32::MIN;
45
46#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
53pub enum Volatility {
54 Immutable,
62 Stable,
74 Volatile,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89pub enum Arity {
90 Fixed(usize),
92 Variable,
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
154pub enum TypeSignature {
155 Variadic(Vec<DataType>),
164 UserDefined,
172 VariadicAny,
174 Uniform(usize, Vec<DataType>),
181 Exact(Vec<DataType>),
185 Coercible(Vec<Coercion>),
193 Comparable(usize),
212 Any(usize),
216 OneOf(Vec<TypeSignature>),
226 ArraySignature(ArrayFunctionSignature),
228 Numeric(usize),
236 String(usize),
247 Nullary,
249}
250
251impl TypeSignature {
252 #[inline]
253 pub fn is_one_of(&self) -> bool {
254 matches!(self, TypeSignature::OneOf(_))
255 }
256
257 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 let has_variable = variants.iter().any(|v| v.arity() == Arity::Variable);
298 if has_variable {
299 return Arity::Variable;
300 }
301 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#[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 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 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 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 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 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 Array {
461 arguments: Vec<ArrayFunctionArgument>,
463 array_coercion: Option<ListCoercion>,
465 },
466 RecursiveArray,
469 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 Element,
501 Index,
503 Array,
506 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 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 TypeSignature::Variadic(_) | TypeSignature::VariadicAny => {
741 self.to_string_repr()
742 }
743 }
744 }
745
746 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 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 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 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 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 _ => vec![],
869 }
870}
871
872#[derive(Debug, Clone, Eq, PartialOrd)]
897pub enum Coercion {
898 Exact {
900 desired_type: TypeSignatureClass,
902 },
903
904 Implicit {
906 desired_type: TypeSignatureClass,
908 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 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#[derive(Debug, Clone, Eq, PartialOrd)]
1018pub struct ImplicitCoercion {
1019 allowed_source_types: Vec<TypeSignatureClass>,
1021
1022 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#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
1059pub struct Signature {
1060 pub type_signature: TypeSignature,
1062 pub volatility: Volatility,
1064 pub parameter_names: Option<Vec<String>>,
1071}
1072
1073impl Signature {
1074 pub fn new(type_signature: TypeSignature, volatility: Volatility) -> Self {
1076 Signature {
1077 type_signature,
1078 volatility,
1079 parameter_names: None,
1080 }
1081 }
1082 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 pub fn user_defined(volatility: Volatility) -> Self {
1092 Self {
1093 type_signature: TypeSignature::UserDefined,
1094 volatility,
1095 parameter_names: None,
1096 }
1097 }
1098
1099 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 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 pub fn variadic_any(volatility: Volatility) -> Self {
1119 Self {
1120 type_signature: TypeSignature::VariadicAny,
1121 volatility,
1122 parameter_names: None,
1123 }
1124 }
1125 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 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 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 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 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 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 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 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 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 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 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 pub fn array(volatility: Volatility) -> Self {
1286 Signature::arrays(1, Some(ListCoercion::FixedSizedListToList), volatility)
1287 }
1288
1289 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 self.validate_parameter_names(&names)?;
1308 self.parameter_names = Some(names);
1309 Ok(self)
1310 }
1311
1312 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 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 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 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 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()]); 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 let sig = TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]);
1671
1672 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 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 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 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 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 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 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 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 let sig = TypeSignature::ArraySignature(ArrayFunctionSignature::RecursiveArray);
1892 assert_eq!(sig.arity(), Arity::Fixed(1));
1893
1894 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 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 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}