1use std::cmp::Ordering;
21use std::fmt::Formatter;
22use std::sync::Arc;
23
24use arrow_array::cast::AsArray;
25use arrow_array::temporal_conversions::{NANOSECONDS, SECONDS_IN_DAY};
26use arrow_array::timezone::Tz;
27use arrow_array::types::*;
28use arrow_array::*;
29use arrow_buffer::{ArrowNativeType, IntervalDayTime, IntervalMonthDayNano};
30use arrow_schema::{ArrowError, DataType, IntervalUnit, TimeUnit};
31use num_traits::ToPrimitive;
32
33use crate::arity::{binary, try_binary};
34
35pub fn add(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
37 arithmetic_op(Op::Add, lhs, rhs)
38}
39
40pub fn add_wrapping(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
42 arithmetic_op(Op::AddWrapping, lhs, rhs)
43}
44
45pub fn sub(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
47 arithmetic_op(Op::Sub, lhs, rhs)
48}
49
50pub fn sub_wrapping(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
52 arithmetic_op(Op::SubWrapping, lhs, rhs)
53}
54
55pub fn mul(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
57 arithmetic_op(Op::Mul, lhs, rhs)
58}
59
60pub fn mul_wrapping(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
62 arithmetic_op(Op::MulWrapping, lhs, rhs)
63}
64
65pub fn div(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
70 arithmetic_op(Op::Div, lhs, rhs)
71}
72
73pub fn rem(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
80 arithmetic_op(Op::Rem, lhs, rhs)
81}
82
83macro_rules! neg_checked {
84 ($t:ty, $a:ident) => {{
85 let array = $a
86 .as_primitive::<$t>()
87 .try_unary::<_, $t, _>(|x| x.neg_checked())?;
88 Ok(Arc::new(array))
89 }};
90}
91
92macro_rules! neg_wrapping {
93 ($t:ty, $a:ident) => {{
94 let array = $a.as_primitive::<$t>().unary::<_, $t>(|x| x.neg_wrapping());
95 Ok(Arc::new(array))
96 }};
97}
98
99pub fn neg(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
104 use DataType::*;
105 use IntervalUnit::*;
106 use TimeUnit::*;
107
108 match array.data_type() {
109 Int8 => neg_checked!(Int8Type, array),
110 Int16 => neg_checked!(Int16Type, array),
111 Int32 => neg_checked!(Int32Type, array),
112 Int64 => neg_checked!(Int64Type, array),
113 Float16 => neg_wrapping!(Float16Type, array),
114 Float32 => neg_wrapping!(Float32Type, array),
115 Float64 => neg_wrapping!(Float64Type, array),
116 Decimal32(p, s) => {
117 let a = array
118 .as_primitive::<Decimal32Type>()
119 .try_unary::<_, Decimal32Type, _>(|x| x.neg_checked())?;
120
121 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
122 }
123 Decimal64(p, s) => {
124 let a = array
125 .as_primitive::<Decimal64Type>()
126 .try_unary::<_, Decimal64Type, _>(|x| x.neg_checked())?;
127
128 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
129 }
130 Decimal128(p, s) => {
131 let a = array
132 .as_primitive::<Decimal128Type>()
133 .try_unary::<_, Decimal128Type, _>(|x| x.neg_checked())?;
134
135 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
136 }
137 Decimal256(p, s) => {
138 let a = array
139 .as_primitive::<Decimal256Type>()
140 .try_unary::<_, Decimal256Type, _>(|x| x.neg_checked())?;
141
142 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
143 }
144 Duration(Second) => neg_checked!(DurationSecondType, array),
145 Duration(Millisecond) => neg_checked!(DurationMillisecondType, array),
146 Duration(Microsecond) => neg_checked!(DurationMicrosecondType, array),
147 Duration(Nanosecond) => neg_checked!(DurationNanosecondType, array),
148 Interval(YearMonth) => neg_checked!(IntervalYearMonthType, array),
149 Interval(DayTime) => {
150 let a = array
151 .as_primitive::<IntervalDayTimeType>()
152 .try_unary::<_, IntervalDayTimeType, ArrowError>(|x| {
153 let (days, ms) = IntervalDayTimeType::to_parts(x);
154 Ok(IntervalDayTimeType::make_value(
155 days.neg_checked()?,
156 ms.neg_checked()?,
157 ))
158 })?;
159 Ok(Arc::new(a))
160 }
161 Interval(MonthDayNano) => {
162 let a = array
163 .as_primitive::<IntervalMonthDayNanoType>()
164 .try_unary::<_, IntervalMonthDayNanoType, ArrowError>(|x| {
165 let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(x);
166 Ok(IntervalMonthDayNanoType::make_value(
167 months.neg_checked()?,
168 days.neg_checked()?,
169 nanos.neg_checked()?,
170 ))
171 })?;
172 Ok(Arc::new(a))
173 }
174 t => Err(ArrowError::InvalidArgumentError(format!(
175 "Invalid arithmetic operation: !{t}"
176 ))),
177 }
178}
179
180pub fn neg_wrapping(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
182 downcast_integer! {
183 array.data_type() => (neg_wrapping, array),
184 _ => neg(array),
185 }
186}
187
188#[derive(Debug, Copy, Clone)]
192enum Op {
193 AddWrapping,
194 Add,
195 SubWrapping,
196 Sub,
197 MulWrapping,
198 Mul,
199 Div,
200 Rem,
201}
202
203impl std::fmt::Display for Op {
204 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
205 match self {
206 Op::AddWrapping | Op::Add => write!(f, "+"),
207 Op::SubWrapping | Op::Sub => write!(f, "-"),
208 Op::MulWrapping | Op::Mul => write!(f, "*"),
209 Op::Div => write!(f, "/"),
210 Op::Rem => write!(f, "%"),
211 }
212 }
213}
214
215impl Op {
216 fn commutative(&self) -> bool {
217 matches!(
218 self,
219 Self::Add | Self::AddWrapping | Self::Mul | Self::MulWrapping
220 )
221 }
222}
223
224fn arithmetic_op(op: Op, lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
226 use DataType::*;
227 use IntervalUnit::*;
228 use TimeUnit::*;
229
230 macro_rules! integer_helper {
231 ($t:ty, $op:ident, $l:ident, $l_scalar:ident, $r:ident, $r_scalar:ident) => {
232 integer_op::<$t>($op, $l, $l_scalar, $r, $r_scalar)
233 };
234 }
235
236 let (l, l_scalar) = lhs.get();
237 let (r, r_scalar) = rhs.get();
238 downcast_integer! {
239 l.data_type(), r.data_type() => (integer_helper, op, l, l_scalar, r, r_scalar),
240 (Float16, Float16) => float_op::<Float16Type>(op, l, l_scalar, r, r_scalar),
241 (Float32, Float32) => float_op::<Float32Type>(op, l, l_scalar, r, r_scalar),
242 (Float64, Float64) => float_op::<Float64Type>(op, l, l_scalar, r, r_scalar),
243 (Timestamp(Second, _), _) => timestamp_op::<TimestampSecondType>(op, l, l_scalar, r, r_scalar),
244 (Timestamp(Millisecond, _), _) => timestamp_op::<TimestampMillisecondType>(op, l, l_scalar, r, r_scalar),
245 (Timestamp(Microsecond, _), _) => timestamp_op::<TimestampMicrosecondType>(op, l, l_scalar, r, r_scalar),
246 (Timestamp(Nanosecond, _), _) => timestamp_op::<TimestampNanosecondType>(op, l, l_scalar, r, r_scalar),
247 (Duration(Second), Duration(Second)) => duration_op::<DurationSecondType>(op, l, l_scalar, r, r_scalar),
248 (Duration(Millisecond), Duration(Millisecond)) => duration_op::<DurationMillisecondType>(op, l, l_scalar, r, r_scalar),
249 (Duration(Microsecond), Duration(Microsecond)) => duration_op::<DurationMicrosecondType>(op, l, l_scalar, r, r_scalar),
250 (Duration(Nanosecond), Duration(Nanosecond)) => duration_op::<DurationNanosecondType>(op, l, l_scalar, r, r_scalar),
251 (Interval(YearMonth), Interval(YearMonth) | Int64) => interval_op::<IntervalYearMonthType>(op, l, l_scalar, r, r_scalar),
252 (Interval(DayTime), Interval(DayTime) | Int64) => interval_op::<IntervalDayTimeType>(op, l, l_scalar, r, r_scalar),
253 (Interval(MonthDayNano), Interval(MonthDayNano) | Int64) => interval_op::<IntervalMonthDayNanoType>(op, l, l_scalar, r, r_scalar),
254 (Interval(MonthDayNano), Float64) => interval_f64_op(op, l, l_scalar, r, r_scalar),
255 (Date32, _) => date_op::<Date32Type>(op, l, l_scalar, r, r_scalar),
256 (Date64, _) => date_op::<Date64Type>(op, l, l_scalar, r, r_scalar),
257 (Decimal32(_, _), Decimal32(_, _)) => decimal_op::<Decimal32Type>(op, l, l_scalar, r, r_scalar),
258 (Decimal64(_, _), Decimal64(_, _)) => decimal_op::<Decimal64Type>(op, l, l_scalar, r, r_scalar),
259 (Decimal128(_, _), Decimal128(_, _)) => decimal_op::<Decimal128Type>(op, l, l_scalar, r, r_scalar),
260 (Decimal256(_, _), Decimal256(_, _)) => decimal_op::<Decimal256Type>(op, l, l_scalar, r, r_scalar),
261 (l_t, r_t) => match (l_t, r_t) {
262 (Duration(_) | Interval(_), Date32 | Date64 | Timestamp(_, _)) if op.commutative() => {
263 arithmetic_op(op, rhs, lhs)
264 }
265 (Int64, Interval(_)) | (Float64, Interval(MonthDayNano))
266 if matches!(op, Op::Mul) =>
267 {
268 arithmetic_op(op, rhs, lhs)
269 }
270 _ => Err(ArrowError::InvalidArgumentError(
271 format!("Invalid arithmetic operation: {l_t} {op} {r_t}")
272 ))
273 }
274 }
275}
276
277macro_rules! op {
279 ($l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {
280 match ($l_s, $r_s) {
281 (true, true) | (false, false) => binary($l, $r, |$l, $r| $op)?,
282 (true, false) => match ($l.null_count() == 0).then(|| $l.value(0)) {
283 None => PrimitiveArray::new_null($r.len()),
284 Some($l) => $r.unary(|$r| $op),
285 },
286 (false, true) => match ($r.null_count() == 0).then(|| $r.value(0)) {
287 None => PrimitiveArray::new_null($l.len()),
288 Some($r) => $l.unary(|$l| $op),
289 },
290 }
291 };
292}
293
294macro_rules! op_ref {
296 ($t:ty, $l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {{
297 let array: PrimitiveArray<$t> = op!($l, $l_s, $r, $r_s, $op);
298 Arc::new(array)
299 }};
300}
301
302macro_rules! try_op {
304 ($l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {
305 match ($l_s, $r_s) {
306 (true, true) | (false, false) => try_binary($l, $r, |$l, $r| $op)?,
307 (true, false) => match ($l.null_count() == 0).then(|| $l.value(0)) {
308 None => PrimitiveArray::new_null($r.len()),
309 Some($l) => $r.try_unary(|$r| $op)?,
310 },
311 (false, true) => match ($r.null_count() == 0).then(|| $r.value(0)) {
312 None => PrimitiveArray::new_null($l.len()),
313 Some($r) => $l.try_unary(|$l| $op)?,
314 },
315 }
316 };
317}
318
319macro_rules! try_op_ref {
321 ($t:ty, $l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {{
322 let array: PrimitiveArray<$t> = try_op!($l, $l_s, $r, $r_s, $op);
323 Arc::new(array)
324 }};
325}
326
327fn integer_op<T: ArrowPrimitiveType>(
329 op: Op,
330 l: &dyn Array,
331 l_s: bool,
332 r: &dyn Array,
333 r_s: bool,
334) -> Result<ArrayRef, ArrowError> {
335 let l = l.as_primitive::<T>();
336 let r = r.as_primitive::<T>();
337 let array: PrimitiveArray<T> = match op {
338 Op::AddWrapping => op!(l, l_s, r, r_s, l.add_wrapping(r)),
339 Op::Add => try_op!(l, l_s, r, r_s, l.add_checked(r)),
340 Op::SubWrapping => op!(l, l_s, r, r_s, l.sub_wrapping(r)),
341 Op::Sub => try_op!(l, l_s, r, r_s, l.sub_checked(r)),
342 Op::MulWrapping => op!(l, l_s, r, r_s, l.mul_wrapping(r)),
343 Op::Mul => try_op!(l, l_s, r, r_s, l.mul_checked(r)),
344 Op::Div => try_op!(l, l_s, r, r_s, l.div_checked(r)),
345 Op::Rem => try_op!(l, l_s, r, r_s, {
346 if r.is_zero() {
347 Err(ArrowError::DivideByZero)
348 } else {
349 Ok(l.mod_wrapping(r))
350 }
351 }),
352 };
353 Ok(Arc::new(array))
354}
355
356fn float_op<T: ArrowPrimitiveType>(
358 op: Op,
359 l: &dyn Array,
360 l_s: bool,
361 r: &dyn Array,
362 r_s: bool,
363) -> Result<ArrayRef, ArrowError> {
364 let l = l.as_primitive::<T>();
365 let r = r.as_primitive::<T>();
366 let array: PrimitiveArray<T> = match op {
367 Op::AddWrapping | Op::Add => op!(l, l_s, r, r_s, l.add_wrapping(r)),
368 Op::SubWrapping | Op::Sub => op!(l, l_s, r, r_s, l.sub_wrapping(r)),
369 Op::MulWrapping | Op::Mul => op!(l, l_s, r, r_s, l.mul_wrapping(r)),
370 Op::Div => op!(l, l_s, r, r_s, l.div_wrapping(r)),
371 Op::Rem => op!(l, l_s, r, r_s, l.mod_wrapping(r)),
372 };
373 Ok(Arc::new(array))
374}
375
376trait TimestampOp: ArrowTimestampType {
378 type Duration: ArrowPrimitiveType<Native = i64>;
379
380 fn add_year_month(timestamp: i64, delta: i32, tz: Tz) -> Option<i64>;
381 fn add_day_time(timestamp: i64, delta: IntervalDayTime, tz: Tz) -> Option<i64>;
382 fn add_month_day_nano(timestamp: i64, delta: IntervalMonthDayNano, tz: Tz) -> Option<i64>;
383
384 fn sub_year_month(timestamp: i64, delta: i32, tz: Tz) -> Option<i64>;
385 fn sub_day_time(timestamp: i64, delta: IntervalDayTime, tz: Tz) -> Option<i64>;
386 fn sub_month_day_nano(timestamp: i64, delta: IntervalMonthDayNano, tz: Tz) -> Option<i64>;
387}
388
389macro_rules! timestamp {
390 ($t:ty, $d:ty) => {
391 impl TimestampOp for $t {
392 type Duration = $d;
393
394 fn add_year_month(left: i64, right: i32, tz: Tz) -> Option<i64> {
395 Self::add_year_months(left, right, tz)
396 }
397
398 fn add_day_time(left: i64, right: IntervalDayTime, tz: Tz) -> Option<i64> {
399 Self::add_day_time(left, right, tz)
400 }
401
402 fn add_month_day_nano(left: i64, right: IntervalMonthDayNano, tz: Tz) -> Option<i64> {
403 Self::add_month_day_nano(left, right, tz)
404 }
405
406 fn sub_year_month(left: i64, right: i32, tz: Tz) -> Option<i64> {
407 Self::subtract_year_months(left, right, tz)
408 }
409
410 fn sub_day_time(left: i64, right: IntervalDayTime, tz: Tz) -> Option<i64> {
411 Self::subtract_day_time(left, right, tz)
412 }
413
414 fn sub_month_day_nano(left: i64, right: IntervalMonthDayNano, tz: Tz) -> Option<i64> {
415 Self::subtract_month_day_nano(left, right, tz)
416 }
417 }
418 };
419}
420timestamp!(TimestampSecondType, DurationSecondType);
421timestamp!(TimestampMillisecondType, DurationMillisecondType);
422timestamp!(TimestampMicrosecondType, DurationMicrosecondType);
423timestamp!(TimestampNanosecondType, DurationNanosecondType);
424
425fn timestamp_op<T: TimestampOp>(
427 op: Op,
428 l: &dyn Array,
429 l_s: bool,
430 r: &dyn Array,
431 r_s: bool,
432) -> Result<ArrayRef, ArrowError> {
433 use DataType::*;
434 use IntervalUnit::*;
435
436 let l = l.as_primitive::<T>();
437 let l_tz: Tz = l.timezone().unwrap_or("+00:00").parse()?;
438
439 let array: PrimitiveArray<T> = match (op, r.data_type()) {
440 (Op::Sub | Op::SubWrapping, Timestamp(unit, _)) if unit == &T::UNIT => {
441 let r = r.as_primitive::<T>();
442 return Ok(try_op_ref!(T::Duration, l, l_s, r, r_s, l.sub_checked(r)));
443 }
444
445 (Op::Add | Op::AddWrapping, Duration(unit)) if unit == &T::UNIT => {
446 let r = r.as_primitive::<T::Duration>();
447 try_op!(l, l_s, r, r_s, l.add_checked(r))
448 }
449 (Op::Sub | Op::SubWrapping, Duration(unit)) if unit == &T::UNIT => {
450 let r = r.as_primitive::<T::Duration>();
451 try_op!(l, l_s, r, r_s, l.sub_checked(r))
452 }
453
454 (Op::Add | Op::AddWrapping, Interval(YearMonth)) => {
455 let r = r.as_primitive::<IntervalYearMonthType>();
456 try_op!(
457 l,
458 l_s,
459 r,
460 r_s,
461 T::add_year_month(l, r, l_tz).ok_or(ArrowError::ComputeError(
462 "Timestamp out of range".to_string()
463 ))
464 )
465 }
466 (Op::Sub | Op::SubWrapping, Interval(YearMonth)) => {
467 let r = r.as_primitive::<IntervalYearMonthType>();
468 try_op!(
469 l,
470 l_s,
471 r,
472 r_s,
473 T::sub_year_month(l, r, l_tz).ok_or(ArrowError::ComputeError(
474 "Timestamp out of range".to_string()
475 ))
476 )
477 }
478
479 (Op::Add | Op::AddWrapping, Interval(DayTime)) => {
480 let r = r.as_primitive::<IntervalDayTimeType>();
481 try_op!(
482 l,
483 l_s,
484 r,
485 r_s,
486 T::add_day_time(l, r, l_tz).ok_or(ArrowError::ComputeError(
487 "Timestamp out of range".to_string()
488 ))
489 )
490 }
491 (Op::Sub | Op::SubWrapping, Interval(DayTime)) => {
492 let r = r.as_primitive::<IntervalDayTimeType>();
493 try_op!(
494 l,
495 l_s,
496 r,
497 r_s,
498 T::sub_day_time(l, r, l_tz).ok_or(ArrowError::ComputeError(
499 "Timestamp out of range".to_string()
500 ))
501 )
502 }
503
504 (Op::Add | Op::AddWrapping, Interval(MonthDayNano)) => {
505 let r = r.as_primitive::<IntervalMonthDayNanoType>();
506 try_op!(
507 l,
508 l_s,
509 r,
510 r_s,
511 T::add_month_day_nano(l, r, l_tz).ok_or(ArrowError::ComputeError(
512 "Timestamp out of range".to_string()
513 ))
514 )
515 }
516 (Op::Sub | Op::SubWrapping, Interval(MonthDayNano)) => {
517 let r = r.as_primitive::<IntervalMonthDayNanoType>();
518 try_op!(
519 l,
520 l_s,
521 r,
522 r_s,
523 T::sub_month_day_nano(l, r, l_tz).ok_or(ArrowError::ComputeError(
524 "Timestamp out of range".to_string()
525 ))
526 )
527 }
528 _ => {
529 return Err(ArrowError::InvalidArgumentError(format!(
530 "Invalid timestamp arithmetic operation: {} {op} {}",
531 l.data_type(),
532 r.data_type()
533 )));
534 }
535 };
536 Ok(Arc::new(array.with_timezone_opt(l.timezone())))
537}
538
539trait DateOp: ArrowTemporalType {
541 fn add_year_month(timestamp: Self::Native, delta: i32) -> Result<Self::Native, ArrowError>;
542 fn add_day_time(
543 timestamp: Self::Native,
544 delta: IntervalDayTime,
545 ) -> Result<Self::Native, ArrowError>;
546 fn add_month_day_nano(
547 timestamp: Self::Native,
548 delta: IntervalMonthDayNano,
549 ) -> Result<Self::Native, ArrowError>;
550
551 fn sub_year_month(timestamp: Self::Native, delta: i32) -> Result<Self::Native, ArrowError>;
552 fn sub_day_time(
553 timestamp: Self::Native,
554 delta: IntervalDayTime,
555 ) -> Result<Self::Native, ArrowError>;
556 fn sub_month_day_nano(
557 timestamp: Self::Native,
558 delta: IntervalMonthDayNano,
559 ) -> Result<Self::Native, ArrowError>;
560}
561
562macro_rules! date {
563 ($t:ty) => {
564 impl DateOp for $t {
565 fn add_year_month(left: Self::Native, right: i32) -> Result<Self::Native, ArrowError> {
566 Self::add_year_months_opt(left, right).ok_or_else(|| {
567 ArrowError::ComputeError(format!(
568 "Date arithmetic overflow: {left} + {right} months"
569 ))
570 })
571 }
572
573 fn add_day_time(
574 left: Self::Native,
575 right: IntervalDayTime,
576 ) -> Result<Self::Native, ArrowError> {
577 Self::add_day_time_opt(left, right).ok_or_else(|| {
578 ArrowError::ComputeError(format!(
579 "Date arithmetic overflow: {left} + {right:?}"
580 ))
581 })
582 }
583
584 fn add_month_day_nano(
585 left: Self::Native,
586 right: IntervalMonthDayNano,
587 ) -> Result<Self::Native, ArrowError> {
588 Self::add_month_day_nano_opt(left, right).ok_or_else(|| {
589 ArrowError::ComputeError(format!(
590 "Date arithmetic overflow: {left} + {right:?}"
591 ))
592 })
593 }
594
595 fn sub_year_month(left: Self::Native, right: i32) -> Result<Self::Native, ArrowError> {
596 Self::subtract_year_months_opt(left, right).ok_or_else(|| {
597 ArrowError::ComputeError(format!(
598 "Date arithmetic overflow: {left} - {right} months"
599 ))
600 })
601 }
602
603 fn sub_day_time(
604 left: Self::Native,
605 right: IntervalDayTime,
606 ) -> Result<Self::Native, ArrowError> {
607 Self::subtract_day_time_opt(left, right).ok_or_else(|| {
608 ArrowError::ComputeError(format!(
609 "Date arithmetic overflow: {left} - {right:?}"
610 ))
611 })
612 }
613
614 fn sub_month_day_nano(
615 left: Self::Native,
616 right: IntervalMonthDayNano,
617 ) -> Result<Self::Native, ArrowError> {
618 Self::subtract_month_day_nano_opt(left, right).ok_or_else(|| {
619 ArrowError::ComputeError(format!(
620 "Date arithmetic overflow: {left} - {right:?}"
621 ))
622 })
623 }
624 }
625 };
626}
627
628date!(Date32Type);
629date!(Date64Type);
630
631trait IntervalOp: ArrowPrimitiveType {
633 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError>;
634 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError>;
635 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError>;
636}
637
638fn mul_i32_i64(left: i32, right: i64) -> Result<i32, ArrowError> {
639 let value = i64::from(left).mul_checked(right)?;
640 i32::try_from(value).map_err(|_| {
641 ArrowError::ArithmeticOverflow(format!("Overflow happened on: {left} * {right}"))
642 })
643}
644
645impl IntervalOp for IntervalYearMonthType {
646 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
647 left.add_checked(right)
648 }
649
650 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
651 left.sub_checked(right)
652 }
653
654 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError> {
655 mul_i32_i64(left, right)
656 }
657}
658
659impl IntervalOp for IntervalDayTimeType {
660 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
661 let (l_days, l_ms) = Self::to_parts(left);
662 let (r_days, r_ms) = Self::to_parts(right);
663 let days = l_days.add_checked(r_days)?;
664 let ms = l_ms.add_checked(r_ms)?;
665 Ok(Self::make_value(days, ms))
666 }
667
668 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
669 let (l_days, l_ms) = Self::to_parts(left);
670 let (r_days, r_ms) = Self::to_parts(right);
671 let days = l_days.sub_checked(r_days)?;
672 let ms = l_ms.sub_checked(r_ms)?;
673 Ok(Self::make_value(days, ms))
674 }
675
676 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError> {
677 let (days, ms) = Self::to_parts(left);
678 Ok(Self::make_value(
679 mul_i32_i64(days, right)?,
680 mul_i32_i64(ms, right)?,
681 ))
682 }
683}
684
685impl IntervalOp for IntervalMonthDayNanoType {
686 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
687 let (l_months, l_days, l_nanos) = Self::to_parts(left);
688 let (r_months, r_days, r_nanos) = Self::to_parts(right);
689 let months = l_months.add_checked(r_months)?;
690 let days = l_days.add_checked(r_days)?;
691 let nanos = l_nanos.add_checked(r_nanos)?;
692 Ok(Self::make_value(months, days, nanos))
693 }
694
695 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
696 let (l_months, l_days, l_nanos) = Self::to_parts(left);
697 let (r_months, r_days, r_nanos) = Self::to_parts(right);
698 let months = l_months.sub_checked(r_months)?;
699 let days = l_days.sub_checked(r_days)?;
700 let nanos = l_nanos.sub_checked(r_nanos)?;
701 Ok(Self::make_value(months, days, nanos))
702 }
703
704 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError> {
705 let (months, days, nanos) = Self::to_parts(left);
706 Ok(Self::make_value(
707 mul_i32_i64(months, right)?,
708 mul_i32_i64(days, right)?,
709 nanos.mul_checked(right)?,
710 ))
711 }
712}
713
714fn interval_mul_op<T: IntervalOp>(
715 interval: &dyn Array,
716 interval_scalar: bool,
717 factor: &dyn Array,
718 factor_scalar: bool,
719) -> Result<ArrayRef, ArrowError> {
720 let interval = interval.as_primitive::<T>();
721 let factor = factor.as_primitive::<Int64Type>();
722 Ok(try_op_ref!(
723 T,
724 interval,
725 interval_scalar,
726 factor,
727 factor_scalar,
728 T::mul_i64(interval, factor)
729 ))
730}
731
732fn interval_mul_f64(
748 interval: IntervalMonthDayNano,
749 factor: f64,
750) -> Result<IntervalMonthDayNano, ArrowError> {
751 const DAYS_PER_MONTH: f64 = 30.;
752 const NANOS_PER_SECOND: f64 = NANOSECONDS as f64;
753 const SECONDS_PER_DAY: f64 = SECONDS_IN_DAY as f64;
754
755 if factor.fract() == 0.
757 && let Some(factor) = ToPrimitive::to_i64(&factor)
758 {
759 return IntervalMonthDayNanoType::mul_i64(interval, factor);
760 }
761
762 let overflow =
767 |component| ArrowError::ArithmeticOverflow(format!("Overflow in interval {component}"));
768 let timestamp_round =
769 |value: f64| (value * NANOS_PER_SECOND).round_ties_even() / NANOS_PER_SECOND;
770
771 let months_product = f64::from(interval.months) * factor;
772 if !months_product.is_finite()
773 || months_product < f64::from(i32::MIN)
774 || months_product > f64::from(i32::MAX)
775 {
776 return Err(overflow("months"));
777 }
778 let months = months_product.to_i32().ok_or_else(|| overflow("months"))?;
779
780 let days_product = f64::from(interval.days) * factor;
781 if !days_product.is_finite()
782 || days_product < f64::from(i32::MIN)
783 || days_product > f64::from(i32::MAX)
784 {
785 return Err(overflow("days"));
786 }
787 let mut days = days_product.to_i32().ok_or_else(|| overflow("days"))?;
788
789 let month_remainder = timestamp_round(months_product.fract() * DAYS_PER_MONTH);
790 let month_remainder_days = month_remainder
791 .to_i32()
792 .ok_or_else(|| overflow("month remainder"))?;
793 let mut seconds_remainder =
794 timestamp_round((days_product.fract() + month_remainder.fract()) * SECONDS_PER_DAY);
795
796 if seconds_remainder.abs() >= SECONDS_PER_DAY {
797 let remainder_days = (seconds_remainder / SECONDS_PER_DAY)
798 .to_i32()
799 .ok_or_else(|| overflow("day remainder"))?;
800 days = days
801 .checked_add(remainder_days)
802 .ok_or_else(|| overflow("days"))?;
803 seconds_remainder -= f64::from(remainder_days) * SECONDS_PER_DAY;
804 }
805 days = days
806 .checked_add(month_remainder_days)
807 .ok_or_else(|| overflow("days"))?;
808
809 let nanoseconds = ((interval.nanoseconds as f64) * factor
810 + seconds_remainder * NANOS_PER_SECOND)
811 .round_ties_even();
812 let nanoseconds = ToPrimitive::to_i64(&nanoseconds).ok_or_else(|| {
813 ArrowError::ArithmeticOverflow(format!("Overflow in interval nanoseconds: {nanoseconds}"))
814 })?;
815
816 Ok(IntervalMonthDayNano::new(months, days, nanoseconds))
817}
818
819fn interval_f64_op(
820 op: Op,
821 interval: &dyn Array,
822 interval_scalar: bool,
823 factor: &dyn Array,
824 factor_scalar: bool,
825) -> Result<ArrayRef, ArrowError> {
826 let interval = interval.as_primitive::<IntervalMonthDayNanoType>();
827 let factor = factor.as_primitive::<Float64Type>();
828 Ok(try_op_ref!(
829 IntervalMonthDayNanoType,
830 interval,
831 interval_scalar,
832 factor,
833 factor_scalar,
834 {
835 match op {
836 Op::Mul => interval_mul_f64(interval, factor),
837 Op::Div if factor == 0. => Err(ArrowError::DivideByZero),
838 Op::Div => interval_mul_f64(interval, 1. / factor),
841 _ => Err(ArrowError::InvalidArgumentError(format!(
842 "Invalid interval arithmetic operation: Interval(MonthDayNano) {op} Float64"
843 ))),
844 }
845 }
846 ))
847}
848
849fn interval_op<T: IntervalOp>(
851 op: Op,
852 l: &dyn Array,
853 l_s: bool,
854 r: &dyn Array,
855 r_s: bool,
856) -> Result<ArrayRef, ArrowError> {
857 match (op, r.data_type()) {
858 (Op::Add | Op::AddWrapping, data_type) if data_type == l.data_type() => {
859 let l = l.as_primitive::<T>();
860 let r = r.as_primitive::<T>();
861 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add(l, r)))
862 }
863 (Op::Sub | Op::SubWrapping, data_type) if data_type == l.data_type() => {
864 let l = l.as_primitive::<T>();
865 let r = r.as_primitive::<T>();
866 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub(l, r)))
867 }
868 (Op::Mul, DataType::Int64) => interval_mul_op::<T>(l, l_s, r, r_s),
869 _ => Err(ArrowError::InvalidArgumentError(format!(
870 "Invalid interval arithmetic operation: {} {op} {}",
871 l.data_type(),
872 r.data_type()
873 ))),
874 }
875}
876
877fn duration_op<T: ArrowPrimitiveType>(
878 op: Op,
879 l: &dyn Array,
880 l_s: bool,
881 r: &dyn Array,
882 r_s: bool,
883) -> Result<ArrayRef, ArrowError> {
884 let l = l.as_primitive::<T>();
885 let r = r.as_primitive::<T>();
886 match op {
887 Op::Add | Op::AddWrapping => Ok(try_op_ref!(T, l, l_s, r, r_s, l.add_checked(r))),
888 Op::Sub | Op::SubWrapping => Ok(try_op_ref!(T, l, l_s, r, r_s, l.sub_checked(r))),
889 _ => Err(ArrowError::InvalidArgumentError(format!(
890 "Invalid duration arithmetic operation: {} {op} {}",
891 l.data_type(),
892 r.data_type()
893 ))),
894 }
895}
896
897fn date_op<T: DateOp>(
899 op: Op,
900 l: &dyn Array,
901 l_s: bool,
902 r: &dyn Array,
903 r_s: bool,
904) -> Result<ArrayRef, ArrowError> {
905 use DataType::*;
906 use IntervalUnit::*;
907
908 const NUM_SECONDS_IN_DAY: i64 = 60 * 60 * 24;
909
910 let r_t = r.data_type();
911 match (T::DATA_TYPE, op, r_t) {
912 (Date32, Op::Sub | Op::SubWrapping, Date32) => {
913 let l = l.as_primitive::<Date32Type>();
914 let r = r.as_primitive::<Date32Type>();
915 return Ok(op_ref!(
916 DurationSecondType,
917 l,
918 l_s,
919 r,
920 r_s,
921 ((l as i64) - (r as i64)) * NUM_SECONDS_IN_DAY
922 ));
923 }
924 (Date64, Op::Sub | Op::SubWrapping, Date64) => {
925 let l = l.as_primitive::<Date64Type>();
926 let r = r.as_primitive::<Date64Type>();
927 let result = try_op_ref!(DurationMillisecondType, l, l_s, r, r_s, l.sub_checked(r));
928 return Ok(result);
929 }
930 _ => {}
931 }
932
933 let l = l.as_primitive::<T>();
934 match (op, r_t) {
935 (Op::Add | Op::AddWrapping, Interval(YearMonth)) => {
936 let r = r.as_primitive::<IntervalYearMonthType>();
937 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add_year_month(l, r)))
938 }
939 (Op::Sub | Op::SubWrapping, Interval(YearMonth)) => {
940 let r = r.as_primitive::<IntervalYearMonthType>();
941 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub_year_month(l, r)))
942 }
943
944 (Op::Add | Op::AddWrapping, Interval(DayTime)) => {
945 let r = r.as_primitive::<IntervalDayTimeType>();
946 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add_day_time(l, r)))
947 }
948 (Op::Sub | Op::SubWrapping, Interval(DayTime)) => {
949 let r = r.as_primitive::<IntervalDayTimeType>();
950 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub_day_time(l, r)))
951 }
952
953 (Op::Add | Op::AddWrapping, Interval(MonthDayNano)) => {
954 let r = r.as_primitive::<IntervalMonthDayNanoType>();
955 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add_month_day_nano(l, r)))
956 }
957 (Op::Sub | Op::SubWrapping, Interval(MonthDayNano)) => {
958 let r = r.as_primitive::<IntervalMonthDayNanoType>();
959 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub_month_day_nano(l, r)))
960 }
961
962 _ => Err(ArrowError::InvalidArgumentError(format!(
963 "Invalid date arithmetic operation: {} {op} {}",
964 l.data_type(),
965 r.data_type()
966 ))),
967 }
968}
969
970fn decimal_op<T: DecimalType>(
972 op: Op,
973 l: &dyn Array,
974 l_s: bool,
975 r: &dyn Array,
976 r_s: bool,
977) -> Result<ArrayRef, ArrowError> {
978 let l = l.as_primitive::<T>();
979 let r = r.as_primitive::<T>();
980
981 let (p1, s1, p2, s2) = match (l.data_type(), r.data_type()) {
982 (DataType::Decimal32(p1, s1), DataType::Decimal32(p2, s2)) => (p1, s1, p2, s2),
983 (DataType::Decimal64(p1, s1), DataType::Decimal64(p2, s2)) => (p1, s1, p2, s2),
984 (DataType::Decimal128(p1, s1), DataType::Decimal128(p2, s2)) => (p1, s1, p2, s2),
985 (DataType::Decimal256(p1, s1), DataType::Decimal256(p2, s2)) => (p1, s1, p2, s2),
986 _ => unreachable!(),
987 };
988
989 let array: PrimitiveArray<T> = match op {
992 Op::Add | Op::AddWrapping | Op::Sub | Op::SubWrapping => {
993 let result_scale = *s1.max(s2);
995
996 let result_precision =
998 (result_scale.saturating_add((*p1 as i8 - s1).max(*p2 as i8 - s2)) as u8)
999 .saturating_add(1)
1000 .min(T::MAX_PRECISION);
1001
1002 let l_mul = T::Native::usize_as(10).pow_checked((result_scale - s1) as _)?;
1003 let r_mul = T::Native::usize_as(10).pow_checked((result_scale - s2) as _)?;
1004
1005 match op {
1006 Op::Add | Op::AddWrapping if s1 == s2 => {
1008 try_op!(l, l_s, r, r_s, l.add_checked(r))
1009 }
1010 Op::Sub | Op::SubWrapping if s1 == s2 => {
1011 try_op!(l, l_s, r, r_s, l.sub_checked(r))
1012 }
1013 Op::Add | Op::AddWrapping => {
1014 try_op!(
1015 l,
1016 l_s,
1017 r,
1018 r_s,
1019 l.mul_checked(l_mul)?.add_checked(r.mul_checked(r_mul)?)
1020 )
1021 }
1022 Op::Sub | Op::SubWrapping => {
1023 try_op!(
1024 l,
1025 l_s,
1026 r,
1027 r_s,
1028 l.mul_checked(l_mul)?.sub_checked(r.mul_checked(r_mul)?)
1029 )
1030 }
1031 _ => unreachable!(),
1032 }
1033 .with_precision_and_scale(result_precision, result_scale)?
1034 }
1035 Op::Mul | Op::MulWrapping => {
1036 let result_precision = p1.saturating_add(p2 + 1).min(T::MAX_PRECISION);
1037 let result_scale = s1.saturating_add(*s2);
1038 if result_scale > T::MAX_SCALE {
1039 return Err(ArrowError::InvalidArgumentError(format!(
1042 "Output scale of {} {op} {} would exceed max scale of {}",
1043 l.data_type(),
1044 r.data_type(),
1045 T::MAX_SCALE
1046 )));
1047 }
1048
1049 try_op!(l, l_s, r, r_s, l.mul_checked(r))
1050 .with_precision_and_scale(result_precision, result_scale)?
1051 }
1052
1053 Op::Div => {
1054 let result_scale = s1.saturating_add(4).min(T::MAX_SCALE);
1057 let mul_pow = result_scale - s1 + s2;
1058
1059 let result_precision = (mul_pow.saturating_add(*p1 as i8) as u8).min(T::MAX_PRECISION);
1061
1062 let (l_mul, r_mul) = match mul_pow.cmp(&0) {
1063 Ordering::Greater => (
1064 T::Native::usize_as(10).pow_checked(mul_pow as _)?,
1065 T::Native::ONE,
1066 ),
1067 Ordering::Equal => (T::Native::ONE, T::Native::ONE),
1068 Ordering::Less => (
1069 T::Native::ONE,
1070 T::Native::usize_as(10).pow_checked(mul_pow.neg_wrapping() as _)?,
1071 ),
1072 };
1073
1074 try_op!(
1075 l,
1076 l_s,
1077 r,
1078 r_s,
1079 l.mul_checked(l_mul)?.div_checked(r.mul_checked(r_mul)?)
1080 )
1081 .with_precision_and_scale(result_precision, result_scale)?
1082 }
1083
1084 Op::Rem => {
1085 let result_scale = *s1.max(s2);
1087 let result_precision =
1089 (result_scale.saturating_add((*p1 as i8 - s1).min(*p2 as i8 - s2)) as u8)
1090 .min(T::MAX_PRECISION);
1091
1092 let l_mul = T::Native::usize_as(10).pow_wrapping((result_scale - s1) as _);
1093 let r_mul = T::Native::usize_as(10).pow_wrapping((result_scale - s2) as _);
1094
1095 try_op!(
1096 l,
1097 l_s,
1098 r,
1099 r_s,
1100 l.mul_checked(l_mul)?.mod_checked(r.mul_checked(r_mul)?)
1101 )
1102 .with_precision_and_scale(result_precision, result_scale)?
1103 }
1104 };
1105
1106 Ok(Arc::new(array))
1107}
1108
1109#[cfg(test)]
1110mod tests {
1111 use super::*;
1112 use arrow_array::temporal_conversions::{as_date, as_datetime};
1113 use arrow_buffer::{ScalarBuffer, i256};
1114 use chrono::{DateTime, NaiveDate};
1115
1116 const MAX_VALID_DATE: NaiveDate = NaiveDate::from_ymd_opt(262142, 12, 31).unwrap();
1118 const MIN_VALID_DATE: NaiveDate = NaiveDate::from_ymd_opt(-262143, 1, 1).unwrap();
1119 const MAX_VALID_MILLIS: i64 = date_to_millis(MAX_VALID_DATE);
1120 const MIN_VALID_MILLIS: i64 = date_to_millis(MIN_VALID_DATE);
1121 const MAX_VALID_DAYS: i32 = date_to_days(MAX_VALID_DATE);
1122 const MIN_VALID_DAYS: i32 = date_to_days(MIN_VALID_DATE);
1123 const EPOCH: NaiveDate = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1124 const YEAR_2000: NaiveDate = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap();
1125
1126 const fn date_to_millis(date: NaiveDate) -> i64 {
1127 date.signed_duration_since(EPOCH).num_milliseconds()
1128 }
1129
1130 const fn date_to_days(date: NaiveDate) -> i32 {
1131 date.signed_duration_since(EPOCH).num_days() as i32
1132 }
1133
1134 fn test_neg_primitive<T: ArrowPrimitiveType>(
1135 input: &[T::Native],
1136 out: Result<&[T::Native], &str>,
1137 ) {
1138 let a = PrimitiveArray::<T>::new(ScalarBuffer::from(input.to_vec()), None);
1139 match out {
1140 Ok(expected) => {
1141 let result = neg(&a).unwrap();
1142 assert_eq!(result.as_primitive::<T>().values(), expected);
1143 }
1144 Err(e) => {
1145 let err = neg(&a).unwrap_err().to_string();
1146 assert_eq!(e, err);
1147 }
1148 }
1149 }
1150
1151 #[test]
1152 fn test_neg() {
1153 let input = &[1, -5, 2, 693, 3929];
1154 let output = &[-1, 5, -2, -693, -3929];
1155 test_neg_primitive::<Int32Type>(input, Ok(output));
1156
1157 let input = &[1, -5, 2, 693, 3929];
1158 let output = &[-1, 5, -2, -693, -3929];
1159 test_neg_primitive::<Int64Type>(input, Ok(output));
1160 test_neg_primitive::<DurationSecondType>(input, Ok(output));
1161 test_neg_primitive::<DurationMillisecondType>(input, Ok(output));
1162 test_neg_primitive::<DurationMicrosecondType>(input, Ok(output));
1163 test_neg_primitive::<DurationNanosecondType>(input, Ok(output));
1164
1165 let input = &[f32::MAX, f32::MIN, f32::INFINITY, 1.3, 0.5];
1166 let output = &[f32::MIN, f32::MAX, f32::NEG_INFINITY, -1.3, -0.5];
1167 test_neg_primitive::<Float32Type>(input, Ok(output));
1168
1169 test_neg_primitive::<Int32Type>(
1170 &[i32::MIN],
1171 Err("Arithmetic overflow: Overflow happened on: - -2147483648"),
1172 );
1173 test_neg_primitive::<Int64Type>(
1174 &[i64::MIN],
1175 Err("Arithmetic overflow: Overflow happened on: - -9223372036854775808"),
1176 );
1177 test_neg_primitive::<DurationSecondType>(
1178 &[i64::MIN],
1179 Err("Arithmetic overflow: Overflow happened on: - -9223372036854775808"),
1180 );
1181
1182 let r = neg_wrapping(&Int32Array::from(vec![i32::MIN])).unwrap();
1183 assert_eq!(r.as_primitive::<Int32Type>().value(0), i32::MIN);
1184
1185 let r = neg_wrapping(&Int64Array::from(vec![i64::MIN])).unwrap();
1186 assert_eq!(r.as_primitive::<Int64Type>().value(0), i64::MIN);
1187
1188 let err = neg_wrapping(&DurationSecondArray::from(vec![i64::MIN]))
1189 .unwrap_err()
1190 .to_string();
1191
1192 assert_eq!(
1193 err,
1194 "Arithmetic overflow: Overflow happened on: - -9223372036854775808"
1195 );
1196
1197 let a = Decimal32Array::from(vec![1, 3, -44, 2, 4])
1198 .with_precision_and_scale(9, 6)
1199 .unwrap();
1200
1201 let r = neg(&a).unwrap();
1202 assert_eq!(r.data_type(), a.data_type());
1203 assert_eq!(
1204 r.as_primitive::<Decimal32Type>().values(),
1205 &[-1, -3, 44, -2, -4]
1206 );
1207
1208 let a = Decimal64Array::from(vec![1, 3, -44, 2, 4])
1209 .with_precision_and_scale(9, 6)
1210 .unwrap();
1211
1212 let r = neg(&a).unwrap();
1213 assert_eq!(r.data_type(), a.data_type());
1214 assert_eq!(
1215 r.as_primitive::<Decimal64Type>().values(),
1216 &[-1, -3, 44, -2, -4]
1217 );
1218
1219 let a = Decimal128Array::from(vec![1, 3, -44, 2, 4])
1220 .with_precision_and_scale(9, 6)
1221 .unwrap();
1222
1223 let r = neg(&a).unwrap();
1224 assert_eq!(r.data_type(), a.data_type());
1225 assert_eq!(
1226 r.as_primitive::<Decimal128Type>().values(),
1227 &[-1, -3, 44, -2, -4]
1228 );
1229
1230 let a = Decimal256Array::from(vec![
1231 i256::from_i128(342),
1232 i256::from_i128(-4949),
1233 i256::from_i128(3),
1234 ])
1235 .with_precision_and_scale(9, 6)
1236 .unwrap();
1237
1238 let r = neg(&a).unwrap();
1239 assert_eq!(r.data_type(), a.data_type());
1240 assert_eq!(
1241 r.as_primitive::<Decimal256Type>().values(),
1242 &[
1243 i256::from_i128(-342),
1244 i256::from_i128(4949),
1245 i256::from_i128(-3),
1246 ]
1247 );
1248
1249 let a = IntervalYearMonthArray::from(vec![
1250 IntervalYearMonthType::make_value(2, 4),
1251 IntervalYearMonthType::make_value(2, -4),
1252 IntervalYearMonthType::make_value(-3, -5),
1253 ]);
1254 let r = neg(&a).unwrap();
1255 assert_eq!(
1256 r.as_primitive::<IntervalYearMonthType>().values(),
1257 &[
1258 IntervalYearMonthType::make_value(-2, -4),
1259 IntervalYearMonthType::make_value(-2, 4),
1260 IntervalYearMonthType::make_value(3, 5),
1261 ]
1262 );
1263
1264 let a = IntervalDayTimeArray::from(vec![
1265 IntervalDayTimeType::make_value(2, 4),
1266 IntervalDayTimeType::make_value(2, -4),
1267 IntervalDayTimeType::make_value(-3, -5),
1268 ]);
1269 let r = neg(&a).unwrap();
1270 assert_eq!(
1271 r.as_primitive::<IntervalDayTimeType>().values(),
1272 &[
1273 IntervalDayTimeType::make_value(-2, -4),
1274 IntervalDayTimeType::make_value(-2, 4),
1275 IntervalDayTimeType::make_value(3, 5),
1276 ]
1277 );
1278
1279 let a = IntervalMonthDayNanoArray::from(vec![
1280 IntervalMonthDayNanoType::make_value(2, 4, 5953394),
1281 IntervalMonthDayNanoType::make_value(2, -4, -45839),
1282 IntervalMonthDayNanoType::make_value(-3, -5, 6944),
1283 ]);
1284 let r = neg(&a).unwrap();
1285 assert_eq!(
1286 r.as_primitive::<IntervalMonthDayNanoType>().values(),
1287 &[
1288 IntervalMonthDayNanoType::make_value(-2, -4, -5953394),
1289 IntervalMonthDayNanoType::make_value(-2, 4, 45839),
1290 IntervalMonthDayNanoType::make_value(3, 5, -6944),
1291 ]
1292 );
1293 }
1294
1295 #[test]
1296 fn test_integer() {
1297 let a = Int32Array::from(vec![4, 3, 5, -6, 100]);
1298 let b = Int32Array::from(vec![6, 2, 5, -7, 3]);
1299 let result = add(&a, &b).unwrap();
1300 assert_eq!(
1301 result.as_ref(),
1302 &Int32Array::from(vec![10, 5, 10, -13, 103])
1303 );
1304 let result = sub(&a, &b).unwrap();
1305 assert_eq!(result.as_ref(), &Int32Array::from(vec![-2, 1, 0, 1, 97]));
1306 let result = div(&a, &b).unwrap();
1307 assert_eq!(result.as_ref(), &Int32Array::from(vec![0, 1, 1, 0, 33]));
1308 let result = mul(&a, &b).unwrap();
1309 assert_eq!(result.as_ref(), &Int32Array::from(vec![24, 6, 25, 42, 300]));
1310 let result = rem(&a, &b).unwrap();
1311 assert_eq!(result.as_ref(), &Int32Array::from(vec![4, 1, 0, -6, 1]));
1312
1313 let a = Int8Array::from(vec![Some(2), None, Some(45)]);
1314 let b = Int8Array::from(vec![Some(5), Some(3), None]);
1315 let result = add(&a, &b).unwrap();
1316 assert_eq!(result.as_ref(), &Int8Array::from(vec![Some(7), None, None]));
1317
1318 let a = UInt8Array::from(vec![56, 5, 3]);
1319 let b = UInt8Array::from(vec![200, 2, 5]);
1320 let err = add(&a, &b).unwrap_err().to_string();
1321 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 56 + 200");
1322 let result = add_wrapping(&a, &b).unwrap();
1323 assert_eq!(result.as_ref(), &UInt8Array::from(vec![0, 7, 8]));
1324
1325 let a = UInt8Array::from(vec![34, 5, 3]);
1326 let b = UInt8Array::from(vec![200, 2, 5]);
1327 let err = sub(&a, &b).unwrap_err().to_string();
1328 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 34 - 200");
1329 let result = sub_wrapping(&a, &b).unwrap();
1330 assert_eq!(result.as_ref(), &UInt8Array::from(vec![90, 3, 254]));
1331
1332 let a = UInt8Array::from(vec![34, 5, 3]);
1333 let b = UInt8Array::from(vec![200, 2, 5]);
1334 let err = mul(&a, &b).unwrap_err().to_string();
1335 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 34 * 200");
1336 let result = mul_wrapping(&a, &b).unwrap();
1337 assert_eq!(result.as_ref(), &UInt8Array::from(vec![144, 10, 15]));
1338
1339 let a = Int16Array::from(vec![i16::MIN]);
1340 let b = Int16Array::from(vec![-1]);
1341 let err = div(&a, &b).unwrap_err().to_string();
1342 assert_eq!(
1343 err,
1344 "Arithmetic overflow: Overflow happened on: -32768 / -1"
1345 );
1346
1347 let a = Int16Array::from(vec![i16::MIN]);
1348 let b = Int16Array::from(vec![-1]);
1349 let result = rem(&a, &b).unwrap();
1350 assert_eq!(result.as_ref(), &Int16Array::from(vec![0]));
1351
1352 let a = Int16Array::from(vec![21]);
1353 let b = Int16Array::from(vec![0]);
1354 let err = div(&a, &b).unwrap_err().to_string();
1355 assert_eq!(err, "Divide by zero error");
1356
1357 let a = Int16Array::from(vec![21]);
1358 let b = Int16Array::from(vec![0]);
1359 let err = rem(&a, &b).unwrap_err().to_string();
1360 assert_eq!(err, "Divide by zero error");
1361 }
1362
1363 #[test]
1364 fn test_float() {
1365 let a = Float32Array::from(vec![1., f32::MAX, 6., -4., -1., 0.]);
1366 let b = Float32Array::from(vec![1., f32::MAX, f32::MAX, -3., 45., 0.]);
1367 let result = add(&a, &b).unwrap();
1368 assert_eq!(
1369 result.as_ref(),
1370 &Float32Array::from(vec![2., f32::INFINITY, f32::MAX, -7., 44.0, 0.])
1371 );
1372
1373 let result = sub(&a, &b).unwrap();
1374 assert_eq!(
1375 result.as_ref(),
1376 &Float32Array::from(vec![0., 0., f32::MIN, -1., -46., 0.])
1377 );
1378
1379 let result = mul(&a, &b).unwrap();
1380 assert_eq!(
1381 result.as_ref(),
1382 &Float32Array::from(vec![1., f32::INFINITY, f32::INFINITY, 12., -45., 0.])
1383 );
1384
1385 let result = div(&a, &b).unwrap();
1386 let r = result.as_primitive::<Float32Type>();
1387 assert_eq!(r.value(0), 1.);
1388 assert_eq!(r.value(1), 1.);
1389 assert!(r.value(2) < f32::EPSILON);
1390 assert_eq!(r.value(3), -4. / -3.);
1391 assert!(r.value(5).is_nan());
1392
1393 let result = rem(&a, &b).unwrap();
1394 let r = result.as_primitive::<Float32Type>();
1395 assert_eq!(&r.values()[..5], &[0., 0., 6., -1., -1.]);
1396 assert!(r.value(5).is_nan());
1397 }
1398
1399 #[test]
1400 fn test_decimal() {
1401 let a = Decimal128Array::from(vec![15, 0, -577, 334, -78, 3])
1403 .with_precision_and_scale(12, 3)
1404 .unwrap();
1405
1406 let b = Decimal128Array::from(vec![54, 34, -356, 3, 6, 745])
1408 .with_precision_and_scale(12, 1)
1409 .unwrap();
1410
1411 let result = add(&a, &b).unwrap();
1412 assert_eq!(result.data_type(), &DataType::Decimal128(15, 3));
1413 assert_eq!(
1414 result.as_primitive::<Decimal128Type>().values(),
1415 &[5415, 3400, -36177, 634, 522, 74503]
1416 );
1417
1418 let result = sub(&a, &b).unwrap();
1419 assert_eq!(result.data_type(), &DataType::Decimal128(15, 3));
1420 assert_eq!(
1421 result.as_primitive::<Decimal128Type>().values(),
1422 &[-5385, -3400, 35023, 34, -678, -74497]
1423 );
1424
1425 let result = mul(&a, &b).unwrap();
1426 assert_eq!(result.data_type(), &DataType::Decimal128(25, 4));
1427 assert_eq!(
1428 result.as_primitive::<Decimal128Type>().values(),
1429 &[810, 0, 205412, 1002, -468, 2235]
1430 );
1431
1432 let result = div(&a, &b).unwrap();
1433 assert_eq!(result.data_type(), &DataType::Decimal128(17, 7));
1434 assert_eq!(
1435 result.as_primitive::<Decimal128Type>().values(),
1436 &[27777, 0, 162078, 11133333, -1300000, 402]
1437 );
1438
1439 let result = rem(&a, &b).unwrap();
1440 assert_eq!(result.data_type(), &DataType::Decimal128(12, 3));
1441 assert_eq!(
1442 result.as_primitive::<Decimal128Type>().values(),
1443 &[15, 0, -577, 34, -78, 3]
1444 );
1445
1446 let a = Decimal128Array::from(vec![1])
1447 .with_precision_and_scale(3, 3)
1448 .unwrap();
1449 let b = Decimal128Array::from(vec![1])
1450 .with_precision_and_scale(37, 37)
1451 .unwrap();
1452 let err = mul(&a, &b).unwrap_err().to_string();
1453 assert_eq!(
1454 err,
1455 "Invalid argument error: Output scale of Decimal128(3, 3) * Decimal128(37, 37) would exceed max scale of 38"
1456 );
1457
1458 let a = Decimal128Array::from(vec![1])
1459 .with_precision_and_scale(3, -2)
1460 .unwrap();
1461 let err = add(&a, &b).unwrap_err().to_string();
1462 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 10 ^ 39");
1463
1464 let a = Decimal128Array::from(vec![10])
1465 .with_precision_and_scale(3, -1)
1466 .unwrap();
1467 let err = add(&a, &b).unwrap_err().to_string();
1468 assert_eq!(
1469 err,
1470 "Arithmetic overflow: Overflow happened on: 10 * 100000000000000000000000000000000000000"
1471 );
1472
1473 let b = Decimal128Array::from(vec![0])
1474 .with_precision_and_scale(1, 1)
1475 .unwrap();
1476 let err = div(&a, &b).unwrap_err().to_string();
1477 assert_eq!(err, "Divide by zero error");
1478 let err = rem(&a, &b).unwrap_err().to_string();
1479 assert_eq!(err, "Divide by zero error");
1480 }
1481
1482 #[test]
1483 fn test_decimal256_same_scale_add_sub() {
1484 let lhs = Decimal256Array::from(vec![
1485 Some(i256::from_parts(u128::MAX, 0)),
1486 Some(i256::MINUS_ONE),
1487 None,
1488 ])
1489 .with_precision_and_scale(70, 2)
1490 .unwrap();
1491 let rhs = Decimal256Array::from(vec![Some(i256::ONE), Some(i256::ONE), Some(i256::MAX)])
1492 .with_precision_and_scale(70, 2)
1493 .unwrap();
1494
1495 let expected =
1496 Decimal256Array::from(vec![Some(i256::from_parts(0, 1)), Some(i256::ZERO), None])
1497 .with_precision_and_scale(71, 2)
1498 .unwrap();
1499 for operation in [add, add_wrapping] {
1500 let result = operation(&lhs, &rhs).unwrap();
1501 assert_eq!(result.as_primitive::<Decimal256Type>(), &expected);
1502 }
1503
1504 let expected = Decimal256Array::from(vec![
1505 Some(i256::from_parts(u128::MAX - 1, 0)),
1506 Some(i256::from_i128(-2)),
1507 None,
1508 ])
1509 .with_precision_and_scale(71, 2)
1510 .unwrap();
1511 for operation in [sub, sub_wrapping] {
1512 let result = operation(&lhs, &rhs).unwrap();
1513 assert_eq!(result.as_primitive::<Decimal256Type>(), &expected);
1514 }
1515
1516 let lhs = Decimal256Array::from(vec![i256::MAX])
1517 .with_precision_and_scale(76, 0)
1518 .unwrap();
1519 let rhs = Decimal256Array::from(vec![i256::ONE])
1520 .with_precision_and_scale(76, 0)
1521 .unwrap();
1522 for operation in [add, add_wrapping] {
1523 assert_eq!(
1524 operation(&lhs, &rhs).unwrap_err().to_string(),
1525 format!(
1526 "Arithmetic overflow: Overflow happened on: {:?} + {:?}",
1527 i256::MAX,
1528 i256::ONE
1529 )
1530 );
1531 }
1532
1533 let lhs = Decimal256Array::from(vec![i256::MIN])
1534 .with_precision_and_scale(76, 0)
1535 .unwrap();
1536 for operation in [sub, sub_wrapping] {
1537 assert_eq!(
1538 operation(&lhs, &rhs).unwrap_err().to_string(),
1539 format!(
1540 "Arithmetic overflow: Overflow happened on: {:?} - {:?}",
1541 i256::MIN,
1542 i256::ONE
1543 )
1544 );
1545 }
1546 }
1547
1548 fn test_timestamp_impl<T: TimestampOp>() {
1549 let a = PrimitiveArray::<T>::new(vec![2000000, 434030324, 53943340].into(), None);
1550 let b = PrimitiveArray::<T>::new(vec![329593, 59349, 694994].into(), None);
1551
1552 let result = sub(&a, &b).unwrap();
1553 assert_eq!(
1554 result.as_primitive::<T::Duration>().values(),
1555 &[1670407, 433970975, 53248346]
1556 );
1557
1558 let r2 = add(&b, &result.as_ref()).unwrap();
1559 assert_eq!(r2.as_ref(), &a);
1560
1561 let r3 = add(&result.as_ref(), &b).unwrap();
1562 assert_eq!(r3.as_ref(), &a);
1563
1564 let format_array = |x: &dyn Array| -> Vec<String> {
1565 x.as_primitive::<T>()
1566 .values()
1567 .into_iter()
1568 .map(|x| as_datetime::<T>(*x).unwrap().to_string())
1569 .collect()
1570 };
1571
1572 let values = vec![
1573 "1970-01-01T00:00:00Z",
1574 "2010-04-01T04:00:20Z",
1575 "1960-01-30T04:23:20Z",
1576 ]
1577 .into_iter()
1578 .map(|x| {
1579 T::from_naive_datetime(DateTime::parse_from_rfc3339(x).unwrap().naive_utc(), None)
1580 .unwrap()
1581 })
1582 .collect();
1583
1584 let a = PrimitiveArray::<T>::new(values, None);
1585 let b = IntervalYearMonthArray::from(vec![
1586 IntervalYearMonthType::make_value(5, 34),
1587 IntervalYearMonthType::make_value(-2, 4),
1588 IntervalYearMonthType::make_value(7, -4),
1589 ]);
1590 let r4 = add(&a, &b).unwrap();
1591 assert_eq!(
1592 &format_array(r4.as_ref()),
1593 &[
1594 "1977-11-01 00:00:00".to_string(),
1595 "2008-08-01 04:00:20".to_string(),
1596 "1966-09-30 04:23:20".to_string()
1597 ]
1598 );
1599
1600 let r5 = sub(&r4, &b).unwrap();
1601 assert_eq!(r5.as_ref(), &a);
1602
1603 let b = IntervalDayTimeArray::from(vec![
1604 IntervalDayTimeType::make_value(5, 454000),
1605 IntervalDayTimeType::make_value(-34, 0),
1606 IntervalDayTimeType::make_value(7, -4000),
1607 ]);
1608 let r6 = add(&a, &b).unwrap();
1609 assert_eq!(
1610 &format_array(r6.as_ref()),
1611 &[
1612 "1970-01-06 00:07:34".to_string(),
1613 "2010-02-26 04:00:20".to_string(),
1614 "1960-02-06 04:23:16".to_string()
1615 ]
1616 );
1617
1618 let r7 = sub(&r6, &b).unwrap();
1619 assert_eq!(r7.as_ref(), &a);
1620
1621 let b = IntervalMonthDayNanoArray::from(vec![
1622 IntervalMonthDayNanoType::make_value(344, 34, -43_000_000_000),
1623 IntervalMonthDayNanoType::make_value(-593, -33, 13_000_000_000),
1624 IntervalMonthDayNanoType::make_value(5, 2, 493_000_000_000),
1625 ]);
1626 let r8 = add(&a, &b).unwrap();
1627 assert_eq!(
1628 &format_array(r8.as_ref()),
1629 &[
1630 "1998-10-04 23:59:17".to_string(),
1631 "1960-09-29 04:00:33".to_string(),
1632 "1960-07-02 04:31:33".to_string()
1633 ]
1634 );
1635
1636 let r9 = sub(&r8, &b).unwrap();
1637 assert_eq!(
1639 &format_array(r9.as_ref()),
1640 &[
1641 "1970-01-02 00:00:00".to_string(),
1642 "2010-04-02 04:00:20".to_string(),
1643 "1960-01-31 04:23:20".to_string()
1644 ]
1645 );
1646 }
1647
1648 #[test]
1649 fn test_timestamp() {
1650 test_timestamp_impl::<TimestampSecondType>();
1651 test_timestamp_impl::<TimestampMillisecondType>();
1652 test_timestamp_impl::<TimestampMicrosecondType>();
1653 test_timestamp_impl::<TimestampNanosecondType>();
1654 }
1655
1656 #[test]
1657 fn test_interval() {
1658 let a = IntervalYearMonthArray::from(vec![
1659 IntervalYearMonthType::make_value(32, 4),
1660 IntervalYearMonthType::make_value(32, 4),
1661 ]);
1662 let b = IntervalYearMonthArray::from(vec![
1663 IntervalYearMonthType::make_value(-4, 6),
1664 IntervalYearMonthType::make_value(-3, 23),
1665 ]);
1666 let result = add(&a, &b).unwrap();
1667 assert_eq!(
1668 result.as_ref(),
1669 &IntervalYearMonthArray::from(vec![
1670 IntervalYearMonthType::make_value(28, 10),
1671 IntervalYearMonthType::make_value(29, 27)
1672 ])
1673 );
1674 let result = sub(&a, &b).unwrap();
1675 assert_eq!(
1676 result.as_ref(),
1677 &IntervalYearMonthArray::from(vec![
1678 IntervalYearMonthType::make_value(36, -2),
1679 IntervalYearMonthType::make_value(35, -19)
1680 ])
1681 );
1682
1683 let a = IntervalDayTimeArray::from(vec![
1684 IntervalDayTimeType::make_value(32, 4),
1685 IntervalDayTimeType::make_value(32, 4),
1686 ]);
1687 let b = IntervalDayTimeArray::from(vec![
1688 IntervalDayTimeType::make_value(-4, 6),
1689 IntervalDayTimeType::make_value(-3, 23),
1690 ]);
1691 let result = add(&a, &b).unwrap();
1692 assert_eq!(
1693 result.as_ref(),
1694 &IntervalDayTimeArray::from(vec![
1695 IntervalDayTimeType::make_value(28, 10),
1696 IntervalDayTimeType::make_value(29, 27)
1697 ])
1698 );
1699 let result = sub(&a, &b).unwrap();
1700 assert_eq!(
1701 result.as_ref(),
1702 &IntervalDayTimeArray::from(vec![
1703 IntervalDayTimeType::make_value(36, -2),
1704 IntervalDayTimeType::make_value(35, -19)
1705 ])
1706 );
1707 let a = IntervalMonthDayNanoArray::from(vec![
1708 IntervalMonthDayNanoType::make_value(32, 4, 4000000000000),
1709 IntervalMonthDayNanoType::make_value(32, 4, 45463000000000000),
1710 ]);
1711 let b = IntervalMonthDayNanoArray::from(vec![
1712 IntervalMonthDayNanoType::make_value(-4, 6, 46000000000000),
1713 IntervalMonthDayNanoType::make_value(-3, 23, 3564000000000000),
1714 ]);
1715 let result = add(&a, &b).unwrap();
1716 assert_eq!(
1717 result.as_ref(),
1718 &IntervalMonthDayNanoArray::from(vec![
1719 IntervalMonthDayNanoType::make_value(28, 10, 50000000000000),
1720 IntervalMonthDayNanoType::make_value(29, 27, 49027000000000000)
1721 ])
1722 );
1723 let result = sub(&a, &b).unwrap();
1724 assert_eq!(
1725 result.as_ref(),
1726 &IntervalMonthDayNanoArray::from(vec![
1727 IntervalMonthDayNanoType::make_value(36, -2, -42000000000000),
1728 IntervalMonthDayNanoType::make_value(35, -19, 41899000000000000)
1729 ])
1730 );
1731 let a = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::MAX]);
1732 let b = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::ONE]);
1733 let err = add(&a, &b).unwrap_err().to_string();
1734 assert_eq!(
1735 err,
1736 "Arithmetic overflow: Overflow happened on: 2147483647 + 1"
1737 );
1738 }
1739
1740 #[test]
1741 fn test_interval_mul_i64() {
1742 let interval = IntervalYearMonthArray::from(vec![16, 5, 0]);
1743 let factor = Int64Array::from(vec![3, -2, i64::MAX]);
1744 let expected = IntervalYearMonthArray::from(vec![48, -10, 0]);
1745 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
1746 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
1747
1748 let interval = IntervalDayTimeArray::from(vec![
1749 Some(IntervalDayTimeType::make_value(10, 2 * 60 * 60 * 1000)),
1750 None,
1751 ]);
1752 let factor = Int64Array::new_scalar(3);
1753 let expected = IntervalDayTimeArray::from(vec![
1754 Some(IntervalDayTimeType::make_value(30, 6 * 60 * 60 * 1000)),
1755 None,
1756 ]);
1757 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
1758 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
1759
1760 let null_factor = Scalar::new(Int64Array::new_null(1));
1761 let expected = IntervalDayTimeArray::new_null(interval.len());
1762 assert_eq!(mul(&interval, &null_factor).unwrap().as_ref(), &expected);
1763 assert_eq!(mul(&null_factor, &interval).unwrap().as_ref(), &expected);
1764
1765 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
1766 12,
1767 15,
1768 5_000_000_000,
1769 ));
1770 let factor = Int64Array::from(vec![2, 0, -1]);
1771 let expected = IntervalMonthDayNanoArray::from(vec![
1772 IntervalMonthDayNanoType::make_value(24, 30, 10_000_000_000),
1773 IntervalMonthDayNanoType::make_value(0, 0, 0),
1774 IntervalMonthDayNanoType::make_value(-12, -15, -5_000_000_000),
1775 ]);
1776 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
1777 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
1778
1779 let float_factor = Float64Array::new_scalar(2.);
1780 assert!(mul_wrapping(&float_factor, &interval).is_err());
1781 assert!(mul_wrapping(&factor, &interval).is_err());
1782 }
1783
1784 #[test]
1785 fn test_interval_mul_div_f64() {
1786 const HOUR_NANOS: i64 = 3_600_000_000_000;
1787 const MINUTE_NANOS: i64 = 60_000_000_000;
1788
1789 let interval = IntervalMonthDayNanoArray::from(vec![
1794 IntervalMonthDayNanoType::make_value(41, 12, 360 * HOUR_NANOS),
1795 IntervalMonthDayNanoType::make_value(-41, -12, 360 * HOUR_NANOS),
1796 IntervalMonthDayNanoType::make_value(1, 1, 0),
1797 IntervalMonthDayNanoType::make_value(0, 0, 1),
1798 IntervalMonthDayNanoType::make_value(0, 0, 3),
1799 IntervalMonthDayNanoType::make_value(0, 0, -1),
1800 IntervalMonthDayNanoType::make_value(0, 0, -3),
1801 ]);
1802 let factor = Float64Array::from(vec![0.3, 0.3, 1.5, 0.5, 0.5, 0.5, 0.5]);
1803 let expected = IntervalMonthDayNanoArray::from(vec![
1804 IntervalMonthDayNanoType::make_value(12, 12, 122 * HOUR_NANOS + 24 * MINUTE_NANOS),
1805 IntervalMonthDayNanoType::make_value(-12, -12, 93 * HOUR_NANOS + 36 * MINUTE_NANOS),
1806 IntervalMonthDayNanoType::make_value(1, 16, 12 * HOUR_NANOS),
1807 IntervalMonthDayNanoType::make_value(0, 0, 0),
1808 IntervalMonthDayNanoType::make_value(0, 0, 2),
1809 IntervalMonthDayNanoType::make_value(0, 0, 0),
1810 IntervalMonthDayNanoType::make_value(0, 0, -2),
1811 ]);
1812 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
1813 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
1814
1815 let interval = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
1816 9,
1817 -27,
1818 45_296 * NANOSECONDS,
1819 )]);
1820 let factor = Float64Array::new_scalar(0.3);
1821 let expected = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
1822 2,
1823 13,
1824 4_948_800_000_000,
1825 )]);
1826 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
1827
1828 let interval = IntervalMonthDayNanoArray::from(vec![
1829 IntervalMonthDayNanoType::make_value(0, 1, 0),
1830 IntervalMonthDayNanoType::make_value(4, 0, 0),
1831 IntervalMonthDayNanoType::make_value(1, 1, 0),
1832 IntervalMonthDayNanoType::make_value(0, 0, (1_i64 << 53) - 1),
1833 IntervalMonthDayNanoType::make_value(0, 0, i64::MAX),
1834 IntervalMonthDayNanoType::make_value(1, 1, 1),
1835 IntervalMonthDayNanoType::make_value(1, 1, 1),
1836 IntervalMonthDayNanoType::make_value(1, 0, 0),
1837 ]);
1838 let factor = Float64Array::from(vec![
1839 3.,
1840 5.,
1841 2.,
1842 0.7,
1843 1.,
1844 f64::INFINITY,
1845 f64::NEG_INFINITY,
1846 -2.,
1847 ]);
1848 let expected = IntervalMonthDayNanoArray::from(vec![
1849 IntervalMonthDayNanoType::make_value(0, 0, 8 * HOUR_NANOS),
1850 IntervalMonthDayNanoType::make_value(0, 24, 0),
1851 IntervalMonthDayNanoType::make_value(0, 15, 12 * HOUR_NANOS),
1852 IntervalMonthDayNanoType::make_value(0, 0, 12_867_427_506_772_844),
1853 IntervalMonthDayNanoType::make_value(0, 0, i64::MAX),
1854 IntervalMonthDayNanoType::make_value(0, 0, 0),
1855 IntervalMonthDayNanoType::make_value(0, 0, 0),
1856 IntervalMonthDayNanoType::make_value(0, -15, 0),
1857 ]);
1858 assert_eq!(div(&interval, &factor).unwrap().as_ref(), &expected);
1859
1860 let null_factor = Scalar::new(Float64Array::new_null(1));
1861 assert_eq!(
1862 mul(&interval, &null_factor).unwrap().as_ref(),
1863 &IntervalMonthDayNanoArray::new_null(interval.len())
1864 );
1865 }
1866
1867 #[test]
1868 fn test_interval_mul_div_f64_errors() {
1869 let factor = Float64Array::new_scalar(2.);
1870 let year_month = IntervalYearMonthArray::new_scalar(1);
1871 let day_time = IntervalDayTimeArray::new_scalar(IntervalDayTime::new(1, 1));
1872 for interval in [&year_month as &dyn Datum, &day_time] {
1873 assert!(mul(interval, &factor).is_err());
1874 assert!(mul(&factor, interval).is_err());
1875 assert!(div(interval, &factor).is_err());
1876 }
1877
1878 let interval =
1879 IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(1, 1, 1));
1880
1881 assert!(matches!(
1882 add(&interval, &factor),
1883 Err(ArrowError::InvalidArgumentError(_))
1884 ));
1885
1886 let zero = Float64Array::new_scalar(-0.);
1887 assert!(matches!(
1888 div(&interval, &zero),
1889 Err(ArrowError::DivideByZero)
1890 ));
1891
1892 assert!(div(&factor, &interval).is_err());
1893
1894 for factor in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
1895 let factor = Float64Array::new_scalar(factor);
1896 assert!(matches!(
1897 mul(&interval, &factor),
1898 Err(ArrowError::ArithmeticOverflow(_))
1899 ));
1900 }
1901
1902 let nan = Float64Array::new_scalar(f64::NAN);
1903 assert!(matches!(
1904 div(&interval, &nan),
1905 Err(ArrowError::ArithmeticOverflow(_))
1906 ));
1907
1908 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
1909 i32::MAX,
1910 0,
1911 0,
1912 ));
1913 assert!(matches!(
1914 mul(&interval, &factor),
1915 Err(ArrowError::ArithmeticOverflow(_))
1916 ));
1917
1918 let factor = Float64Array::new_scalar(1.5);
1919 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
1920 0,
1921 0,
1922 i64::MAX,
1923 ));
1924 assert!(matches!(
1925 mul(&interval, &factor),
1926 Err(ArrowError::ArithmeticOverflow(_))
1927 ));
1928
1929 let factor = Float64Array::new_scalar(1.000_000_000_4);
1930 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
1931 i32::MIN,
1932 0,
1933 0,
1934 ));
1935 assert!(matches!(
1936 mul(&interval, &factor),
1937 Err(ArrowError::ArithmeticOverflow(_))
1938 ));
1939
1940 let factor = Float64Array::new_scalar(0.999_999_999);
1941 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
1942 1,
1943 i32::MAX,
1944 0,
1945 ));
1946 assert!(matches!(
1947 mul(&interval, &factor),
1948 Err(ArrowError::ArithmeticOverflow(_))
1949 ));
1950 }
1951
1952 #[test]
1953 fn test_interval_mul_i64_overflow() {
1954 let interval = IntervalYearMonthArray::from(vec![i32::MAX]);
1955 let factor = Int64Array::from(vec![2]);
1956 assert_eq!(
1957 mul(&interval, &factor).unwrap_err().to_string(),
1958 "Arithmetic overflow: Overflow happened on: 2147483647 * 2"
1959 );
1960
1961 let interval = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
1962 0,
1963 0,
1964 i64::MAX,
1965 )]);
1966 assert_eq!(
1967 mul(&interval, &factor).unwrap_err().to_string(),
1968 "Arithmetic overflow: Overflow happened on: 9223372036854775807 * 2"
1969 );
1970 }
1971
1972 fn test_duration_impl<T: ArrowPrimitiveType<Native = i64>>() {
1973 let a = PrimitiveArray::<T>::new(vec![1000, 4394, -3944].into(), None);
1974 let b = PrimitiveArray::<T>::new(vec![4, -5, -243].into(), None);
1975
1976 let result = add(&a, &b).unwrap();
1977 assert_eq!(result.as_primitive::<T>().values(), &[1004, 4389, -4187]);
1978 let result = sub(&a, &b).unwrap();
1979 assert_eq!(result.as_primitive::<T>().values(), &[996, 4399, -3701]);
1980
1981 let err = mul(&a, &b).unwrap_err().to_string();
1982 assert!(
1983 err.contains("Invalid duration arithmetic operation"),
1984 "{err}"
1985 );
1986
1987 let err = div(&a, &b).unwrap_err().to_string();
1988 assert!(
1989 err.contains("Invalid duration arithmetic operation"),
1990 "{err}"
1991 );
1992
1993 let err = rem(&a, &b).unwrap_err().to_string();
1994 assert!(
1995 err.contains("Invalid duration arithmetic operation"),
1996 "{err}"
1997 );
1998
1999 let a = PrimitiveArray::<T>::new(vec![i64::MAX].into(), None);
2000 let b = PrimitiveArray::<T>::new(vec![1].into(), None);
2001 let err = add(&a, &b).unwrap_err().to_string();
2002 assert_eq!(
2003 err,
2004 "Arithmetic overflow: Overflow happened on: 9223372036854775807 + 1"
2005 );
2006 }
2007
2008 #[test]
2009 fn test_duration() {
2010 test_duration_impl::<DurationSecondType>();
2011 test_duration_impl::<DurationMillisecondType>();
2012 test_duration_impl::<DurationMicrosecondType>();
2013 test_duration_impl::<DurationNanosecondType>();
2014 }
2015
2016 fn test_date_impl<T: ArrowPrimitiveType, F>(f: F)
2017 where
2018 F: Fn(NaiveDate) -> T::Native,
2019 T::Native: TryInto<i64>,
2020 {
2021 let a = PrimitiveArray::<T>::new(
2022 vec![
2023 f(NaiveDate::from_ymd_opt(1979, 1, 30).unwrap()),
2024 f(NaiveDate::from_ymd_opt(2010, 4, 3).unwrap()),
2025 f(NaiveDate::from_ymd_opt(2008, 2, 29).unwrap()),
2026 ]
2027 .into(),
2028 None,
2029 );
2030
2031 let b = IntervalYearMonthArray::from(vec![
2032 IntervalYearMonthType::make_value(34, 2),
2033 IntervalYearMonthType::make_value(3, -3),
2034 IntervalYearMonthType::make_value(-12, 4),
2035 ]);
2036
2037 let format_array = |x: &dyn Array| -> Vec<String> {
2038 x.as_primitive::<T>()
2039 .values()
2040 .into_iter()
2041 .map(|x| {
2042 as_date::<T>((*x).try_into().ok().unwrap())
2043 .unwrap()
2044 .to_string()
2045 })
2046 .collect()
2047 };
2048
2049 let result = add(&a, &b).unwrap();
2050 assert_eq!(
2051 &format_array(result.as_ref()),
2052 &[
2053 "2013-03-30".to_string(),
2054 "2013-01-03".to_string(),
2055 "1996-06-29".to_string(),
2056 ]
2057 );
2058 let result = sub(&result, &b).unwrap();
2059 assert_eq!(result.as_ref(), &a);
2060
2061 let b = IntervalDayTimeArray::from(vec![
2062 IntervalDayTimeType::make_value(34, 2),
2063 IntervalDayTimeType::make_value(3, -3),
2064 IntervalDayTimeType::make_value(-12, 4),
2065 ]);
2066
2067 let result = add(&a, &b).unwrap();
2068 assert_eq!(
2069 &format_array(result.as_ref()),
2070 &[
2071 "1979-03-05".to_string(),
2072 "2010-04-06".to_string(),
2073 "2008-02-17".to_string(),
2074 ]
2075 );
2076 let result = sub(&result, &b).unwrap();
2077 assert_eq!(result.as_ref(), &a);
2078
2079 let b = IntervalMonthDayNanoArray::from(vec![
2080 IntervalMonthDayNanoType::make_value(34, 2, -34353534),
2081 IntervalMonthDayNanoType::make_value(3, -3, 2443),
2082 IntervalMonthDayNanoType::make_value(-12, 4, 2323242423232),
2083 ]);
2084
2085 let result = add(&a, &b).unwrap();
2086 assert_eq!(
2087 &format_array(result.as_ref()),
2088 &[
2089 "1981-12-02".to_string(),
2090 "2010-06-30".to_string(),
2091 "2007-03-04".to_string(),
2092 ]
2093 );
2094 let result = sub(&result, &b).unwrap();
2095 assert_eq!(
2096 &format_array(result.as_ref()),
2097 &[
2098 "1979-01-31".to_string(),
2099 "2010-04-02".to_string(),
2100 "2008-02-29".to_string(),
2101 ]
2102 );
2103 }
2104
2105 #[test]
2106 fn test_date() {
2107 test_date_impl::<Date32Type, _>(Date32Type::from_naive_date);
2108 test_date_impl::<Date64Type, _>(Date64Type::from_naive_date);
2109
2110 let a = Date32Array::from(vec![i32::MIN, i32::MAX, 23, 7684]);
2111 let b = Date32Array::from(vec![i32::MIN, i32::MIN, -2, 45]);
2112 let result = sub(&a, &b).unwrap();
2113 assert_eq!(
2114 result.as_primitive::<DurationSecondType>().values(),
2115 &[0, 371085174288000, 2160000, 660009600]
2116 );
2117
2118 let a = Date64Array::from(vec![4343, 76676, 3434]);
2119 let b = Date64Array::from(vec![3, -5, 5]);
2120 let result = sub(&a, &b).unwrap();
2121 assert_eq!(
2122 result.as_primitive::<DurationMillisecondType>().values(),
2123 &[4340, 76681, 3429]
2124 );
2125
2126 let a = Date64Array::from(vec![i64::MAX]);
2127 let b = Date64Array::from(vec![-1]);
2128 let err = sub(&a, &b).unwrap_err().to_string();
2129 assert_eq!(
2130 err,
2131 "Arithmetic overflow: Overflow happened on: 9223372036854775807 - -1"
2132 );
2133 }
2134
2135 #[test]
2136 fn test_date32_to_naive_date_opt_boundaries() {
2137 assert_eq!(MAX_VALID_DAYS, 95026236);
2138 assert_eq!(MIN_VALID_DAYS, -96465292);
2139
2140 assert!(Date32Type::to_naive_date_opt(MAX_VALID_DAYS).is_some());
2142 assert!(Date32Type::to_naive_date_opt(MIN_VALID_DAYS).is_some());
2143
2144 assert!(Date32Type::to_naive_date_opt(MAX_VALID_DAYS + 1).is_none());
2146 assert!(Date32Type::to_naive_date_opt(MIN_VALID_DAYS - 1).is_none());
2147
2148 assert!(Date32Type::to_naive_date_opt(i32::MAX).is_none());
2150 assert!(Date32Type::to_naive_date_opt(i32::MIN).is_none());
2151
2152 assert!(Date32Type::to_naive_date_opt(0).is_some());
2154 assert!(Date32Type::to_naive_date_opt(date_to_days(YEAR_2000)).is_some());
2155 }
2156
2157 #[test]
2158 fn test_date64_to_naive_date_opt_boundaries() {
2159 const MS_PER_DAY: i64 = 24 * 60 * 60 * 1000;
2160
2161 assert_eq!(MAX_VALID_MILLIS, 8210266790400000i64);
2163 assert_eq!(MIN_VALID_MILLIS, -8334601228800000i64);
2164
2165 assert!(Date64Type::to_naive_date_opt(MAX_VALID_MILLIS).is_some());
2167 assert!(Date64Type::to_naive_date_opt(MIN_VALID_MILLIS).is_some());
2168
2169 assert!(Date64Type::to_naive_date_opt(MAX_VALID_MILLIS + MS_PER_DAY).is_none());
2171 assert!(Date64Type::to_naive_date_opt(MIN_VALID_MILLIS - MS_PER_DAY).is_none());
2172
2173 assert!(Date64Type::to_naive_date_opt(i64::MAX).is_none());
2175 assert!(Date64Type::to_naive_date_opt(i64::MIN).is_none());
2176
2177 assert!(Date64Type::to_naive_date_opt(0).is_some());
2179 assert!(Date64Type::to_naive_date_opt(date_to_millis(YEAR_2000)).is_some());
2180 }
2181
2182 macro_rules! test_year_month_ops {
2183 ($type:ty, $date_fn:expr) => {{
2184 let date = $date_fn(YEAR_2000);
2185
2186 assert!(
2188 <$type>::add_year_months_opt(date, 120).is_some(),
2189 "add_year_months: normal add"
2190 );
2191 assert!(
2192 <$type>::add_year_months_opt(date, 0).is_some(),
2193 "add_year_months: zero interval"
2194 );
2195 assert!(
2196 <$type>::subtract_year_months_opt(date, 120).is_some(),
2197 "subtract_year_months: normal subtract"
2198 );
2199 assert!(
2200 <$type>::subtract_year_months_opt(date, 0).is_some(),
2201 "subtract_year_months: zero interval"
2202 );
2203
2204 let large_year = $date_fn(NaiveDate::from_ymd_opt(5000, 1, 1).unwrap());
2206 let neg_year = $date_fn(NaiveDate::from_ymd_opt(-5000, 12, 31).unwrap());
2207 assert!(
2208 <$type>::add_year_months_opt(large_year, 12).is_some(),
2209 "add_year_months: large year"
2210 );
2211 assert!(
2212 <$type>::add_year_months_opt(neg_year, -12).is_some(),
2213 "add_year_months: negative year"
2214 );
2215 assert!(
2216 <$type>::subtract_year_months_opt(large_year, 12).is_some(),
2217 "subtract_year_months: large year"
2218 );
2219 assert!(
2220 <$type>::subtract_year_months_opt(neg_year, -12).is_some(),
2221 "subtract_year_months: negative year"
2222 );
2223
2224 assert!(
2226 <$type>::subtract_year_months_opt($date_fn(MIN_VALID_DATE), 1).is_none(),
2227 "subtract_year_months: overflow days from min"
2228 );
2229 assert!(
2230 <$type>::subtract_year_months_opt($date_fn(MAX_VALID_DATE), -1).is_none(),
2231 "subtract_year_months: overflow neg days from max"
2232 );
2233 assert!(
2234 <$type>::add_year_months_opt($date_fn(MAX_VALID_DATE), 1).is_none(),
2235 "add_year_months: overflow days"
2236 );
2237 assert!(
2238 <$type>::add_year_months_opt($date_fn(MIN_VALID_DATE), -1).is_none(),
2239 "add_year_months: overflow neg days"
2240 );
2241 }};
2242 }
2243
2244 #[test]
2245 fn test_date_year_month_operations() {
2246 test_year_month_ops!(Date32Type, date_to_days);
2247 test_year_month_ops!(Date64Type, date_to_millis);
2248 }
2249
2250 macro_rules! test_day_time_ops {
2251 ($type:ty, $date_fn:expr) => {{
2252 let date = $date_fn(YEAR_2000);
2253
2254 assert!(
2256 <$type>::add_day_time_opt(date, IntervalDayTime::new(30, 0)).is_some(),
2257 "add_day_time: +30 days"
2258 );
2259 assert!(
2260 <$type>::add_day_time_opt(date, IntervalDayTime::new(-30, 0)).is_some(),
2261 "add_day_time: -30 days"
2262 );
2263 assert!(
2264 <$type>::add_day_time_opt(date, IntervalDayTime::new(1000, 12345)).is_some(),
2265 "add_day_time: normal"
2266 );
2267 assert!(
2268 <$type>::subtract_day_time_opt(date, IntervalDayTime::new(30, 0)).is_some(),
2269 "subtract_day_time: +30 days"
2270 );
2271 assert!(
2272 <$type>::subtract_day_time_opt(date, IntervalDayTime::new(-30, 0)).is_some(),
2273 "subtract_day_time: -30 days"
2274 );
2275 assert!(
2276 <$type>::subtract_day_time_opt(date, IntervalDayTime::new(1000, 12345)).is_some(),
2277 "subtract_day_time: normal"
2278 );
2279
2280 assert!(
2282 <$type>::subtract_day_time_opt(
2283 $date_fn(MIN_VALID_DATE),
2284 IntervalDayTime::new(1, 0)
2285 )
2286 .is_none(),
2287 "subtract_day_time: overflow days from min"
2288 );
2289 assert!(
2290 <$type>::subtract_day_time_opt(
2291 $date_fn(MAX_VALID_DATE),
2292 IntervalDayTime::new(-1, 0)
2293 )
2294 .is_none(),
2295 "subtract_day_time: overflow neg days from max"
2296 );
2297
2298 assert!(
2300 <$type>::add_day_time_opt($date_fn(MAX_VALID_DATE), IntervalDayTime::new(1, 0))
2301 .is_none(),
2302 "add_day_time: overflow days"
2303 );
2304 assert!(
2305 <$type>::add_day_time_opt($date_fn(MIN_VALID_DATE), IntervalDayTime::new(-1, 0))
2306 .is_none(),
2307 "add_day_time: overflow neg days"
2308 );
2309
2310 assert!(
2312 <$type>::add_day_time_opt(
2313 $date_fn(EPOCH),
2314 IntervalDayTime::new(i32::MAX, i32::MAX)
2315 )
2316 .is_none(),
2317 "add_day_time: max interval"
2318 );
2319 assert!(
2320 <$type>::add_day_time_opt(
2321 $date_fn(EPOCH),
2322 IntervalDayTime::new(i32::MIN, i32::MIN)
2323 )
2324 .is_none(),
2325 "add_day_time: min interval"
2326 );
2327 assert!(
2328 <$type>::subtract_day_time_opt(
2329 $date_fn(EPOCH),
2330 IntervalDayTime::new(i32::MAX, i32::MAX)
2331 )
2332 .is_none(),
2333 "subtract_day_time: max interval"
2334 );
2335 assert!(
2336 <$type>::subtract_day_time_opt(
2337 $date_fn(EPOCH),
2338 IntervalDayTime::new(i32::MIN, i32::MIN)
2339 )
2340 .is_none(),
2341 "subtract_day_time: min interval"
2342 );
2343 }};
2344 }
2345
2346 #[test]
2347 fn test_date_day_time_operations() {
2348 test_day_time_ops!(Date32Type, date_to_days);
2349 test_day_time_ops!(Date64Type, date_to_millis);
2350 }
2351
2352 macro_rules! test_month_day_nano_ops {
2353 ($type:ty, $date_fn:expr) => {{
2354 let date = $date_fn(YEAR_2000);
2355 let zero = IntervalMonthDayNano::new(0, 0, 0);
2356
2357 assert!(
2359 <$type>::add_month_day_nano_opt(date, IntervalMonthDayNano::new(1, 30, 0))
2360 .is_some(),
2361 "add_month_day_nano: +1mo +30d"
2362 );
2363 assert!(
2364 <$type>::add_month_day_nano_opt(date, IntervalMonthDayNano::new(-1, -30, 0))
2365 .is_some(),
2366 "add_month_day_nano: -1mo -30d"
2367 );
2368 assert!(
2369 <$type>::add_month_day_nano_opt(date, zero).is_some(),
2370 "add_month_day_nano: zero interval"
2371 );
2372 assert!(
2373 <$type>::add_month_day_nano_opt(
2374 date,
2375 IntervalMonthDayNano::new(2, 10, 123_456_789_000)
2376 )
2377 .is_some(),
2378 "add_month_day_nano: normal"
2379 );
2380 assert!(
2381 <$type>::subtract_month_day_nano_opt(date, IntervalMonthDayNano::new(1, 30, 0))
2382 .is_some(),
2383 "subtract_month_day_nano: +1mo +30d"
2384 );
2385 assert!(
2386 <$type>::subtract_month_day_nano_opt(date, IntervalMonthDayNano::new(-1, -30, 0))
2387 .is_some(),
2388 "subtract_month_day_nano: -1mo -30d"
2389 );
2390 assert!(
2391 <$type>::subtract_month_day_nano_opt(date, zero).is_some(),
2392 "subtract_month_day_nano: zero interval"
2393 );
2394 assert!(
2395 <$type>::subtract_month_day_nano_opt(
2396 date,
2397 IntervalMonthDayNano::new(2, 10, 123_456_789_000)
2398 )
2399 .is_some(),
2400 "subtract_month_day_nano: normal"
2401 );
2402
2403 assert!(
2405 <$type>::subtract_month_day_nano_opt(
2406 $date_fn(MIN_VALID_DATE),
2407 IntervalMonthDayNano::new(0, 1, 0)
2408 )
2409 .is_none(),
2410 "subtract_month_day_nano: overflow days from min"
2411 );
2412 assert!(
2413 <$type>::subtract_month_day_nano_opt(
2414 $date_fn(MAX_VALID_DATE),
2415 IntervalMonthDayNano::new(0, -1, 0)
2416 )
2417 .is_none(),
2418 "subtract_month_day_nano: overflow neg days from max"
2419 );
2420
2421 assert!(
2423 <$type>::add_month_day_nano_opt(
2424 $date_fn(MAX_VALID_DATE),
2425 IntervalMonthDayNano::new(0, 1, 0)
2426 )
2427 .is_none(),
2428 "add_month_day_nano: overflow days"
2429 );
2430 assert!(
2431 <$type>::add_month_day_nano_opt(
2432 $date_fn(MIN_VALID_DATE),
2433 IntervalMonthDayNano::new(0, -1, 0)
2434 )
2435 .is_none(),
2436 "add_month_day_nano: overflow neg days"
2437 );
2438
2439 assert!(
2441 <$type>::add_month_day_nano_opt(date, IntervalMonthDayNano::new(0, 0, 999_999_999))
2442 .is_some(),
2443 "add_month_day_nano: nanos"
2444 );
2445 assert!(
2446 <$type>::subtract_month_day_nano_opt(
2447 date,
2448 IntervalMonthDayNano::new(0, 0, 999_999_999)
2449 )
2450 .is_some(),
2451 "subtract_month_day_nano: nanos"
2452 );
2453 assert!(
2455 <$type>::add_month_day_nano_opt(
2456 date,
2457 IntervalMonthDayNano::new(0, 0, 86_400_000_000_000)
2458 )
2459 .is_some(),
2460 "add_month_day_nano: 1 day nanos"
2461 );
2462 assert!(
2463 <$type>::subtract_month_day_nano_opt(
2464 date,
2465 IntervalMonthDayNano::new(0, 0, 86_400_000_000_000)
2466 )
2467 .is_some(),
2468 "subtract_month_day_nano: 1 day nanos"
2469 );
2470 }};
2471 }
2472
2473 #[test]
2474 fn test_date_month_day_nano_operations() {
2475 test_month_day_nano_ops!(Date32Type, date_to_days);
2476 test_month_day_nano_ops!(Date64Type, date_to_millis);
2477 }
2478}