Skip to content

Commit 879a011

Browse files
committed
Normalize List take indices before range rebuild
Signed-off-by: Daniel King <dan@spiraldb.com>
1 parent 608b9ac commit 879a011

1 file changed

Lines changed: 17 additions & 29 deletions

File tree

  • vortex-array/src/arrays/list/compute

vortex-array/src/arrays/list/compute/take.rs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
use itertools::Itertools as _;
55
use vortex_buffer::BufferMut;
6-
use vortex_error::VortexExpect;
76
use vortex_error::VortexResult;
87
use vortex_error::vortex_bail;
98
use vortex_error::vortex_ensure;
109
use vortex_error::vortex_err;
10+
use vortex_mask::Mask;
1111

1212
use crate::ArrayRef;
1313
use crate::Canonical;
@@ -26,11 +26,13 @@ use crate::arrays::list::ListArrayExt;
2626
use crate::arrays::piecewise_sequence::constant_unsigned_usize;
2727
use crate::arrays::piecewise_sequence::maybe_contiguous_slices;
2828
use crate::arrays::primitive::PrimitiveArrayExt;
29+
use crate::builtins::ArrayBuiltins;
2930
use crate::dtype::IntegerPType;
3031
use crate::dtype::UnsignedPType;
3132
use crate::executor::ExecutionCtx;
3233
use crate::match_each_unsigned_integer_ptype;
3334
use crate::match_smallest_offset_type;
35+
use crate::scalar::Scalar;
3436
use crate::validity::Validity;
3537

3638
// TODO(connor)[ListView]: Re-revert to the version where we simply convert to a `ListView` and call
@@ -54,10 +56,16 @@ impl TakeExecute for List {
5456
return Ok(Some(taken));
5557
}
5658

57-
let indices = indices.clone().execute::<PrimitiveArray>(ctx)?;
59+
let new_validity = array.validity()?.take(indices)?;
60+
let normalized_indices = indices
61+
.clone()
62+
.mask(new_validity.to_array(indices.len()))?
63+
.fill_null(Scalar::from(0).cast(indices.dtype())?)?;
64+
let indices = normalized_indices.execute::<PrimitiveArray>(ctx)?;
5865
let indices = indices.reinterpret_cast(indices.ptype().to_unsigned());
5966
let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
6067
let offsets = offsets.reinterpret_cast(offsets.ptype().to_unsigned());
68+
let validity_mask = new_validity.execute_mask(indices.len(), ctx)?;
6169
// This is an over-approximation of the total number of elements in the resulting array.
6270
let total_approx = array.elements().len().saturating_mul(indices.len());
6371

@@ -68,7 +76,8 @@ impl TakeExecute for List {
6876
array,
6977
offsets.as_view(),
7078
indices.as_view(),
71-
ctx,
79+
new_validity,
80+
&validity_mask,
7281
)
7382
.map(Some)
7483
})
@@ -85,16 +94,9 @@ fn take_with_piecewise_elements<
8594
array: ArrayView<'_, List>,
8695
offsets_array: ArrayView<'_, Primitive>,
8796
indices_array: ArrayView<'_, Primitive>,
88-
ctx: &mut ExecutionCtx,
97+
new_validity: Validity,
98+
validity_mask: &Mask,
8999
) -> VortexResult<ArrayRef> {
90-
let data_validity = array
91-
.list_validity()
92-
.execute_mask(array.as_ref().len(), ctx)?;
93-
let indices_validity = indices_array
94-
.validity()
95-
.vortex_expect("Failed to compute validity mask")
96-
.execute_mask(indices_array.as_ref().len(), ctx)?;
97-
98100
let offsets: &[O] = offsets_array.as_slice();
99101
let indices: &[I] = indices_array.as_slice();
100102

@@ -109,8 +111,8 @@ fn take_with_piecewise_elements<
109111
let mut current_offset = 0usize;
110112
new_offsets.push(OutputOffsetType::zero());
111113

112-
for (&data_idx, index_valid) in indices.iter().zip_eq(indices_validity.iter()) {
113-
if !index_valid {
114+
for (&data_idx, is_valid) in indices.iter().zip_eq(validity_mask.iter()) {
115+
if !is_valid {
114116
new_offsets.push(new_offset_value::<OutputOffsetType>(current_offset)?);
115117
element_starts.push(0);
116118
element_lengths.push(0);
@@ -119,13 +121,6 @@ fn take_with_piecewise_elements<
119121

120122
let data_idx: usize = data_idx.as_();
121123

122-
if !data_validity.value(data_idx) {
123-
new_offsets.push(new_offset_value::<OutputOffsetType>(current_offset)?);
124-
element_starts.push(0);
125-
element_lengths.push(0);
126-
continue;
127-
}
128-
129124
let start = offsets[data_idx];
130125
let stop = offsets[data_idx + 1];
131126
let start: usize = start.as_();
@@ -160,14 +155,7 @@ fn take_with_piecewise_elements<
160155

161156
// SAFETY: offsets are rebuilt from the gathered element ranges and have one entry per output
162157
// row plus the leading zero; validity is produced by the usual take-validity path.
163-
Ok(unsafe {
164-
ListArray::new_unchecked(
165-
new_elements,
166-
new_offsets,
167-
array.validity()?.take(indices_array.array())?,
168-
)
169-
}
170-
.into_array())
158+
Ok(unsafe { ListArray::new_unchecked(new_elements, new_offsets, new_validity) }.into_array())
171159
}
172160

173161
fn take_piecewise_sequence(

0 commit comments

Comments
 (0)