@@ -20,13 +20,13 @@ use crate::{timezone, BinaryOutputStyle};
2020use crate :: { EvalMode , SparkError , SparkResult } ;
2121use arrow:: array:: builder:: StringBuilder ;
2222use arrow:: array:: {
23- BooleanBuilder , Decimal128Builder , DictionaryArray , GenericByteArray , ListArray ,
23+ BinaryBuilder , BooleanBuilder , Decimal128Builder , DictionaryArray , GenericByteArray , ListArray ,
2424 PrimitiveBuilder , StringArray , StructArray ,
2525} ;
2626use arrow:: compute:: can_cast_types;
2727use arrow:: datatypes:: {
28- i256, ArrowDictionaryKeyType , ArrowNativeType , DataType , Decimal256Type , GenericBinaryType ,
29- Schema ,
28+ i256, ArrowDictionaryKeyType , ArrowNativeType , DataType , Decimal256Type ,
29+ GenericBinaryType , Schema ,
3030} ;
3131use arrow:: {
3232 array:: {
@@ -311,22 +311,22 @@ fn can_cast_from_byte(to_type: &DataType, _: &SparkCastOptions) -> bool {
311311 use DataType :: * ;
312312 matches ! (
313313 to_type,
314- Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 | Decimal128 ( _, _)
314+ Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 | Decimal128 ( _, _) | Binary
315315 )
316316}
317317
318318fn can_cast_from_short ( to_type : & DataType , _: & SparkCastOptions ) -> bool {
319319 use DataType :: * ;
320320 matches ! (
321321 to_type,
322- Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 | Decimal128 ( _, _)
322+ Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 | Decimal128 ( _, _) | Binary
323323 )
324324}
325325
326326fn can_cast_from_int ( to_type : & DataType , options : & SparkCastOptions ) -> bool {
327327 use DataType :: * ;
328328 match to_type {
329- Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 | Utf8 => true ,
329+ Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 | Utf8 | Binary => true ,
330330 Decimal128 ( _, _) => {
331331 // incompatible: no overflow check
332332 options. allow_incompat
@@ -338,7 +338,7 @@ fn can_cast_from_int(to_type: &DataType, options: &SparkCastOptions) -> bool {
338338fn can_cast_from_long ( to_type : & DataType , options : & SparkCastOptions ) -> bool {
339339 use DataType :: * ;
340340 match to_type {
341- Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 => true ,
341+ Boolean | Int8 | Int16 | Int32 | Int64 | Float32 | Float64 | Binary => true ,
342342 Decimal128 ( _, _) => {
343343 // incompatible: no overflow check
344344 options. allow_incompat
@@ -501,6 +501,29 @@ macro_rules! cast_float_to_string {
501501 } } ;
502502}
503503
504+ // eval mode is not needed since all ints can be implemented in binary format
505+ macro_rules! cast_whole_num_to_binary {
506+ ( $array: expr, $primitive_type: ty, $byte_size: expr) => { {
507+ let input_arr = $array
508+ . as_any( )
509+ . downcast_ref:: <$primitive_type>( )
510+ . ok_or_else( || SparkError :: Internal ( "Expected numeric array" . to_string( ) ) ) ?;
511+
512+ let len = input_arr. len( ) ;
513+ let mut builder = BinaryBuilder :: with_capacity( len, len * $byte_size) ;
514+
515+ for i in 0 ..input_arr. len( ) {
516+ if input_arr. is_null( i) {
517+ builder. append_null( ) ;
518+ } else {
519+ builder. append_value( input_arr. value( i) . to_be_bytes( ) ) ;
520+ }
521+ }
522+
523+ Ok ( Arc :: new( builder. finish( ) ) as ArrayRef )
524+ } } ;
525+ }
526+
504527macro_rules! cast_int_to_int_macro {
505528 (
506529 $array: expr,
@@ -1096,6 +1119,10 @@ fn cast_array(
10961119 Ok ( cast_with_options ( & array, to_type, & CAST_OPTIONS ) ?)
10971120 }
10981121 ( Binary , Utf8 ) => Ok ( cast_binary_to_string :: < i32 > ( & array, cast_options) ?) ,
1122+ ( Int8 , Binary ) => cast_whole_num_to_binary ! ( & array, Int8Array , 1 ) ,
1123+ ( Int16 , Binary ) => cast_whole_num_to_binary ! ( & array, Int16Array , 2 ) ,
1124+ ( Int32 , Binary ) => cast_whole_num_to_binary ! ( & array, Int32Array , 4 ) ,
1125+ ( Int64 , Binary ) => cast_whole_num_to_binary ! ( & array, Int64Array , 8 ) ,
10991126 _ if cast_options. is_adapting_schema
11001127 || is_datafusion_spark_compatible ( from_type, to_type) =>
11011128 {
0 commit comments