Skip to content

Commit fb435f1

Browse files
committed
Normalize List take indices before range rebuild
Signed-off-by: Daniel King <dan@spiraldb.com>
1 parent 90c43ab commit fb435f1

1 file changed

Lines changed: 16 additions & 29 deletions

File tree

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

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

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
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_ensure;
98
use vortex_error::vortex_err;
@@ -25,11 +24,13 @@ use crate::arrays::list::ListArrayExt;
2524
use crate::arrays::piecewise_sequence::constant_unsigned_usize;
2625
use crate::arrays::piecewise_sequence::maybe_contiguous_slices;
2726
use crate::arrays::primitive::PrimitiveArrayExt;
27+
use crate::builtins::ArrayBuiltins;
2828
use crate::dtype::IntegerPType;
2929
use crate::dtype::UnsignedPType;
3030
use crate::executor::ExecutionCtx;
3131
use crate::match_each_unsigned_integer_ptype;
3232
use crate::match_smallest_offset_type;
33+
use crate::scalar::Scalar;
3334
use crate::validity::Validity;
3435

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

56-
let indices = indices.clone().execute::<PrimitiveArray>(ctx)?;
57+
let new_validity = array.validity()?.take(indices)?;
58+
let normalized_indices = indices
59+
.clone()
60+
.mask(new_validity.to_array(indices.len()))?
61+
.fill_null(Scalar::from(0).cast(indices.dtype())?)?;
62+
let indices = normalized_indices.execute::<PrimitiveArray>(ctx)?;
5763
let indices = indices.reinterpret_cast(indices.ptype().to_unsigned());
5864
let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
5965
let offsets = offsets.reinterpret_cast(offsets.ptype().to_unsigned());
66+
let validity_mask = new_validity.execute_mask(indices.len(), ctx)?;
6067
// This is an over-approximation of the total number of elements in the resulting array.
6168
let total_approx = array.elements().len().saturating_mul(indices.len());
6269

@@ -67,7 +74,8 @@ impl TakeExecute for List {
6774
array,
6875
offsets.as_view(),
6976
indices.as_view(),
70-
ctx,
77+
new_validity,
78+
&validity_mask,
7179
)
7280
.map(Some)
7381
})
@@ -84,16 +92,9 @@ fn take_with_piecewise_elements<
8492
array: ArrayView<'_, List>,
8593
offsets_array: ArrayView<'_, Primitive>,
8694
indices_array: ArrayView<'_, Primitive>,
87-
ctx: &mut ExecutionCtx,
95+
new_validity: Validity,
96+
validity_mask: &Mask,
8897
) -> VortexResult<ArrayRef> {
89-
let data_validity = array
90-
.list_validity()
91-
.execute_mask(array.as_ref().len(), ctx)?;
92-
let indices_validity = indices_array
93-
.validity()
94-
.vortex_expect("Failed to compute validity mask")
95-
.execute_mask(indices_array.as_ref().len(), ctx)?;
96-
9798
let offsets: &[O] = offsets_array.as_slice();
9899
let indices: &[I] = indices_array.as_slice();
99100

@@ -108,8 +109,8 @@ fn take_with_piecewise_elements<
108109
let mut current_offset = 0usize;
109110
new_offsets.push(OutputOffsetType::zero());
110111

111-
for (&data_idx, index_valid) in indices.iter().zip_eq(indices_validity.iter()) {
112-
if !index_valid {
112+
for (&data_idx, is_valid) in indices.iter().zip_eq(validity_mask.iter()) {
113+
if !is_valid {
113114
new_offsets.push(new_offset_value::<OutputOffsetType>(current_offset)?);
114115
element_starts.push(0);
115116
element_lengths.push(0);
@@ -118,13 +119,6 @@ fn take_with_piecewise_elements<
118119

119120
let data_idx: usize = data_idx.as_();
120121

121-
if !data_validity.value(data_idx) {
122-
new_offsets.push(new_offset_value::<OutputOffsetType>(current_offset)?);
123-
element_starts.push(0);
124-
element_lengths.push(0);
125-
continue;
126-
}
127-
128122
let start = offsets[data_idx];
129123
let stop = offsets[data_idx + 1];
130124
let start: usize = start.as_();
@@ -159,14 +153,7 @@ fn take_with_piecewise_elements<
159153

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

172159
fn take_slices(

0 commit comments

Comments
 (0)