diff --git a/arrow-arith/src/numeric.rs b/arrow-arith/src/numeric.rs index 29d6956a413..7862fe2f9be 100644 --- a/arrow-arith/src/numeric.rs +++ b/arrow-arith/src/numeric.rs @@ -346,15 +346,13 @@ fn float_op( trait TimestampOp: ArrowTimestampType { type Duration: ArrowPrimitiveType; - fn add_year_month(timestamp: i64, delta: i32, tz: Tz) -> Result; - fn add_day_time(timestamp: i64, delta: i64, tz: Tz) -> Result; - fn add_month_day_nano(timestamp: i64, delta: i128, tz: Tz) - -> Result; - - fn sub_year_month(timestamp: i64, delta: i32, tz: Tz) -> Result; - fn sub_day_time(timestamp: i64, delta: i64, tz: Tz) -> Result; - fn sub_month_day_nano(timestamp: i64, delta: i128, tz: Tz) - -> Result; + fn add_year_month(timestamp: i64, delta: i32, tz: Tz) -> Option; + fn add_day_time(timestamp: i64, delta: i64, tz: Tz) -> Option; + fn add_month_day_nano(timestamp: i64, delta: i128, tz: Tz) -> Option; + + fn sub_year_month(timestamp: i64, delta: i32, tz: Tz) -> Option; + fn sub_day_time(timestamp: i64, delta: i64, tz: Tz) -> Option; + fn sub_month_day_nano(timestamp: i64, delta: i128, tz: Tz) -> Option; } macro_rules! timestamp { @@ -362,35 +360,27 @@ macro_rules! timestamp { impl TimestampOp for $t { type Duration = $d; - fn add_year_month(left: i64, right: i32, tz: Tz) -> Result { + fn add_year_month(left: i64, right: i32, tz: Tz) -> Option { Self::add_year_months(left, right, tz) } - fn add_day_time(left: i64, right: i64, tz: Tz) -> Result { + fn add_day_time(left: i64, right: i64, tz: Tz) -> Option { Self::add_day_time(left, right, tz) } - fn add_month_day_nano( - left: i64, - right: i128, - tz: Tz, - ) -> Result { + fn add_month_day_nano(left: i64, right: i128, tz: Tz) -> Option { Self::add_month_day_nano(left, right, tz) } - fn sub_year_month(left: i64, right: i32, tz: Tz) -> Result { + fn sub_year_month(left: i64, right: i32, tz: Tz) -> Option { Self::subtract_year_months(left, right, tz) } - fn sub_day_time(left: i64, right: i64, tz: Tz) -> Result { + fn sub_day_time(left: i64, right: i64, tz: Tz) -> Option { Self::subtract_day_time(left, right, tz) } - fn sub_month_day_nano( - left: i64, - right: i128, - tz: Tz, - ) -> Result { + fn sub_month_day_nano(left: i64, right: i128, tz: Tz) -> Option { Self::subtract_month_day_nano(left, right, tz) } } @@ -432,29 +422,77 @@ fn timestamp_op( (Op::Add | Op::AddWrapping, Interval(YearMonth)) => { let r = r.as_primitive::(); - try_op!(l, l_s, r, r_s, T::add_year_month(l, r, l_tz)) + try_op!( + l, + l_s, + r, + r_s, + T::add_year_month(l, r, l_tz).ok_or(ArrowError::ComputeError( + "Timestamp out of range".to_string() + )) + ) } (Op::Sub | Op::SubWrapping, Interval(YearMonth)) => { let r = r.as_primitive::(); - try_op!(l, l_s, r, r_s, T::sub_year_month(l, r, l_tz)) + try_op!( + l, + l_s, + r, + r_s, + T::sub_year_month(l, r, l_tz).ok_or(ArrowError::ComputeError( + "Timestamp out of range".to_string() + )) + ) } (Op::Add | Op::AddWrapping, Interval(DayTime)) => { let r = r.as_primitive::(); - try_op!(l, l_s, r, r_s, T::add_day_time(l, r, l_tz)) + try_op!( + l, + l_s, + r, + r_s, + T::add_day_time(l, r, l_tz).ok_or(ArrowError::ComputeError( + "Timestamp out of range".to_string() + )) + ) } (Op::Sub | Op::SubWrapping, Interval(DayTime)) => { let r = r.as_primitive::(); - try_op!(l, l_s, r, r_s, T::sub_day_time(l, r, l_tz)) + try_op!( + l, + l_s, + r, + r_s, + T::sub_day_time(l, r, l_tz).ok_or(ArrowError::ComputeError( + "Timestamp out of range".to_string() + )) + ) } (Op::Add | Op::AddWrapping, Interval(MonthDayNano)) => { let r = r.as_primitive::(); - try_op!(l, l_s, r, r_s, T::add_month_day_nano(l, r, l_tz)) + try_op!( + l, + l_s, + r, + r_s, + T::add_month_day_nano(l, r, l_tz).ok_or(ArrowError::ComputeError( + "Timestamp out of range".to_string() + )) + ) } (Op::Sub | Op::SubWrapping, Interval(MonthDayNano)) => { let r = r.as_primitive::(); - try_op!(l, l_s, r, r_s, T::sub_month_day_nano(l, r, l_tz)) + try_op!( + l, + l_s, + r, + r_s, + T::sub_month_day_nano(l, r, l_tz).ok_or(ArrowError::ComputeError( + "Timestamp out of range".to_string() + )) + ) } _ => { return Err(ArrowError::InvalidArgumentError(format!( diff --git a/arrow-array/src/types.rs b/arrow-array/src/types.rs index 245106c2c00..769dbf974b9 100644 --- a/arrow-array/src/types.rs +++ b/arrow-array/src/types.rs @@ -359,110 +359,84 @@ fn add_year_months( timestamp: ::Native, delta: ::Native, tz: Tz, -) -> Result<::Native, ArrowError> { +) -> Option<::Native> { let months = IntervalYearMonthType::to_months(delta); - let res = as_datetime_with_timezone::(timestamp, tz) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = add_months_datetime(res, months) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; + let res = as_datetime_with_timezone::(timestamp, tz)?; + let res = add_months_datetime(res, months)?; let res = res.naive_utc(); T::make_value(res) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string())) } fn add_day_time( timestamp: ::Native, delta: ::Native, tz: Tz, -) -> Result<::Native, ArrowError> { +) -> Option<::Native> { let (days, ms) = IntervalDayTimeType::to_parts(delta); - let res = as_datetime_with_timezone::(timestamp, tz) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = add_days_datetime(res, days) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = res - .checked_add_signed(Duration::milliseconds(ms as i64)) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; + let res = as_datetime_with_timezone::(timestamp, tz)?; + let res = add_days_datetime(res, days)?; + let res = res.checked_add_signed(Duration::milliseconds(ms as i64))?; let res = res.naive_utc(); T::make_value(res) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string())) } fn add_month_day_nano( timestamp: ::Native, delta: ::Native, tz: Tz, -) -> Result<::Native, ArrowError> { +) -> Option<::Native> { let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); - let res = as_datetime_with_timezone::(timestamp, tz) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = add_months_datetime(res, months) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = add_days_datetime(res, days) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = res - .checked_add_signed(Duration::nanoseconds(nanos)) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; + let res = as_datetime_with_timezone::(timestamp, tz)?; + let res = add_months_datetime(res, months)?; + let res = add_days_datetime(res, days)?; + let res = res.checked_add_signed(Duration::nanoseconds(nanos))?; let res = res.naive_utc(); T::make_value(res) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string())) } fn subtract_year_months( timestamp: ::Native, delta: ::Native, tz: Tz, -) -> Result<::Native, ArrowError> { +) -> Option<::Native> { let months = IntervalYearMonthType::to_months(delta); - let res = as_datetime_with_timezone::(timestamp, tz) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = sub_months_datetime(res, months) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; + let res = as_datetime_with_timezone::(timestamp, tz)?; + let res = sub_months_datetime(res, months)?; let res = res.naive_utc(); T::make_value(res) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string())) } fn subtract_day_time( timestamp: ::Native, delta: ::Native, tz: Tz, -) -> Result<::Native, ArrowError> { +) -> Option<::Native> { let (days, ms) = IntervalDayTimeType::to_parts(delta); - let res = as_datetime_with_timezone::(timestamp, tz) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = sub_days_datetime(res, days) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = res - .checked_sub_signed(Duration::milliseconds(ms as i64)) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; + let res = as_datetime_with_timezone::(timestamp, tz)?; + let res = sub_days_datetime(res, days)?; + let res = res.checked_sub_signed(Duration::milliseconds(ms as i64))?; let res = res.naive_utc(); T::make_value(res) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string())) } fn subtract_month_day_nano( timestamp: ::Native, delta: ::Native, tz: Tz, -) -> Result<::Native, ArrowError> { +) -> Option<::Native> { let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); - let res = as_datetime_with_timezone::(timestamp, tz) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = sub_months_datetime(res, months) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = sub_days_datetime(res, days) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; - let res = res - .checked_sub_signed(Duration::nanoseconds(nanos)) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string()))?; + let res = as_datetime_with_timezone::(timestamp, tz)?; + let res = sub_months_datetime(res, months)?; + let res = sub_days_datetime(res, days)?; + let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?; let res = res.naive_utc(); T::make_value(res) - .ok_or_else(|| ArrowError::ComputeError("Timestamp out of range".to_string())) } impl TimestampSecondType { - /// Adds the given IntervalYearMonthType to an arrow TimestampSecondType + /// Adds the given IntervalYearMonthType to an arrow TimestampSecondType. + /// + /// Returns `None` when it will result in overflow. /// /// # Arguments /// @@ -473,11 +447,13 @@ impl TimestampSecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_year_months::(timestamp, delta, tz) } - /// Adds the given IntervalDayTimeType to an arrow TimestampSecondType + /// Adds the given IntervalDayTimeType to an arrow TimestampSecondType. + /// + /// Returns `None` when it will result in overflow. /// /// # Arguments /// @@ -488,12 +464,13 @@ impl TimestampSecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_day_time::(timestamp, delta, tz) } /// Adds the given IntervalMonthDayNanoType to an arrow TimestampSecondType /// + /// Returns `None` when it will result in overflow. /// # Arguments /// /// * `timestamp` - The date on which to perform the operation @@ -503,12 +480,14 @@ impl TimestampSecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_month_day_nano::(timestamp, delta, tz) } /// Subtracts the given IntervalYearMonthType to an arrow TimestampSecondType /// + /// Returns `None` when it will result in overflow. + /// /// # Arguments /// /// * `timestamp` - The date on which to perform the operation @@ -518,12 +497,14 @@ impl TimestampSecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_year_months::(timestamp, delta, tz) } /// Subtracts the given IntervalDayTimeType to an arrow TimestampSecondType /// + /// Returns `None` when it will result in overflow. + /// /// # Arguments /// /// * `timestamp` - The date on which to perform the operation @@ -533,12 +514,14 @@ impl TimestampSecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_day_time::(timestamp, delta, tz) } /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampSecondType /// + /// Returns `None` when it will result in overflow. + /// /// # Arguments /// /// * `timestamp` - The date on which to perform the operation @@ -548,7 +531,7 @@ impl TimestampSecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_month_day_nano::(timestamp, delta, tz) } } @@ -565,7 +548,7 @@ impl TimestampMicrosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_year_months::(timestamp, delta, tz) } @@ -580,7 +563,7 @@ impl TimestampMicrosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_day_time::(timestamp, delta, tz) } @@ -595,7 +578,7 @@ impl TimestampMicrosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_month_day_nano::(timestamp, delta, tz) } @@ -610,7 +593,7 @@ impl TimestampMicrosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_year_months::(timestamp, delta, tz) } @@ -625,7 +608,7 @@ impl TimestampMicrosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_day_time::(timestamp, delta, tz) } @@ -640,7 +623,7 @@ impl TimestampMicrosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_month_day_nano::(timestamp, delta, tz) } } @@ -657,7 +640,7 @@ impl TimestampMillisecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_year_months::(timestamp, delta, tz) } @@ -672,7 +655,7 @@ impl TimestampMillisecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_day_time::(timestamp, delta, tz) } @@ -687,7 +670,7 @@ impl TimestampMillisecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_month_day_nano::(timestamp, delta, tz) } @@ -702,7 +685,7 @@ impl TimestampMillisecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_year_months::(timestamp, delta, tz) } @@ -717,7 +700,7 @@ impl TimestampMillisecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_day_time::(timestamp, delta, tz) } @@ -732,7 +715,7 @@ impl TimestampMillisecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_month_day_nano::(timestamp, delta, tz) } } @@ -749,7 +732,7 @@ impl TimestampNanosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_year_months::(timestamp, delta, tz) } @@ -764,7 +747,7 @@ impl TimestampNanosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_day_time::(timestamp, delta, tz) } @@ -779,11 +762,11 @@ impl TimestampNanosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { add_month_day_nano::(timestamp, delta, tz) } - /// Subtracs the given IntervalYearMonthType to an arrow TimestampNanosecondType + /// Subtracts the given IntervalYearMonthType to an arrow TimestampNanosecondType /// /// # Arguments /// @@ -794,11 +777,11 @@ impl TimestampNanosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_year_months::(timestamp, delta, tz) } - /// Subtracs the given IntervalDayTimeType to an arrow TimestampNanosecondType + /// Subtracts the given IntervalDayTimeType to an arrow TimestampNanosecondType /// /// # Arguments /// @@ -809,11 +792,11 @@ impl TimestampNanosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_day_time::(timestamp, delta, tz) } - /// Subtracs the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType + /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType /// /// # Arguments /// @@ -824,7 +807,7 @@ impl TimestampNanosecondType { timestamp: ::Native, delta: ::Native, tz: Tz, - ) -> Result<::Native, ArrowError> { + ) -> Option<::Native> { subtract_month_day_nano::(timestamp, delta, tz) } }