@@ -43,13 +43,15 @@ mod list;
4343mod map;
4444mod run_array;
4545mod string;
46+ mod union;
4647
4748use crate :: cast:: decimal:: * ;
4849use crate :: cast:: dictionary:: * ;
4950use crate :: cast:: list:: * ;
5051use crate :: cast:: map:: * ;
5152use crate :: cast:: run_array:: * ;
5253use crate :: cast:: string:: * ;
54+ pub use crate :: cast:: union:: * ;
5355
5456use arrow_buffer:: IntervalMonthDayNano ;
5557use arrow_data:: ByteView ;
@@ -71,6 +73,7 @@ use arrow_select::take::take;
7173use num_traits:: { NumCast , ToPrimitive , cast:: AsPrimitive } ;
7274
7375pub use decimal:: { DecimalCast , rescale_decimal} ;
76+ pub use string:: cast_single_string_to_boolean_default;
7477
7578/// CastOptions provides a way to override the default cast behaviors
7679#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
@@ -108,6 +111,8 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
108111 can_cast_types ( from_value_type, to_value_type)
109112 }
110113 ( Dictionary ( _, value_type) , _) => can_cast_types ( value_type, to_type) ,
114+ ( Union ( fields, _) , _) => union:: resolve_child_array ( fields, to_type) . is_some ( ) ,
115+ ( _, Union ( _, _) ) => false ,
111116 ( RunEndEncoded ( _, value_type) , _) => can_cast_types ( value_type. data_type ( ) , to_type) ,
112117 ( _, RunEndEncoded ( _, value_type) ) => can_cast_types ( from_type, value_type. data_type ( ) ) ,
113118 ( _, Dictionary ( _, value_type) ) => can_cast_types ( from_type, value_type) ,
@@ -230,7 +235,6 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
230235 }
231236 ( Struct ( _) , _) => false ,
232237 ( _, Struct ( _) ) => false ,
233-
234238 ( _, Boolean ) => from_type. is_integer ( ) || from_type. is_floating ( ) || from_type. is_string ( ) ,
235239 ( Boolean , _) => to_type. is_integer ( ) || to_type. is_floating ( ) || to_type. is_string ( ) ,
236240
@@ -781,6 +785,14 @@ pub fn cast_with_options(
781785 ) ) ) ,
782786 }
783787 }
788+ ( Union ( _, _) , _) => union_extract_by_type (
789+ array. as_any ( ) . downcast_ref :: < UnionArray > ( ) . unwrap ( ) ,
790+ to_type,
791+ cast_options,
792+ ) ,
793+ ( _, Union ( _, _) ) => Err ( ArrowError :: CastError ( format ! (
794+ "Casting from {from_type} to {to_type} not supported"
795+ ) ) ) ,
784796 ( Dictionary ( index_type, _) , _) => match * * index_type {
785797 Int8 => dictionary_cast :: < Int8Type > ( array, to_type, cast_options) ,
786798 Int16 => dictionary_cast :: < Int16Type > ( array, to_type, cast_options) ,
@@ -2287,7 +2299,7 @@ fn cast_from_decimal<D, F>(
22872299) -> Result < ArrayRef , ArrowError >
22882300where
22892301 D : DecimalType + ArrowPrimitiveType ,
2290- <D as ArrowPrimitiveType >:: Native : ArrowNativeTypeOp + ToPrimitive ,
2302+ <D as ArrowPrimitiveType >:: Native : ToPrimitive ,
22912303 F : Fn ( D :: Native ) -> f64 ,
22922304{
22932305 use DataType :: * ;
@@ -2464,7 +2476,7 @@ where
24642476 R :: Native : NumCast ,
24652477{
24662478 from. try_unary ( |value| {
2467- num_traits :: cast :: cast :: < T :: Native , R :: Native > ( value) . ok_or_else ( || {
2479+ num_cast :: < T :: Native , R :: Native > ( value) . ok_or_else ( || {
24682480 ArrowError :: CastError ( format ! (
24692481 "Can't cast value {:?} to type {}" ,
24702482 value,
@@ -2474,6 +2486,17 @@ where
24742486 } )
24752487}
24762488
2489+ /// Natural cast between numeric types
2490+ /// Return None if the input `value` can't be casted to type `O`.
2491+ #[ inline]
2492+ pub fn num_cast < I , O > ( value : I ) -> Option < O >
2493+ where
2494+ I : NumCast ,
2495+ O : NumCast ,
2496+ {
2497+ num_traits:: cast:: cast :: < I , O > ( value)
2498+ }
2499+
24772500// Natural cast between numeric types
24782501// If the value of T can't be casted to R, it will be converted to null
24792502fn numeric_cast < T , R > ( from : & PrimitiveArray < T > ) -> PrimitiveArray < R >
@@ -2483,7 +2506,7 @@ where
24832506 T :: Native : NumCast ,
24842507 R :: Native : NumCast ,
24852508{
2486- from. unary_opt :: < _ , R > ( num_traits :: cast :: cast :: < T :: Native , R :: Native > )
2509+ from. unary_opt :: < _ , R > ( num_cast :: < T :: Native , R :: Native > )
24872510}
24882511
24892512fn cast_numeric_to_binary < FROM : ArrowPrimitiveType , O : OffsetSizeTrait > (
@@ -2540,16 +2563,23 @@ where
25402563 for i in 0 ..from. len ( ) {
25412564 if from. is_null ( i) {
25422565 b. append_null ( ) ;
2543- } else if from. value ( i) != T :: default_value ( ) {
2544- b. append_value ( true ) ;
25452566 } else {
2546- b. append_value ( false ) ;
2567+ b. append_value ( cast_num_to_bool :: < T :: Native > ( from . value ( i ) ) ) ;
25472568 }
25482569 }
25492570
25502571 Ok ( b. finish ( ) )
25512572}
25522573
2574+ /// Cast numeric types to boolean
2575+ #[ inline]
2576+ pub fn cast_num_to_bool < I > ( value : I ) -> bool
2577+ where
2578+ I : Default + PartialEq ,
2579+ {
2580+ value != I :: default ( )
2581+ }
2582+
25532583/// Cast Boolean types to numeric
25542584///
25552585/// `false` returns 0 while `true` returns 1
@@ -2575,11 +2605,8 @@ where
25752605 let iter = ( 0 ..from. len ( ) ) . map ( |i| {
25762606 if from. is_null ( i) {
25772607 None
2578- } else if from. value ( i) {
2579- // a workaround to cast a primitive to T::Native, infallible
2580- num_traits:: cast:: cast ( 1 )
25812608 } else {
2582- Some ( T :: default_value ( ) )
2609+ single_bool_to_numeric :: < T :: Native > ( from . value ( i ) )
25832610 }
25842611 } ) ;
25852612 // Benefit:
@@ -2589,6 +2616,20 @@ where
25892616 unsafe { PrimitiveArray :: < T > :: from_trusted_len_iter ( iter) }
25902617}
25912618
2619+ /// Cast single bool value to numeric value.
2620+ #[ inline]
2621+ pub fn single_bool_to_numeric < O > ( value : bool ) -> Option < O >
2622+ where
2623+ O : num_traits:: NumCast + Default ,
2624+ {
2625+ if value {
2626+ // a workaround to cast a primitive to type O, infallible
2627+ num_traits:: cast:: cast ( 1 )
2628+ } else {
2629+ Some ( O :: default ( ) )
2630+ }
2631+ }
2632+
25922633/// Helper function to cast from one `BinaryArray` or 'LargeBinaryArray' to 'FixedSizeBinaryArray'.
25932634fn cast_binary_to_fixed_size_binary < O : OffsetSizeTrait > (
25942635 array : & dyn Array ,
0 commit comments