@@ -243,6 +243,12 @@ fn arithmetic_op(op: Op, lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, A
243243 ( Duration ( Millisecond ) , Duration ( Millisecond ) ) => duration_op:: <DurationMillisecondType >( op, l, l_scalar, r, r_scalar) ,
244244 ( Duration ( Microsecond ) , Duration ( Microsecond ) ) => duration_op:: <DurationMicrosecondType >( op, l, l_scalar, r, r_scalar) ,
245245 ( Duration ( Nanosecond ) , Duration ( Nanosecond ) ) => duration_op:: <DurationNanosecondType >( op, l, l_scalar, r, r_scalar) ,
246+ ( Interval ( YearMonth ) , Int64 ) if matches!( op, Op :: Mul ) => interval_mul_op:: <IntervalYearMonthType >( l, l_scalar, r, r_scalar) ,
247+ ( Interval ( DayTime ) , Int64 ) if matches!( op, Op :: Mul ) => interval_mul_op:: <IntervalDayTimeType >( l, l_scalar, r, r_scalar) ,
248+ ( Interval ( MonthDayNano ) , Int64 ) if matches!( op, Op :: Mul ) => interval_mul_op:: <IntervalMonthDayNanoType >( l, l_scalar, r, r_scalar) ,
249+ ( Int64 , Interval ( YearMonth ) ) if matches!( op, Op :: Mul ) => interval_mul_op:: <IntervalYearMonthType >( r, r_scalar, l, l_scalar) ,
250+ ( Int64 , Interval ( DayTime ) ) if matches!( op, Op :: Mul ) => interval_mul_op:: <IntervalDayTimeType >( r, r_scalar, l, l_scalar) ,
251+ ( Int64 , Interval ( MonthDayNano ) ) if matches!( op, Op :: Mul ) => interval_mul_op:: <IntervalMonthDayNanoType >( r, r_scalar, l, l_scalar) ,
246252 ( Interval ( YearMonth ) , Interval ( YearMonth ) ) => interval_op:: <IntervalYearMonthType >( op, l, l_scalar, r, r_scalar) ,
247253 ( Interval ( DayTime ) , Interval ( DayTime ) ) => interval_op:: <IntervalDayTimeType >( op, l, l_scalar, r, r_scalar) ,
248254 ( Interval ( MonthDayNano ) , Interval ( MonthDayNano ) ) => interval_op:: <IntervalMonthDayNanoType >( op, l, l_scalar, r, r_scalar) ,
@@ -621,6 +627,14 @@ date!(Date64Type);
621627trait IntervalOp : ArrowPrimitiveType {
622628 fn add ( left : Self :: Native , right : Self :: Native ) -> Result < Self :: Native , ArrowError > ;
623629 fn sub ( left : Self :: Native , right : Self :: Native ) -> Result < Self :: Native , ArrowError > ;
630+ fn mul_i64 ( left : Self :: Native , right : i64 ) -> Result < Self :: Native , ArrowError > ;
631+ }
632+
633+ fn mul_i32_i64 ( left : i32 , right : i64 ) -> Result < i32 , ArrowError > {
634+ let value = i64:: from ( left) . mul_checked ( right) ?;
635+ i32:: try_from ( value) . map_err ( |_| {
636+ ArrowError :: ArithmeticOverflow ( format ! ( "Overflow happened on: {left} * {right}" ) )
637+ } )
624638}
625639
626640impl IntervalOp for IntervalYearMonthType {
@@ -631,6 +645,10 @@ impl IntervalOp for IntervalYearMonthType {
631645 fn sub ( left : Self :: Native , right : Self :: Native ) -> Result < Self :: Native , ArrowError > {
632646 left. sub_checked ( right)
633647 }
648+
649+ fn mul_i64 ( left : Self :: Native , right : i64 ) -> Result < Self :: Native , ArrowError > {
650+ mul_i32_i64 ( left, right)
651+ }
634652}
635653
636654impl IntervalOp for IntervalDayTimeType {
@@ -649,6 +667,14 @@ impl IntervalOp for IntervalDayTimeType {
649667 let ms = l_ms. sub_checked ( r_ms) ?;
650668 Ok ( Self :: make_value ( days, ms) )
651669 }
670+
671+ fn mul_i64 ( left : Self :: Native , right : i64 ) -> Result < Self :: Native , ArrowError > {
672+ let ( days, ms) = Self :: to_parts ( left) ;
673+ Ok ( Self :: make_value (
674+ mul_i32_i64 ( days, right) ?,
675+ mul_i32_i64 ( ms, right) ?,
676+ ) )
677+ }
652678}
653679
654680impl IntervalOp for IntervalMonthDayNanoType {
@@ -669,6 +695,33 @@ impl IntervalOp for IntervalMonthDayNanoType {
669695 let nanos = l_nanos. sub_checked ( r_nanos) ?;
670696 Ok ( Self :: make_value ( months, days, nanos) )
671697 }
698+
699+ fn mul_i64 ( left : Self :: Native , right : i64 ) -> Result < Self :: Native , ArrowError > {
700+ let ( months, days, nanos) = Self :: to_parts ( left) ;
701+ Ok ( Self :: make_value (
702+ mul_i32_i64 ( months, right) ?,
703+ mul_i32_i64 ( days, right) ?,
704+ nanos. mul_checked ( right) ?,
705+ ) )
706+ }
707+ }
708+
709+ fn interval_mul_op < T : IntervalOp > (
710+ interval : & dyn Array ,
711+ interval_scalar : bool ,
712+ factor : & dyn Array ,
713+ factor_scalar : bool ,
714+ ) -> Result < ArrayRef , ArrowError > {
715+ let interval = interval. as_primitive :: < T > ( ) ;
716+ let factor = factor. as_primitive :: < Int64Type > ( ) ;
717+ Ok ( try_op_ref ! (
718+ T ,
719+ interval,
720+ interval_scalar,
721+ factor,
722+ factor_scalar,
723+ T :: mul_i64( interval, factor)
724+ ) )
672725}
673726
674727/// Perform arithmetic operation on an interval array
@@ -1555,6 +1608,70 @@ mod tests {
15551608 ) ;
15561609 }
15571610
1611+ #[ test]
1612+ fn test_interval_mul_i64 ( ) {
1613+ let interval = IntervalYearMonthArray :: from ( vec ! [ 16 , 5 , 0 ] ) ;
1614+ let factor = Int64Array :: from ( vec ! [ 3 , -2 , i64 :: MAX ] ) ;
1615+ let expected = IntervalYearMonthArray :: from ( vec ! [ 48 , -10 , 0 ] ) ;
1616+ assert_eq ! ( mul( & interval, & factor) . unwrap( ) . as_ref( ) , & expected) ;
1617+ assert_eq ! ( mul( & factor, & interval) . unwrap( ) . as_ref( ) , & expected) ;
1618+
1619+ let interval = IntervalDayTimeArray :: from ( vec ! [
1620+ Some ( IntervalDayTimeType :: make_value( 10 , 2 * 60 * 60 * 1000 ) ) ,
1621+ None ,
1622+ ] ) ;
1623+ let factor = Int64Array :: new_scalar ( 3 ) ;
1624+ let expected = IntervalDayTimeArray :: from ( vec ! [
1625+ Some ( IntervalDayTimeType :: make_value( 30 , 6 * 60 * 60 * 1000 ) ) ,
1626+ None ,
1627+ ] ) ;
1628+ assert_eq ! ( mul( & interval, & factor) . unwrap( ) . as_ref( ) , & expected) ;
1629+ assert_eq ! ( mul( & factor, & interval) . unwrap( ) . as_ref( ) , & expected) ;
1630+
1631+ let null_factor = Scalar :: new ( Int64Array :: new_null ( 1 ) ) ;
1632+ let expected = IntervalDayTimeArray :: new_null ( interval. len ( ) ) ;
1633+ assert_eq ! ( mul( & interval, & null_factor) . unwrap( ) . as_ref( ) , & expected) ;
1634+ assert_eq ! ( mul( & null_factor, & interval) . unwrap( ) . as_ref( ) , & expected) ;
1635+
1636+ let interval = IntervalMonthDayNanoArray :: new_scalar ( IntervalMonthDayNanoType :: make_value (
1637+ 12 ,
1638+ 15 ,
1639+ 5_000_000_000 ,
1640+ ) ) ;
1641+ let factor = Int64Array :: from ( vec ! [ 2 , 0 , -1 ] ) ;
1642+ let expected = IntervalMonthDayNanoArray :: from ( vec ! [
1643+ IntervalMonthDayNanoType :: make_value( 24 , 30 , 10_000_000_000 ) ,
1644+ IntervalMonthDayNanoType :: make_value( 0 , 0 , 0 ) ,
1645+ IntervalMonthDayNanoType :: make_value( -12 , -15 , -5_000_000_000 ) ,
1646+ ] ) ;
1647+ assert_eq ! ( mul( & interval, & factor) . unwrap( ) . as_ref( ) , & expected) ;
1648+ assert_eq ! ( mul( & factor, & interval) . unwrap( ) . as_ref( ) , & expected) ;
1649+
1650+ let float_factor = Float64Array :: new_scalar ( 2. ) ;
1651+ assert ! ( mul( & interval, & float_factor) . is_err( ) ) ;
1652+ assert ! ( mul_wrapping( & factor, & interval) . is_err( ) ) ;
1653+ }
1654+
1655+ #[ test]
1656+ fn test_interval_mul_i64_overflow ( ) {
1657+ let interval = IntervalYearMonthArray :: from ( vec ! [ i32 :: MAX ] ) ;
1658+ let factor = Int64Array :: from ( vec ! [ 2 ] ) ;
1659+ assert_eq ! (
1660+ mul( & interval, & factor) . unwrap_err( ) . to_string( ) ,
1661+ "Arithmetic overflow: Overflow happened on: 2147483647 * 2"
1662+ ) ;
1663+
1664+ let interval = IntervalMonthDayNanoArray :: from ( vec ! [ IntervalMonthDayNanoType :: make_value(
1665+ 0 ,
1666+ 0 ,
1667+ i64 :: MAX ,
1668+ ) ] ) ;
1669+ assert_eq ! (
1670+ mul( & interval, & factor) . unwrap_err( ) . to_string( ) ,
1671+ "Arithmetic overflow: Overflow happened on: 9223372036854775807 * 2"
1672+ ) ;
1673+ }
1674+
15581675 fn test_duration_impl < T : ArrowPrimitiveType < Native = i64 > > ( ) {
15591676 let a = PrimitiveArray :: < T > :: new ( vec ! [ 1000 , 4394 , -3944 ] . into ( ) , None ) ;
15601677 let b = PrimitiveArray :: < T > :: new ( vec ! [ 4 , -5 , -243 ] . into ( ) , None ) ;
0 commit comments