33
44use itertools:: Itertools as _;
55use vortex_buffer:: BufferMut ;
6- use vortex_error:: VortexExpect ;
76use vortex_error:: VortexResult ;
87use vortex_error:: vortex_ensure;
98use vortex_error:: vortex_err;
@@ -25,11 +24,13 @@ use crate::arrays::list::ListArrayExt;
2524use crate :: arrays:: piecewise_sequence:: constant_unsigned_usize;
2625use crate :: arrays:: piecewise_sequence:: maybe_contiguous_slices;
2726use crate :: arrays:: primitive:: PrimitiveArrayExt ;
27+ use crate :: builtins:: ArrayBuiltins ;
2828use crate :: dtype:: IntegerPType ;
2929use crate :: dtype:: UnsignedPType ;
3030use crate :: executor:: ExecutionCtx ;
3131use crate :: match_each_unsigned_integer_ptype;
3232use crate :: match_smallest_offset_type;
33+ use crate :: scalar:: Scalar ;
3334use 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
172159fn take_slices (
0 commit comments