Skip to content

Commit

Permalink
Cleanup nullif kernel (#4416)
Browse files Browse the repository at this point in the history
  • Loading branch information
tustvold authored Jun 14, 2023
1 parent 700bd33 commit 23177ee
Showing 1 changed file with 19 additions and 42 deletions.
61 changes: 19 additions & 42 deletions arrow-select/src/nullif.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@
// specific language governing permissions and limitations
// under the License.

use arrow_array::builder::BooleanBufferBuilder;
use arrow_array::{make_array, Array, ArrayRef, BooleanArray};
use arrow_buffer::buffer::{
bitwise_bin_op_helper, bitwise_unary_op_helper, buffer_bin_and,
};
use arrow_buffer::buffer::{bitwise_bin_op_helper, bitwise_unary_op_helper};
use arrow_buffer::{BooleanBuffer, NullBuffer};
use arrow_schema::ArrowError;

/// Copies original array, setting validity bit to false if a secondary comparison
Expand All @@ -28,16 +26,14 @@ use arrow_schema::ArrowError;
/// Typically used to implement NULLIF.
pub fn nullif(left: &dyn Array, right: &BooleanArray) -> Result<ArrayRef, ArrowError> {
let left_data = left.to_data();
let right_data = right.to_data();

if left_data.len() != right_data.len() {
if left_data.len() != right.len() {
return Err(ArrowError::ComputeError(
"Cannot perform comparison operation on arrays of different length"
.to_string(),
));
}
let len = left_data.len();
let l_offset = left_data.offset();

if len == 0 {
return Ok(make_array(left_data));
Expand All @@ -53,18 +49,9 @@ pub fn nullif(left: &dyn Array, right: &BooleanArray) -> Result<ArrayRef, ArrowE
// OR left null bitmap & !(right_values & right_bitmap)

// Compute right_values & right_bitmap
let (right, r_offset) = match right_data.nulls() {
Some(nulls) => (
buffer_bin_and(
right_data.buffers()[0],
right_data.offset(),
nulls.buffer(),
nulls.offset(),
len,
),
0,
),
None => (right_data.buffers()[0].clone(), right_data.offset()),
let right = match right.nulls() {
Some(nulls) => right.values() & nulls.inner(),
None => right.values().clone(),
};

// Compute left null bitmap & !right
Expand All @@ -75,8 +62,8 @@ pub fn nullif(left: &dyn Array, right: &BooleanArray) -> Result<ArrayRef, ArrowE
let b = bitwise_bin_op_helper(
left.buffer(),
left.offset(),
&right,
r_offset,
right.inner(),
right.offset(),
len,
|l, r| {
let t = l & !r;
Expand All @@ -88,31 +75,21 @@ pub fn nullif(left: &dyn Array, right: &BooleanArray) -> Result<ArrayRef, ArrowE
}
None => {
let mut null_count = 0;
let buffer = bitwise_unary_op_helper(&right, r_offset, len, |b| {
let t = !b;
null_count += t.count_zeros() as usize;
t
});
let buffer =
bitwise_unary_op_helper(right.inner(), right.offset(), len, |b| {
let t = !b;
null_count += t.count_zeros() as usize;
t
});
(buffer, null_count)
}
};

// Need to construct null buffer with offset of left
let null_buffer = match left_data.offset() {
0 => combined,
_ => {
let mut builder = BooleanBufferBuilder::new(len + l_offset);
// Pad with 0s up to offset
builder.resize(l_offset);
builder.append_packed_range(0..len, &combined);
builder.into()
}
};

let data = left_data
.into_builder()
.null_bit_buffer(Some(null_buffer))
.null_count(null_count);
let combined = BooleanBuffer::new(combined, 0, len);
// Safety:
// Counted nulls whilst computing
let nulls = unsafe { NullBuffer::new_unchecked(combined, null_count) };
let data = left_data.into_builder().nulls(Some(nulls));

// SAFETY:
// Only altered null mask
Expand Down

0 comments on commit 23177ee

Please sign in to comment.