This is an automated email from the ASF dual-hosted git repository.
Jefffrey pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 895a2f2ab3 fix(arrow-arith): handle sliced boolean arrays in and_not
(#10699)
895a2f2ab3 is described below
commit 895a2f2ab3176dd6179e5762108b4e3d66eb6ad0
Author: yongster <[email protected]>
AuthorDate: Sat Aug 15 22:17:08 2026 +0800
fix(arrow-arith): handle sliced boolean arrays in and_not (#10699)
# Which issue does this PR close?
- Closes #10699.
# Rationale for this change
`and_not` produced incorrect values for sliced `BooleanArray`s.
The implementation passed the left and right bitmap offsets to
`buffer_bin_and_not` in reverse order. It also reapplied `left.offset()`
when
wrapping a buffer that had already been normalized to offset zero.
As a result, `and_not(left, right)` could differ from its documented
equivalent, `and(left, not(right))`, when the input arrays were slices.
# What changes are included in this PR?
- Pass the bitmap offsets to `buffer_bin_and_not` in the correct order.
- Wrap its normalized result with offset `0`.
- Add regression tests for sliced inputs with matching and different
offsets.
# Are there any user-facing changes?
No API changes. This fixes incorrect results returned by the existing
public
`and_not` API when called with sliced `BooleanArray`s.
# Tests
```text
cargo test -p arrow-arith and_not
cargo fmt --check
Co-authored-by: yang3.xie <[email protected]>
---
arrow-arith/src/boolean.rs | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/arrow-arith/src/boolean.rs b/arrow-arith/src/boolean.rs
index 6bf438e646..020ba39590 100644
--- a/arrow-arith/src/boolean.rs
+++ b/arrow-arith/src/boolean.rs
@@ -290,8 +290,8 @@ pub fn or(left: &BooleanArray, right: &BooleanArray) ->
Result<BooleanArray, Arr
/// assert_eq!(andn_ab, and(&a, ¬(&b).unwrap()).unwrap());
pub fn and_not(left: &BooleanArray, right: &BooleanArray) ->
Result<BooleanArray, ArrowError> {
binary_boolean_kernel(left, right, |a, b| {
- let buffer = buffer_bin_and_not(a.inner(), b.offset(), b.inner(),
a.offset(), a.len());
- BooleanBuffer::new(buffer, left.offset(), left.len())
+ let buffer = buffer_bin_and_not(a.inner(), a.offset(), b.inner(),
b.offset(), a.len());
+ BooleanBuffer::new(buffer, 0, left.len())
})
}
@@ -394,6 +394,30 @@ mod tests {
assert_eq!(c, and(&a, ¬(&b).unwrap()).unwrap());
}
+ #[test]
+ fn test_bool_array_and_not_sliced() {
+ let a = BooleanArray::from(vec![true, false, true, false, true, false,
true]);
+ let b = BooleanArray::from(vec![false, true, false, true, false, true,
false]);
+ let a = a.slice(2, 3);
+ let b = b.slice(2, 3);
+ let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
+ let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
+
+ assert_eq!(and_not(a, b).unwrap(), and(a, ¬(b).unwrap()).unwrap());
+ }
+
+ #[test]
+ fn test_bool_array_and_not_sliced_different_offsets() {
+ let a = BooleanArray::from(vec![false, true, true, false, true, false,
true]);
+ let b = BooleanArray::from(vec![true, false, false, true, false, true,
false]);
+ let a = a.slice(1, 4);
+ let b = b.slice(2, 4);
+ let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
+ let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
+
+ assert_eq!(and_not(a, b).unwrap(), and(a, ¬(b).unwrap()).unwrap());
+ }
+
#[test]
fn test_bool_array_or_nulls() {
let a = BooleanArray::from(vec![