Skip to content

Commit

Permalink
Backport "feat: cast between Intervals"
Browse files Browse the repository at this point in the history
See apache@863d599
See apache#4182

Can drop this after rebase on commit 863d599 "feat: cast between Intervals (apache#4182)", first released in 41.0.0
  • Loading branch information
mcheshkov committed Aug 21, 2024
1 parent 4b7a3df commit 8f6522c
Showing 1 changed file with 127 additions and 0 deletions.
127 changes: 127 additions & 0 deletions arrow/src/compute/kernels/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
IntervalUnit::MonthDayNano => false,
}
}
(Interval(IntervalUnit::YearMonth), Interval(IntervalUnit::MonthDayNano)) => true,
(Interval(IntervalUnit::DayTime), Interval(IntervalUnit::MonthDayNano)) => true,
(_, _) => false,
}
}
Expand Down Expand Up @@ -355,6 +357,45 @@ macro_rules! cast_floating_point_to_decimal {
}};
}

/// Cast the array from interval year month to month day nano
fn cast_interval_year_month_to_interval_month_day_nano(
array: &dyn Array,
_cast_options: &CastOptions,
) -> Result<ArrayRef> {
let array = array
.as_any()
.downcast_ref::<IntervalYearMonthArray>()
.unwrap();

Ok(Arc::new(unary::<_, _, IntervalMonthDayNanoType>(
array,
|v| {
let months = IntervalYearMonthType::to_months(v);
IntervalMonthDayNanoType::make_value(months, 0, 0)
},
)))
}

/// Cast the array from interval day time to month day nano
fn cast_interval_day_time_to_interval_month_day_nano(
array: &dyn Array,
_cast_options: &CastOptions,
) -> Result<ArrayRef> {
let array = array
.as_any()
.downcast_ref::<IntervalDayTimeArray>()
.unwrap();
let mul = 1_000_000;

Ok(Arc::new(unary::<_, _, IntervalMonthDayNanoType>(
array,
|v| {
let (days, ms) = IntervalDayTimeType::to_parts(v);
IntervalMonthDayNanoType::make_value(0, days, ms as i64 * mul)
},
)))
}

// cast the decimal array to integer array
macro_rules! cast_decimal_to_integer {
($ARRAY:expr, $SCALE : ident, $VALUE_BUILDER: ident, $NATIVE_TYPE : ident, $DATA_TYPE : expr) => {{
Expand Down Expand Up @@ -1338,6 +1379,12 @@ pub fn cast_with_options(
from_type, to_type,
))),
},
(Interval(IntervalUnit::YearMonth), Interval(IntervalUnit::MonthDayNano)) => {
cast_interval_year_month_to_interval_month_day_nano(array, cast_options)
}
(Interval(IntervalUnit::DayTime), Interval(IntervalUnit::MonthDayNano)) => {
cast_interval_day_time_to_interval_month_day_nano(array, cast_options)
}
(_, _) => Err(ArrowError::CastError(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
Expand Down Expand Up @@ -2715,6 +2762,86 @@ mod tests {
);
}

/// helper function to test casting from interval year month to interval month day nano
fn cast_from_interval_year_month_to_interval_month_day_nano(
array: Vec<i32>,
cast_options: &CastOptions,
) -> Result<ArrayRef> {
let array = PrimitiveArray::<IntervalYearMonthType>::from(array);
let array = Arc::new(array) as ArrayRef;
let casted_array = cast_with_options(
&array,
&DataType::Interval(IntervalUnit::MonthDayNano),
cast_options,
)?;
Ok(casted_array)
}

#[test]
fn test_cast_from_interval_year_month_to_interval_month_day_nano() {
// from interval year month to interval month day nano
let array = vec![1234567];
let casted_array = cast_from_interval_year_month_to_interval_month_day_nano(
array,
&DEFAULT_CAST_OPTIONS,
)
.unwrap();
let casted_array = casted_array
.as_any()
.downcast_ref::<IntervalMonthDayNanoArray>()
.ok_or_else(|| {
ArrowError::ComputeError(
"Failed to downcast to IntervalMonthDayNanoArray".to_string(),
)
})
.unwrap();
assert_eq!(
casted_array.data_type(),
&DataType::Interval(IntervalUnit::MonthDayNano)
);
assert_eq!(casted_array.value(0), 97812474910747780469848774134464512);
}

/// helper function to test casting from interval day time to interval month day nano
fn cast_from_interval_day_time_to_interval_month_day_nano(
array: Vec<i64>,
cast_options: &CastOptions,
) -> Result<ArrayRef> {
let array = PrimitiveArray::<IntervalDayTimeType>::from(array);
let array = Arc::new(array) as ArrayRef;
let casted_array = cast_with_options(
&array,
&DataType::Interval(IntervalUnit::MonthDayNano),
cast_options,
)?;
Ok(casted_array)
}

#[test]
fn test_cast_from_interval_day_time_to_interval_month_day_nano() {
// from interval day time to interval month day nano
let array = vec![123];
let casted_array = cast_from_interval_day_time_to_interval_month_day_nano(
array,
&DEFAULT_CAST_OPTIONS,
)
.unwrap();
let casted_array = casted_array
.as_any()
.downcast_ref::<IntervalMonthDayNanoArray>()
.ok_or_else(|| {
ArrowError::ComputeError(
"Failed to downcast to IntervalMonthDayNanoArray".to_string(),
)
})
.unwrap();
assert_eq!(
casted_array.data_type(),
&DataType::Interval(IntervalUnit::MonthDayNano)
);
assert_eq!(casted_array.value(0), 123000000);
}

#[test]
fn test_cast_i32_to_f64() {
let a = Int32Array::from(vec![5, 6, 7, 8, 9]);
Expand Down

0 comments on commit 8f6522c

Please sign in to comment.