Skip to content

Commit b7ad4df

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

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,10 +3,10 @@
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;
9+
use vortex_mask::Mask;
1010

1111
use crate::ArrayRef;
1212
use crate::IntoArray;
@@ -23,11 +23,13 @@ use crate::arrays::list::ListArrayExt;
2323
use crate::arrays::piecewise_sequence::UnitMultiplierLengths;
2424
use crate::arrays::piecewise_sequence::execute_unit_multiplier_index_arrays;
2525
use crate::arrays::primitive::PrimitiveArrayExt;
26+
use crate::builtins::ArrayBuiltins;
2627
use crate::dtype::IntegerPType;
2728
use crate::dtype::UnsignedPType;
2829
use crate::executor::ExecutionCtx;
2930
use crate::match_each_unsigned_integer_ptype;
3031
use crate::match_smallest_offset_type;
32+
use crate::scalar::Scalar;
3133
use crate::validity::Validity;
3234

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

54-
let indices = indices.clone().execute::<PrimitiveArray>(ctx)?;
56+
let new_validity = array.validity()?.take(indices)?;
57+
let normalized_indices = indices
58+
.clone()
59+
.mask(new_validity.to_array(indices.len()))?
60+
.fill_null(Scalar::from(0).cast(indices.dtype())?)?;
61+
let indices = normalized_indices.execute::<PrimitiveArray>(ctx)?;
5562
let indices = indices.reinterpret_cast(indices.ptype().to_unsigned());
5663
let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
5764
let offsets = offsets.reinterpret_cast(offsets.ptype().to_unsigned());
65+
let validity_mask = new_validity.execute_mask(indices.len(), ctx)?;
5866
// This is an over-approximation of the total number of elements in the resulting array.
5967
let total_approx = array.elements().len().saturating_mul(indices.len());
6068

@@ -65,7 +73,8 @@ impl TakeExecute for List {
6573
array,
6674
offsets.as_view(),
6775
indices.as_view(),
68-
ctx,
76+
new_validity,
77+
&validity_mask,
6978
)
7079
.map(Some)
7180
})
@@ -82,16 +91,9 @@ fn take_with_piecewise_elements<
8291
array: ArrayView<'_, List>,
8392
offsets_array: ArrayView<'_, Primitive>,
8493
indices_array: ArrayView<'_, Primitive>,
85-
ctx: &mut ExecutionCtx,
94+
new_validity: Validity,
95+
validity_mask: &Mask,
8696
) -> VortexResult<ArrayRef> {
87-
let data_validity = array
88-
.list_validity()
89-
.execute_mask(array.as_ref().len(), ctx)?;
90-
let indices_validity = indices_array
91-
.validity()
92-
.vortex_expect("Failed to compute validity mask")
93-
.execute_mask(indices_array.as_ref().len(), ctx)?;
94-
9597
let offsets: &[O] = offsets_array.as_slice();
9698
let indices: &[I] = indices_array.as_slice();
9799

@@ -106,8 +108,8 @@ fn take_with_piecewise_elements<
106108
let mut current_offset = 0usize;
107109
new_offsets.push(OutputOffsetType::zero());
108110

109-
for (&data_idx, index_valid) in indices.iter().zip_eq(indices_validity.iter()) {
110-
if !index_valid {
111+
for (&data_idx, is_valid) in indices.iter().zip_eq(validity_mask.iter()) {
112+
if !is_valid {
111113
new_offsets.push(new_offset_value::<OutputOffsetType>(current_offset)?);
112114
element_starts.push(0);
113115
element_lengths.push(0);
@@ -116,13 +118,6 @@ fn take_with_piecewise_elements<
116118

117119
let data_idx: usize = data_idx.as_();
118120

119-
if !data_validity.value(data_idx) {
120-
new_offsets.push(new_offset_value::<OutputOffsetType>(current_offset)?);
121-
element_starts.push(0);
122-
element_lengths.push(0);
123-
continue;
124-
}
125-
126121
let start = offsets[data_idx];
127122
let stop = offsets[data_idx + 1];
128123
let start: usize = start.as_();
@@ -157,14 +152,7 @@ fn take_with_piecewise_elements<
157152

158153
// SAFETY: offsets are rebuilt from the gathered element ranges and have one entry per output
159154
// row plus the leading zero; validity is produced by the usual take-validity path.
160-
Ok(unsafe {
161-
ListArray::new_unchecked(
162-
new_elements,
163-
new_offsets,
164-
array.validity()?.take(indices_array.array())?,
165-
)
166-
}
167-
.into_array())
155+
Ok(unsafe { ListArray::new_unchecked(new_elements, new_offsets, new_validity) }.into_array())
168156
}
169157

170158
fn take_piecewise_sequence(

0 commit comments

Comments
 (0)