Skip to content

Commit

Permalink
Implement bitwise XOR operator (#) (#3430)
Browse files Browse the repository at this point in the history
* include bitwise xor operator

* fix clippy warning

Co-authored-by: srib <srib@MacDesktop.local>
  • Loading branch information
askoa and srib authored Sep 11, 2022
1 parent deea8c3 commit 8df5496
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 1 deletion.
2 changes: 2 additions & 0 deletions datafusion/expr/src/binary_rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub fn binary_operator_data_type(
// bitwise operations return the common coerced type
Operator::BitwiseAnd
| Operator::BitwiseOr
| Operator::BitwiseXor
| Operator::BitwiseShiftLeft
| Operator::BitwiseShiftRight => Ok(result_type),
// math operations return the same value as the common coerced type
Expand All @@ -81,6 +82,7 @@ pub fn coerce_types(
let result = match op {
Operator::BitwiseAnd
| Operator::BitwiseOr
| Operator::BitwiseXor
| Operator::BitwiseShiftRight
| Operator::BitwiseShiftLeft => bitwise_coercion(lhs_type, rhs_type),
Operator::And | Operator::Or => match (lhs_type, rhs_type) {
Expand Down
4 changes: 4 additions & 0 deletions datafusion/expr/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub enum Operator {
BitwiseAnd,
/// Bitwise or, like `|`
BitwiseOr,
/// Bitwise xor, like `#`
BitwiseXor,
/// Bitwise right, like `>>`
BitwiseShiftRight,
/// Bitwise left, like `<<`
Expand Down Expand Up @@ -107,6 +109,7 @@ impl Operator {
| Operator::RegexNotIMatch
| Operator::BitwiseAnd
| Operator::BitwiseOr
| Operator::BitwiseXor
| Operator::BitwiseShiftRight
| Operator::BitwiseShiftLeft
| Operator::StringConcat => None,
Expand Down Expand Up @@ -140,6 +143,7 @@ impl fmt::Display for Operator {
Operator::IsNotDistinctFrom => "IS NOT DISTINCT FROM",
Operator::BitwiseAnd => "&",
Operator::BitwiseOr => "|",
Operator::BitwiseXor => "#",
Operator::BitwiseShiftRight => ">>",
Operator::BitwiseShiftLeft => "<<",
Operator::StringConcat => "||",
Expand Down
26 changes: 25 additions & 1 deletion datafusion/physical-expr/src/expressions/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ use arrow::compute::kernels::concat_elements::concat_elements_utf8;
use kernels::{
bitwise_and, bitwise_and_scalar, bitwise_or, bitwise_or_scalar, bitwise_shift_left,
bitwise_shift_left_scalar, bitwise_shift_right, bitwise_shift_right_scalar,
bitwise_xor, bitwise_xor_scalar,
};
use kernels_arrow::{
add_decimal, add_decimal_scalar, divide_decimal, divide_decimal_scalar,
Expand Down Expand Up @@ -764,6 +765,7 @@ impl BinaryExpr {
),
Operator::BitwiseAnd => bitwise_and_scalar(array, scalar.clone()),
Operator::BitwiseOr => bitwise_or_scalar(array, scalar.clone()),
Operator::BitwiseXor => bitwise_xor_scalar(array, scalar.clone()),
Operator::BitwiseShiftRight => {
bitwise_shift_right_scalar(array, scalar.clone())
}
Expand Down Expand Up @@ -880,6 +882,7 @@ impl BinaryExpr {
}
Operator::BitwiseAnd => bitwise_and(left, right),
Operator::BitwiseOr => bitwise_or(left, right),
Operator::BitwiseXor => bitwise_xor(left, right),
Operator::BitwiseShiftRight => bitwise_shift_right(left, right),
Operator::BitwiseShiftLeft => bitwise_shift_left(left, right),
Operator::StringConcat => {
Expand Down Expand Up @@ -1295,6 +1298,18 @@ mod tests {
DataType::Int64,
vec![11i64, 6i64, 7i64]
);
test_coercion!(
Int16Array,
DataType::Int16,
vec![3i16, 2i16, 3i16],
Int64Array,
DataType::Int64,
vec![10i64, 6i64, 5i64],
Operator::BitwiseXor,
Int64Array,
DataType::Int64,
vec![9i64, 4i64, 6i64]
);
Ok(())
}

Expand Down Expand Up @@ -2511,6 +2526,11 @@ mod tests {
result = bitwise_or(left.clone(), right.clone())?;
let expected = Int32Array::from(vec![Some(13), None, Some(15)]);
assert_eq!(result.as_ref(), &expected);

result = bitwise_xor(left.clone(), right.clone())?;
let expected = Int32Array::from(vec![Some(13), None, Some(12)]);
assert_eq!(result.as_ref(), &expected);

Ok(())
}

Expand Down Expand Up @@ -2550,9 +2570,13 @@ mod tests {
let expected = Int32Array::from(vec![Some(0), None, Some(3)]);
assert_eq!(result.as_ref(), &expected);

result = bitwise_or_scalar(&left, right).unwrap()?;
result = bitwise_or_scalar(&left, right.clone()).unwrap()?;
let expected = Int32Array::from(vec![Some(15), None, Some(11)]);
assert_eq!(result.as_ref(), &expected);

result = bitwise_xor_scalar(&left, right).unwrap()?;
let expected = Int32Array::from(vec![Some(15), None, Some(8)]);
assert_eq!(result.as_ref(), &expected);
Ok(())
}

Expand Down
48 changes: 48 additions & 0 deletions datafusion/physical-expr/src/expressions/binary/kernels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,28 @@ pub(crate) fn bitwise_or(left: ArrayRef, right: ArrayRef) -> Result<ArrayRef> {
}
}

pub(crate) fn bitwise_xor(left: ArrayRef, right: ArrayRef) -> Result<ArrayRef> {
match &left.data_type() {
DataType::Int8 => {
binary_bitwise_array_op!(left, right, |a, b| a ^ b, Int8Array)
}
DataType::Int16 => {
binary_bitwise_array_op!(left, right, |a, b| a ^ b, Int16Array)
}
DataType::Int32 => {
binary_bitwise_array_op!(left, right, |a, b| a ^ b, Int32Array)
}
DataType::Int64 => {
binary_bitwise_array_op!(left, right, |a, b| a ^ b, Int64Array)
}
other => Err(DataFusionError::Internal(format!(
"Data type {:?} not supported for binary operation '{}' on dyn arrays",
other,
Operator::BitwiseXor
))),
}
}

pub(crate) fn bitwise_and_scalar(
array: &dyn Array,
scalar: ScalarValue,
Expand Down Expand Up @@ -253,6 +275,32 @@ pub(crate) fn bitwise_or_scalar(
Some(result)
}

pub(crate) fn bitwise_xor_scalar(
array: &dyn Array,
scalar: ScalarValue,
) -> Option<Result<ArrayRef>> {
let result = match array.data_type() {
DataType::Int8 => {
binary_bitwise_array_scalar!(array, scalar, |a, b| a ^ b, Int8Array, i8)
}
DataType::Int16 => {
binary_bitwise_array_scalar!(array, scalar, |a, b| a ^ b, Int16Array, i16)
}
DataType::Int32 => {
binary_bitwise_array_scalar!(array, scalar, |a, b| a ^ b, Int32Array, i32)
}
DataType::Int64 => {
binary_bitwise_array_scalar!(array, scalar, |a, b| a ^ b, Int64Array, i64)
}
other => Err(DataFusionError::Internal(format!(
"Data type {:?} not supported for binary operation '{}' on dyn arrays",
other,
Operator::BitwiseXor
))),
};
Some(result)
}

pub(crate) fn bitwise_shift_right_scalar(
array: &dyn Array,
scalar: ScalarValue,
Expand Down
1 change: 1 addition & 0 deletions datafusion/sql/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
BinaryOperator::PGRegexNotIMatch => Ok(Operator::RegexNotIMatch),
BinaryOperator::BitwiseAnd => Ok(Operator::BitwiseAnd),
BinaryOperator::BitwiseOr => Ok(Operator::BitwiseOr),
BinaryOperator::BitwiseXor => Ok(Operator::BitwiseXor),
BinaryOperator::PGBitwiseShiftRight => Ok(Operator::BitwiseShiftRight),
BinaryOperator::PGBitwiseShiftLeft => Ok(Operator::BitwiseShiftLeft),
BinaryOperator::StringConcat => Ok(Operator::StringConcat),
Expand Down

0 comments on commit 8df5496

Please sign in to comment.