33
44use itertools:: Itertools as _;
55use vortex_buffer:: BufferMut ;
6- use vortex_error:: VortexExpect ;
76use vortex_error:: VortexResult ;
87use vortex_error:: vortex_bail;
98use vortex_error:: vortex_ensure;
109use vortex_error:: vortex_err;
10+ use vortex_mask:: Mask ;
1111
1212use crate :: ArrayRef ;
1313use crate :: Canonical ;
@@ -26,11 +26,13 @@ use crate::arrays::list::ListArrayExt;
2626use crate :: arrays:: piecewise_sequence:: constant_unsigned_usize;
2727use crate :: arrays:: piecewise_sequence:: maybe_contiguous_slices;
2828use crate :: arrays:: primitive:: PrimitiveArrayExt ;
29+ use crate :: builtins:: ArrayBuiltins ;
2930use crate :: dtype:: IntegerPType ;
3031use crate :: dtype:: UnsignedPType ;
3132use crate :: executor:: ExecutionCtx ;
3233use crate :: match_each_unsigned_integer_ptype;
3334use crate :: match_smallest_offset_type;
35+ use crate :: scalar:: Scalar ;
3436use 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
173161fn take_piecewise_sequence (
0 commit comments