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]

Reply via email to