This is an automated email from the ASF dual-hosted git repository.
tustvold 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 5f402752f refactor: timestamp overflow check (#3840)
5f402752f is described below
commit 5f402752f8695eda88b1b6f7342a391ae58e21cc
Author: Alex Huang <[email protected]>
AuthorDate: Fri Mar 10 14:48:42 2023 +0100
refactor: timestamp overflow check (#3840)
* refactor: timestamp overflow check
* update tests
* refactor: cast based on cast_option
---
arrow-cast/src/cast.rs | 43 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 40 insertions(+), 3 deletions(-)
diff --git a/arrow-cast/src/cast.rs b/arrow-cast/src/cast.rs
index 35bf62969..0a4b88ec8 100644
--- a/arrow-cast/src/cast.rs
+++ b/arrow-cast/src/cast.rs
@@ -1682,7 +1682,11 @@ pub fn cast_with_options(
Ordering::Equal => time_array.clone(),
Ordering::Less => {
let mul = to_size / from_size;
- time_array.unary::<_, Int64Type>(|o| o * mul)
+ if cast_options.safe {
+ time_array.unary_opt::<_, Int64Type>(|o|
o.checked_mul(mul))
+ } else {
+ time_array.try_unary::<_, Int64Type, _>(|o|
o.mul_checked(mul))?
+ }
}
};
Ok(make_timestamp_array(
@@ -1709,8 +1713,22 @@ pub fn cast_with_options(
Ok(Arc::new(b.finish()) as ArrayRef)
}
(Timestamp(TimeUnit::Second, _), Date64) => Ok(Arc::new(
- as_primitive_array::<TimestampSecondType>(array)
- .unary::<_, Date64Type>(|x| x * MILLISECONDS),
+ match cast_options.safe {
+ true => {
+ // change error to None
+ as_primitive_array::<TimestampSecondType>(array)
+ .unary_opt::<_, Date64Type>(|x| {
+ x.checked_mul(MILLISECONDS)
+ })
+ }
+ false => {
+
as_primitive_array::<TimestampSecondType>(array).try_unary::<_, Date64Type, _>(
+ |x| {
+ x.mul_checked(MILLISECONDS)
+ },
+ )?
+ }
+ },
)),
(Timestamp(TimeUnit::Millisecond, _), Date64) => {
cast_reinterpret_arrays::<TimestampMillisecondType,
Date64Type>(array)
@@ -5330,6 +5348,23 @@ mod tests {
assert_eq!(864000000005, c.value(0));
assert_eq!(1545696000001, c.value(1));
assert!(c.is_null(2));
+
+ let array =
+ TimestampSecondArray::from(vec![Some(864000000005),
Some(1545696000001)]);
+ let b = cast(&array, &DataType::Date64).unwrap();
+ let c = b.as_any().downcast_ref::<Date64Array>().unwrap();
+ assert_eq!(864000000005000, c.value(0));
+ assert_eq!(1545696000001000, c.value(1));
+
+ // test overflow, safe cast
+ let array = TimestampSecondArray::from(vec![Some(i64::MAX)]);
+ let b = cast(&array, &DataType::Date64).unwrap();
+ assert!(b.is_null(0));
+ // test overflow, unsafe cast
+ let array = TimestampSecondArray::from(vec![Some(i64::MAX)]);
+ let options = CastOptions { safe: false };
+ let b = cast_with_options(&array, &DataType::Date64, &options);
+ assert!(b.is_err());
}
#[test]
@@ -5406,6 +5441,8 @@ mod tests {
assert!(b.is_err());
let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond));
assert!(b.is_err());
+ let b = cast(&array, &DataType::Time64(TimeUnit::Millisecond));
+ assert!(b.is_err());
}
#[test]