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;
9+ use vortex_mask:: Mask ;
1010
1111use crate :: ArrayRef ;
1212use crate :: Columnar ;
@@ -24,11 +24,13 @@ use crate::arrays::list::ListArrayExt;
2424use crate :: arrays:: piecewise_sequence:: constant_unsigned_usize;
2525use crate :: arrays:: piecewise_sequence:: maybe_contiguous_slices;
2626use crate :: arrays:: primitive:: PrimitiveArrayExt ;
27+ use crate :: builtins:: ArrayBuiltins ;
2728use crate :: dtype:: IntegerPType ;
2829use crate :: dtype:: UnsignedPType ;
2930use crate :: executor:: ExecutionCtx ;
3031use crate :: match_each_unsigned_integer_ptype;
3132use crate :: match_smallest_offset_type;
33+ use crate :: scalar:: Scalar ;
3234use 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
171159fn take_piecewise_sequence (
0 commit comments