Skip to content

Commit 844f8a5

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

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::Columnar;
@@ -24,11 +24,13 @@ use crate::arrays::list::ListArrayExt;
2424
use crate::arrays::piecewise_sequence::constant_unsigned_usize;
2525
use crate::arrays::piecewise_sequence::maybe_contiguous_slices;
2626
use crate::arrays::primitive::PrimitiveArrayExt;
27+
use crate::builtins::ArrayBuiltins;
2728
use crate::dtype::IntegerPType;
2829
use crate::dtype::UnsignedPType;
2930
use crate::executor::ExecutionCtx;
3031
use crate::match_each_unsigned_integer_ptype;
3132
use crate::match_smallest_offset_type;
33+
use crate::scalar::Scalar;
3234
use crate::validity::Validity;
3335

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

55-
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)?;
5663
let indices = indices.reinterpret_cast(indices.ptype().to_unsigned());
5764
let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
5865
let offsets = offsets.reinterpret_cast(offsets.ptype().to_unsigned());
66+
let validity_mask = new_validity.execute_mask(indices.len(), ctx)?;
5967
// This is an over-approximation of the total number of elements in the resulting array.
6068
let total_approx = array.elements().len().saturating_mul(indices.len());
6169

@@ -66,7 +74,8 @@ impl TakeExecute for List {
6674
array,
6775
offsets.as_view(),
6876
indices.as_view(),
69-
ctx,
77+
new_validity,
78+
&validity_mask,
7079
)
7180
.map(Some)
7281
})
@@ -83,16 +92,9 @@ fn take_with_piecewise_elements<
8392
array: ArrayView<'_, List>,
8493
offsets_array: ArrayView<'_, Primitive>,
8594
indices_array: ArrayView<'_, Primitive>,
86-
ctx: &mut ExecutionCtx,
95+
new_validity: Validity,
96+
validity_mask: &Mask,
8797
) -> VortexResult<ArrayRef> {
88-
let data_validity = array
89-
.list_validity()
90-
.execute_mask(array.as_ref().len(), ctx)?;
91-
let indices_validity = indices_array
92-
.validity()
93-
.vortex_expect("Failed to compute validity mask")
94-
.execute_mask(indices_array.as_ref().len(), ctx)?;
95-
9698
let offsets: &[O] = offsets_array.as_slice();
9799
let indices: &[I] = indices_array.as_slice();
98100

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

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

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

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

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

171159
fn take_piecewise_sequence(

0 commit comments

Comments
 (0)