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, &not(&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, &not(&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, &not(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, &not(b).unwrap()).unwrap());
+    }
+
     #[test]
     fn test_bool_array_or_nulls() {
         let a = BooleanArray::from(vec![

Reply via email to