@@ -20,7 +20,7 @@ use std::{any::Any, sync::Arc};
2020use arrow:: array:: TimestampMillisecondArray ;
2121use arrow:: array:: * ;
2222use arrow:: compute:: kernels:: arithmetic:: {
23- add, divide, divide_scalar, multiply, subtract,
23+ add, divide, divide_scalar, modulus , modulus_scalar , multiply, subtract,
2424} ;
2525use arrow:: compute:: kernels:: boolean:: { and_kleene, or_kleene} ;
2626use arrow:: compute:: kernels:: comparison:: { eq, gt, gt_eq, lt, lt_eq, neq} ;
@@ -360,14 +360,11 @@ fn common_binary_type(
360360 }
361361 // for math expressions, the final value of the coercion is also the return type
362362 // because coercion favours higher information types
363- Operator :: Plus | Operator :: Minus | Operator :: Divide | Operator :: Multiply => {
364- numerical_coercion ( lhs_type, rhs_type)
365- }
366- Operator :: Modulus => {
367- return Err ( DataFusionError :: NotImplemented (
368- "Modulus operator is still not supported" . to_string ( ) ,
369- ) )
370- }
363+ Operator :: Plus
364+ | Operator :: Minus
365+ | Operator :: Modulus
366+ | Operator :: Divide
367+ | Operator :: Multiply => numerical_coercion ( lhs_type, rhs_type) ,
371368 } ;
372369
373370 // re-write the error message of failed coercions to include the operator's information
@@ -408,12 +405,11 @@ pub fn binary_operator_data_type(
408405 | Operator :: GtEq
409406 | Operator :: LtEq => Ok ( DataType :: Boolean ) ,
410407 // math operations return the same value as the common coerced type
411- Operator :: Plus | Operator :: Minus | Operator :: Divide | Operator :: Multiply => {
412- Ok ( common_type)
413- }
414- Operator :: Modulus => Err ( DataFusionError :: NotImplemented (
415- "Modulus operator is still not supported" . to_string ( ) ,
416- ) ) ,
408+ Operator :: Plus
409+ | Operator :: Minus
410+ | Operator :: Divide
411+ | Operator :: Multiply
412+ | Operator :: Modulus => Ok ( common_type) ,
417413 }
418414}
419415
@@ -473,6 +469,9 @@ impl PhysicalExpr for BinaryExpr {
473469 Operator :: Divide => {
474470 binary_primitive_array_op_scalar ! ( array, scalar. clone( ) , divide)
475471 }
472+ Operator :: Modulus => {
473+ binary_primitive_array_op_scalar ! ( array, scalar. clone( ) , modulus)
474+ }
476475 // if scalar operation is not supported - fallback to array implementation
477476 _ => None ,
478477 }
@@ -522,6 +521,7 @@ impl PhysicalExpr for BinaryExpr {
522521 Operator :: Minus => binary_primitive_array_op ! ( left, right, subtract) ,
523522 Operator :: Multiply => binary_primitive_array_op ! ( left, right, multiply) ,
524523 Operator :: Divide => binary_primitive_array_op ! ( left, right, divide) ,
524+ Operator :: Modulus => binary_primitive_array_op ! ( left, right, modulus) ,
525525 Operator :: And => {
526526 if left_data_type == DataType :: Boolean {
527527 boolean_op ! ( left, right, and_kleene)
@@ -544,9 +544,6 @@ impl PhysicalExpr for BinaryExpr {
544544 ) ) ) ;
545545 }
546546 }
547- Operator :: Modulus => Err ( DataFusionError :: NotImplemented (
548- "Modulus operator is still not supported" . to_string ( ) ,
549- ) ) ,
550547 } ;
551548 result. map ( |a| ColumnarValue :: Array ( a) )
552549 }
@@ -996,6 +993,25 @@ mod tests {
996993 Ok ( ( ) )
997994 }
998995
996+ #[ test]
997+ fn modulus_op ( ) -> Result < ( ) > {
998+ let schema = Arc :: new ( Schema :: new ( vec ! [
999+ Field :: new( "a" , DataType :: Int32 , false ) ,
1000+ Field :: new( "b" , DataType :: Int32 , false ) ,
1001+ ] ) ) ;
1002+ let a = Arc :: new ( Int32Array :: from ( vec ! [ 8 , 32 , 128 , 512 , 2048 ] ) ) ;
1003+ let b = Arc :: new ( Int32Array :: from ( vec ! [ 2 , 4 , 7 , 14 , 32 ] ) ) ;
1004+
1005+ apply_arithmetic :: < Int32Type > (
1006+ schema,
1007+ vec ! [ a, b] ,
1008+ Operator :: Modulus ,
1009+ Int32Array :: from ( vec ! [ 0 , 0 , 2 , 8 , 0 ] ) ,
1010+ ) ?;
1011+
1012+ Ok ( ( ) )
1013+ }
1014+
9991015 fn apply_arithmetic < T : ArrowNumericType > (
10001016 schema : SchemaRef ,
10011017 data : Vec < ArrayRef > ,
0 commit comments