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 :: IntoArray ;
@@ -23,11 +23,13 @@ use crate::arrays::list::ListArrayExt;
2323use crate :: arrays:: piecewise_sequence:: UnitMultiplierLengths ;
2424use crate :: arrays:: piecewise_sequence:: execute_unit_multiplier_index_arrays;
2525use crate :: arrays:: primitive:: PrimitiveArrayExt ;
26+ use crate :: builtins:: ArrayBuiltins ;
2627use crate :: dtype:: IntegerPType ;
2728use crate :: dtype:: UnsignedPType ;
2829use crate :: executor:: ExecutionCtx ;
2930use crate :: match_each_unsigned_integer_ptype;
3031use crate :: match_smallest_offset_type;
32+ use crate :: scalar:: Scalar ;
3133use 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
170158fn take_piecewise_sequence (
0 commit comments