Skip to content

Commit 8941959

Browse files
committed
Use a different approach to take fixed size binary that applies null buffers separately at the end
1 parent 10425c7 commit 8941959

File tree

1 file changed

+25
-25
lines changed

1 file changed

+25
-25
lines changed

arrow-select/src/take.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -367,13 +367,6 @@ pub struct TakeOptions {
367367
pub check_bounds: bool,
368368
}
369369

370-
#[inline(always)]
371-
fn maybe_usize<I: ArrowNativeType>(index: I) -> Result<usize, ArrowError> {
372-
index
373-
.to_usize()
374-
.ok_or_else(|| ArrowError::ComputeError("Cast to usize failed".to_string()))
375-
}
376-
377370
/// `take` implementation for all primitive arrays
378371
///
379372
/// This checks if an `indices` slot is populated, and gets the value from `values`
@@ -701,25 +694,32 @@ fn take_fixed_size_binary<IndexType: ArrowPrimitiveType>(
701694
indices: &PrimitiveArray<IndexType>,
702695
size: i32,
703696
) -> Result<FixedSizeBinaryArray, ArrowError> {
704-
let nulls = values.nulls();
705-
let array_iter = indices
706-
.iter()
707-
.map(|idx| {
708-
let Some(idx) = idx else {
709-
return Ok(None);
710-
};
711-
712-
let idx = maybe_usize::<IndexType::Native>(idx)?;
713-
if nulls.map(|n| n.is_valid(idx)).unwrap_or(true) {
714-
Ok(Some(values.value(idx)))
715-
} else {
716-
Ok(None)
717-
}
718-
})
719-
.collect::<Result<Vec<_>, ArrowError>>()?
720-
.into_iter();
697+
let size_usize = usize::try_from(size).map_err(|_| {
698+
ArrowError::InvalidArgumentError(format!("Cannot convert size '{}' to usize", size))
699+
})?;
700+
701+
let values_buffer = values.values().as_slice();
702+
let mut values_buffer_builder = BufferBuilder::new(indices.len() * size_usize);
703+
let array_iter = indices.values().iter().map(|idx| {
704+
let offset = idx.as_usize() * size_usize;
705+
&values_buffer[offset..offset + size_usize]
706+
});
707+
for slice in array_iter {
708+
values_buffer_builder.append_slice(slice);
709+
}
710+
let values_buffer = values_buffer_builder.finish();
711+
712+
let value_nulls = take_nulls(values.nulls(), indices);
713+
let final_nulls = NullBuffer::union(value_nulls.as_ref(), indices.nulls());
714+
715+
let array_data = ArrayDataBuilder::new(DataType::FixedSizeBinary(size))
716+
.len(indices.len())
717+
.nulls(final_nulls)
718+
.offset(0)
719+
.add_buffer(values_buffer)
720+
.build()?;
721721

722-
FixedSizeBinaryArray::try_from_sparse_iter_with_size(array_iter, size)
722+
Ok(FixedSizeBinaryArray::from(array_data))
723723
}
724724

725725
/// `take` implementation for dictionary arrays

0 commit comments

Comments
 (0)