This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/master by this push:
     new 799330b  feat: add support for casting Duration/Interval to Int64Array 
(#1196)
799330b is described below

commit 799330b18ea1ba404cbe4a7fa47199ee3450b253
Author: Edd Robinson <[email protected]>
AuthorDate: Wed Jan 19 12:19:29 2022 +0000

    feat: add support for casting Duration/Interval to Int64Array (#1196)
    
    * feat: add support for casting Duration to Int64Array
    
    * feat: cast from Interval to Int64
---
 arrow/src/compute/kernels/cast.rs | 58 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/arrow/src/compute/kernels/cast.rs 
b/arrow/src/compute/kernels/cast.rs
index 34b7810..a3b4d6b 100644
--- a/arrow/src/compute/kernels/cast.rs
+++ b/arrow/src/compute/kernels/cast.rs
@@ -221,6 +221,14 @@ pub fn can_cast_types(from_type: &DataType, to_type: 
&DataType) -> bool {
         (Timestamp(_, _), Timestamp(_, _) | Date32 | Date64) => true,
         // date64 to timestamp might not make sense,
         (Int64, Duration(_)) => true,
+        (Duration(_), Int64) => true,
+        (Interval(from_type), Int64) => {
+            match from_type{
+                IntervalUnit::YearMonth => true,
+                IntervalUnit::DayTime => true,
+                IntervalUnit::MonthDayNano => false, // Native type is i128
+            }
+        }
         (_, _) => false,
     }
 }
@@ -358,7 +366,6 @@ macro_rules! cast_decimal_to_float {
 /// * To or from `StructArray`
 /// * List to primitive
 /// * Utf8 to boolean
-/// * Interval and duration
 pub fn cast_with_options(
     array: &ArrayRef,
     to_type: &DataType,
@@ -1111,6 +1118,17 @@ pub fn cast_with_options(
                 }
             }
         }
+        (Duration(_), Int64) => cast_array_data::<Int64Type>(array, 
to_type.clone()),
+        (Interval(from_type), Int64) => match from_type {
+            IntervalUnit::YearMonth => {
+                cast_numeric_arrays::<IntervalYearMonthType, Int64Type>(array)
+            }
+            IntervalUnit::DayTime => cast_array_data::<Int64Type>(array, 
to_type.clone()),
+            IntervalUnit::MonthDayNano => Err(ArrowError::CastError(format!(
+                "Casting from {:?} to {:?} not supported",
+                from_type, to_type,
+            ))),
+        },
         (_, _) => Err(ArrowError::CastError(format!(
             "Casting from {:?} to {:?} not supported",
             from_type, to_type,
@@ -2766,6 +2784,44 @@ mod tests {
     }
 
     #[test]
+    fn test_cast_duration_to_i64() {
+        let base = vec![5, 6, 7, 8, 100000000];
+
+        let duration_arrays = vec![
+            Arc::new(DurationNanosecondArray::from(base.clone())) as ArrayRef,
+            Arc::new(DurationMicrosecondArray::from(base.clone())) as ArrayRef,
+            Arc::new(DurationMillisecondArray::from(base.clone())) as ArrayRef,
+            Arc::new(DurationSecondArray::from(base.clone())) as ArrayRef,
+        ];
+
+        for arr in duration_arrays {
+            assert!(can_cast_types(arr.data_type(), &DataType::Int64));
+            let result = cast(&arr, &DataType::Int64).unwrap();
+            let result = result.as_any().downcast_ref::<Int64Array>().unwrap();
+            assert_eq!(base.as_slice(), result.values());
+        }
+    }
+
+    #[test]
+    fn test_cast_interval_to_i64() {
+        let base = vec![5, 6, 7, 8];
+
+        let interval_arrays = vec![
+            Arc::new(IntervalDayTimeArray::from(base.clone())) as ArrayRef,
+            Arc::new(IntervalYearMonthArray::from(
+                base.iter().map(|x| *x as i32).collect::<Vec<i32>>(),
+            )) as ArrayRef,
+        ];
+
+        for arr in interval_arrays {
+            assert!(can_cast_types(arr.data_type(), &DataType::Int64));
+            let result = cast(&arr, &DataType::Int64).unwrap();
+            let result = result.as_any().downcast_ref::<Int64Array>().unwrap();
+            assert_eq!(base.as_slice(), result.values());
+        }
+    }
+
+    #[test]
     fn test_cast_to_strings() {
         let a = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
         let out = cast(&a, &DataType::Utf8).unwrap();

Reply via email to