@@ -102,7 +102,12 @@ fn build_array_for_field(rows: &[TableRow], field_idx: usize, data_type: &DataTy
102
102
build_timestamptz_array ( rows, field_idx, tz)
103
103
}
104
104
DataType :: Timestamp ( TimeUnit :: Microsecond , None ) => {
105
- build_primitive_array :: < TimestampMicrosecondType , _ > ( rows, field_idx, cell_to_timestamp)
105
+ // Support both naive timestamps and time-of-day encoded as timestamp-from-epoch.
106
+ build_primitive_array :: < TimestampMicrosecondType , _ > (
107
+ rows,
108
+ field_idx,
109
+ cell_to_timestamp_or_time,
110
+ )
106
111
}
107
112
DataType :: Decimal128 ( precision, scale) => {
108
113
build_decimal128_array ( rows, field_idx, * precision, * scale)
@@ -188,7 +193,12 @@ fn build_timestamptz_array(rows: &[TableRow], field_idx: usize, tz: &str) -> Arr
188
193
let mut builder = TimestampMicrosecondBuilder :: new ( ) . with_timezone ( tz) ;
189
194
190
195
for row in rows {
191
- let arrow_value = cell_to_timestamptz ( & row. values [ field_idx] ) ;
196
+ // Accept either timestamptz values or time-of-day (encoded from epoch date).
197
+ let arrow_value = match & row. values [ field_idx] {
198
+ Cell :: TimestampTz ( _) => cell_to_timestamptz ( & row. values [ field_idx] ) ,
199
+ Cell :: Time ( _) => cell_to_time_as_timestamp ( & row. values [ field_idx] ) ,
200
+ _ => None ,
201
+ } ;
192
202
builder. append_option ( arrow_value) ;
193
203
}
194
204
@@ -429,6 +439,20 @@ fn cell_to_timestamp(cell: &Cell) -> Option<i64> {
429
439
}
430
440
}
431
441
442
+ /// Converts a [`Cell`] to a 64-bit timestamp value (microseconds since Unix epoch),
443
+ /// accepting either a naive timestamp or a time-of-day.
444
+ ///
445
+ /// - [`Cell::Timestamp`] is converted like [`cell_to_timestamp`].
446
+ /// - [`Cell::Time`] is converted to microseconds since Unix epoch by treating it as
447
+ /// a time on the Unix epoch date (1970-01-01T00:00:00).
448
+ fn cell_to_timestamp_or_time ( cell : & Cell ) -> Option < i64 > {
449
+ match cell {
450
+ Cell :: Timestamp ( _) => cell_to_timestamp ( cell) ,
451
+ Cell :: Time ( time) => time. signed_duration_since ( MIDNIGHT ) . num_microseconds ( ) ,
452
+ _ => None ,
453
+ }
454
+ }
455
+
432
456
/// Converts a [`Cell`] to a timezone-aware timestamp value (microseconds since Unix epoch).
433
457
///
434
458
/// Transforms timezone-aware [`Cell::TimestampTz`] values into microseconds
@@ -530,7 +554,7 @@ fn build_list_array(rows: &[TableRow], field_idx: usize, field: FieldRef) -> Arr
530
554
DataType :: Float64 => build_float64_list_array ( rows, field_idx, field) ,
531
555
DataType :: Utf8 => build_string_list_array ( rows, field_idx, field) ,
532
556
DataType :: Binary => build_binary_list_array ( rows, field_idx, field) ,
533
- DataType :: LargeBinary => build_binary_list_array ( rows, field_idx, field) ,
557
+ DataType :: LargeBinary => build_large_binary_list_array ( rows, field_idx, field) ,
534
558
DataType :: Date32 => build_date32_list_array ( rows, field_idx, field) ,
535
559
DataType :: Time64 ( TimeUnit :: Microsecond ) => build_time64_list_array ( rows, field_idx, field) ,
536
560
DataType :: Time64 ( TimeUnit :: Nanosecond ) => build_time64_list_array ( rows, field_idx, field) ,
@@ -791,6 +815,34 @@ fn build_string_list_array(rows: &[TableRow], field_idx: usize, field: FieldRef)
791
815
792
816
/// Builds a list array for binary elements.
793
817
fn build_binary_list_array ( rows : & [ TableRow ] , field_idx : usize , field : FieldRef ) -> ArrayRef {
818
+ let mut list_builder = ListBuilder :: new ( BinaryBuilder :: new ( ) ) . with_field ( field. clone ( ) ) ;
819
+
820
+ for row in rows {
821
+ if let Some ( array_cell) = cell_to_array_cell ( & row. values [ field_idx] ) {
822
+ match array_cell {
823
+ ArrayCell :: Bytes ( vec) => {
824
+ for item in vec {
825
+ match item {
826
+ Some ( bytes) => list_builder. values ( ) . append_value ( bytes) ,
827
+ None => list_builder. values ( ) . append_null ( ) ,
828
+ }
829
+ }
830
+ list_builder. append ( true ) ;
831
+ }
832
+ _ => {
833
+ return build_list_array_for_strings ( rows, field_idx, field) ;
834
+ }
835
+ }
836
+ } else {
837
+ list_builder. append_null ( ) ;
838
+ }
839
+ }
840
+
841
+ Arc :: new ( list_builder. finish ( ) )
842
+ }
843
+
844
+ /// Builds a list array for large binary elements.
845
+ fn build_large_binary_list_array ( rows : & [ TableRow ] , field_idx : usize , field : FieldRef ) -> ArrayRef {
794
846
let mut list_builder = ListBuilder :: new ( LargeBinaryBuilder :: new ( ) ) . with_field ( field. clone ( ) ) ;
795
847
796
848
for row in rows {
@@ -889,6 +941,15 @@ fn build_timestamp_list_array(rows: &[TableRow], field_idx: usize, field: FieldR
889
941
}
890
942
list_builder. append ( true ) ;
891
943
}
944
+ ArrayCell :: Time ( vec) => {
945
+ for item in vec {
946
+ let arrow_value = item. and_then ( |time| {
947
+ time. signed_duration_since ( MIDNIGHT ) . num_microseconds ( )
948
+ } ) ;
949
+ list_builder. values ( ) . append_option ( arrow_value) ;
950
+ }
951
+ list_builder. append ( true ) ;
952
+ }
892
953
_ => {
893
954
return build_list_array_for_strings ( rows, field_idx, field) ;
894
955
}
@@ -923,6 +984,15 @@ fn build_timestamptz_list_array(rows: &[TableRow], field_idx: usize, field: Fiel
923
984
}
924
985
list_builder. append ( true ) ;
925
986
}
987
+ ArrayCell :: Time ( vec) => {
988
+ for item in vec {
989
+ let arrow_value = item. and_then ( |time| {
990
+ time. signed_duration_since ( MIDNIGHT ) . num_microseconds ( )
991
+ } ) ;
992
+ list_builder. values ( ) . append_option ( arrow_value) ;
993
+ }
994
+ list_builder. append ( true ) ;
995
+ }
926
996
_ => {
927
997
return build_list_array_for_strings ( rows, field_idx, field) ;
928
998
}
@@ -935,6 +1005,14 @@ fn build_timestamptz_list_array(rows: &[TableRow], field_idx: usize, field: Fiel
935
1005
Arc :: new ( list_builder. finish ( ) )
936
1006
}
937
1007
1008
+ /// Converts a [`Cell::Time`] to a timestamp-from-epoch in microseconds.
1009
+ fn cell_to_time_as_timestamp ( cell : & Cell ) -> Option < i64 > {
1010
+ match cell {
1011
+ Cell :: Time ( time) => time. signed_duration_since ( MIDNIGHT ) . num_microseconds ( ) ,
1012
+ _ => None ,
1013
+ }
1014
+ }
1015
+
938
1016
/// Builds a list array for UUID elements.
939
1017
fn build_uuid_list_array ( rows : & [ TableRow ] , field_idx : usize , field : FieldRef ) -> ArrayRef {
940
1018
let mut list_builder =
@@ -2608,7 +2686,7 @@ mod tests {
2608
2686
use arrow:: array:: ListArray ;
2609
2687
use arrow:: datatypes:: Field ;
2610
2688
2611
- let field = Field :: new ( "items" , DataType :: LargeBinary , true ) ;
2689
+ let field = Field :: new ( "items" , DataType :: Binary , true ) ;
2612
2690
let field_ref = Arc :: new ( field) ;
2613
2691
2614
2692
let test_bytes_1 = vec ! [ 1 , 2 , 3 , 4 , 5 ] ;
@@ -2646,7 +2724,7 @@ mod tests {
2646
2724
let first_list = list_array. value ( 0 ) ;
2647
2725
let binary_array = first_list
2648
2726
. as_any ( )
2649
- . downcast_ref :: < arrow:: array:: LargeBinaryArray > ( )
2727
+ . downcast_ref :: < arrow:: array:: BinaryArray > ( )
2650
2728
. unwrap ( ) ;
2651
2729
assert_eq ! ( binary_array. len( ) , 3 ) ;
2652
2730
assert_eq ! ( binary_array. value( 0 ) , test_bytes_1) ;
@@ -2658,7 +2736,7 @@ mod tests {
2658
2736
let second_list = list_array. value ( 1 ) ;
2659
2737
let binary_array = second_list
2660
2738
. as_any ( )
2661
- . downcast_ref :: < arrow:: array:: LargeBinaryArray > ( )
2739
+ . downcast_ref :: < arrow:: array:: BinaryArray > ( )
2662
2740
. unwrap ( ) ;
2663
2741
assert_eq ! ( binary_array. len( ) , 1 ) ;
2664
2742
assert_eq ! ( binary_array. value( 0 ) , empty_bytes) ;
0 commit comments