Skip to content

Commit d55a105

Browse files
authored
Support modulus op (#577)
1 parent f2c01de commit d55a105

File tree

1 file changed

+34
-18
lines changed
  • datafusion/src/physical_plan/expressions

1 file changed

+34
-18
lines changed

datafusion/src/physical_plan/expressions/binary.rs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::{any::Any, sync::Arc};
2020
use arrow::array::TimestampMillisecondArray;
2121
use arrow::array::*;
2222
use arrow::compute::kernels::arithmetic::{
23-
add, divide, divide_scalar, multiply, subtract,
23+
add, divide, divide_scalar, modulus, modulus_scalar, multiply, subtract,
2424
};
2525
use arrow::compute::kernels::boolean::{and_kleene, or_kleene};
2626
use 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

Comments
 (0)