Skip to content

Commit 799330b

Browse files
authored
feat: add support for casting Duration/Interval to Int64Array (#1196)
* feat: add support for casting Duration to Int64Array * feat: cast from Interval to Int64
1 parent d68c4ae commit 799330b

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

arrow/src/compute/kernels/cast.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,14 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
221221
(Timestamp(_, _), Timestamp(_, _) | Date32 | Date64) => true,
222222
// date64 to timestamp might not make sense,
223223
(Int64, Duration(_)) => true,
224+
(Duration(_), Int64) => true,
225+
(Interval(from_type), Int64) => {
226+
match from_type{
227+
IntervalUnit::YearMonth => true,
228+
IntervalUnit::DayTime => true,
229+
IntervalUnit::MonthDayNano => false, // Native type is i128
230+
}
231+
}
224232
(_, _) => false,
225233
}
226234
}
@@ -358,7 +366,6 @@ macro_rules! cast_decimal_to_float {
358366
/// * To or from `StructArray`
359367
/// * List to primitive
360368
/// * Utf8 to boolean
361-
/// * Interval and duration
362369
pub fn cast_with_options(
363370
array: &ArrayRef,
364371
to_type: &DataType,
@@ -1111,6 +1118,17 @@ pub fn cast_with_options(
11111118
}
11121119
}
11131120
}
1121+
(Duration(_), Int64) => cast_array_data::<Int64Type>(array, to_type.clone()),
1122+
(Interval(from_type), Int64) => match from_type {
1123+
IntervalUnit::YearMonth => {
1124+
cast_numeric_arrays::<IntervalYearMonthType, Int64Type>(array)
1125+
}
1126+
IntervalUnit::DayTime => cast_array_data::<Int64Type>(array, to_type.clone()),
1127+
IntervalUnit::MonthDayNano => Err(ArrowError::CastError(format!(
1128+
"Casting from {:?} to {:?} not supported",
1129+
from_type, to_type,
1130+
))),
1131+
},
11141132
(_, _) => Err(ArrowError::CastError(format!(
11151133
"Casting from {:?} to {:?} not supported",
11161134
from_type, to_type,
@@ -2765,6 +2783,44 @@ mod tests {
27652783
assert!(c.is_null(2));
27662784
}
27672785

2786+
#[test]
2787+
fn test_cast_duration_to_i64() {
2788+
let base = vec![5, 6, 7, 8, 100000000];
2789+
2790+
let duration_arrays = vec![
2791+
Arc::new(DurationNanosecondArray::from(base.clone())) as ArrayRef,
2792+
Arc::new(DurationMicrosecondArray::from(base.clone())) as ArrayRef,
2793+
Arc::new(DurationMillisecondArray::from(base.clone())) as ArrayRef,
2794+
Arc::new(DurationSecondArray::from(base.clone())) as ArrayRef,
2795+
];
2796+
2797+
for arr in duration_arrays {
2798+
assert!(can_cast_types(arr.data_type(), &DataType::Int64));
2799+
let result = cast(&arr, &DataType::Int64).unwrap();
2800+
let result = result.as_any().downcast_ref::<Int64Array>().unwrap();
2801+
assert_eq!(base.as_slice(), result.values());
2802+
}
2803+
}
2804+
2805+
#[test]
2806+
fn test_cast_interval_to_i64() {
2807+
let base = vec![5, 6, 7, 8];
2808+
2809+
let interval_arrays = vec![
2810+
Arc::new(IntervalDayTimeArray::from(base.clone())) as ArrayRef,
2811+
Arc::new(IntervalYearMonthArray::from(
2812+
base.iter().map(|x| *x as i32).collect::<Vec<i32>>(),
2813+
)) as ArrayRef,
2814+
];
2815+
2816+
for arr in interval_arrays {
2817+
assert!(can_cast_types(arr.data_type(), &DataType::Int64));
2818+
let result = cast(&arr, &DataType::Int64).unwrap();
2819+
let result = result.as_any().downcast_ref::<Int64Array>().unwrap();
2820+
assert_eq!(base.as_slice(), result.values());
2821+
}
2822+
}
2823+
27682824
#[test]
27692825
fn test_cast_to_strings() {
27702826
let a = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;

0 commit comments

Comments
 (0)