@@ -19,7 +19,7 @@ use crate::coalesce::InProgressArray;
1919use crate :: filter:: { FilterPredicate , IndexIterator , IterationStrategy , SlicesIterator } ;
2020use arrow_array:: cast:: AsArray ;
2121use arrow_array:: { Array , ArrayRef , ArrowPrimitiveType , PrimitiveArray } ;
22- use arrow_buffer:: { NullBufferBuilder , ScalarBuffer } ;
22+ use arrow_buffer:: { NullBufferBuilder , ScalarBuffer , bit_util } ;
2323use arrow_schema:: { ArrowError , DataType } ;
2424use std:: fmt:: Debug ;
2525use std:: sync:: Arc ;
@@ -153,16 +153,28 @@ impl<T: ArrowPrimitiveType + Debug> InProgressArray for InProgressPrimitiveArray
153153 IterationStrategy :: IndexIterator => {
154154 // Copy values and nulls for each index
155155 if let Some ( nulls) = s. nulls ( ) . filter ( |n| n. null_count ( ) > 0 ) {
156- let indices = IndexIterator :: new ( filter. filter_array ( ) , count) ;
157- self . current . extend ( indices. map ( |idx : usize | {
158- if nulls. is_null ( idx) {
159- self . nulls . append_null ( ) ;
160- } else {
161- self . nulls . append_non_null ( ) ;
162- }
163- // SAFETY: idx is derived from filter predicate
164- unsafe { * values. get_unchecked ( idx) }
165- } ) ) ;
156+ let null_buffer = nulls. inner ( ) ;
157+ let null_ptr = null_buffer. values ( ) . as_ptr ( ) ;
158+ let null_offset = null_buffer. offset ( ) ;
159+
160+ // Collect indices for reuse (values + nulls)
161+ let indices: Vec < usize > =
162+ IndexIterator :: new ( filter. filter_array ( ) , count) . collect ( ) ;
163+
164+ // Efficiently extend null buffer
165+ // SAFETY: indices iterator reports correct length
166+ unsafe {
167+ self . nulls . extend_from_trusted_len_iter (
168+ indices
169+ . iter ( )
170+ . map ( |& idx| bit_util:: get_bit_raw ( null_ptr, idx + null_offset) ) ,
171+ ) ;
172+ }
173+
174+ // Copy values
175+ // SAFETY: indices are derived from filter predicate
176+ self . current
177+ . extend ( indices. iter ( ) . map ( |& idx| unsafe { * values. get_unchecked ( idx) } ) ) ;
166178 } else {
167179 self . nulls . append_n_non_nulls ( count) ;
168180 let indices = IndexIterator :: new ( filter. filter_array ( ) , count) ;
@@ -174,16 +186,24 @@ impl<T: ArrowPrimitiveType + Debug> InProgressArray for InProgressPrimitiveArray
174186 IterationStrategy :: Indices ( indices) => {
175187 // Copy values and nulls using precomputed indices
176188 if let Some ( nulls) = s. nulls ( ) . filter ( |n| n. null_count ( ) > 0 ) {
177- self . current . extend ( indices. iter ( ) . map ( |& idx| {
178- // TODO: speed up
179- if nulls. is_null ( idx) {
180- self . nulls . append_null ( ) ;
181- } else {
182- self . nulls . append_non_null ( ) ;
183- }
184- // SAFETY: indices are derived from filter predicate
185- unsafe { * values. get_unchecked ( idx) }
186- } ) ) ;
189+ let null_buffer = nulls. inner ( ) ;
190+ let null_ptr = null_buffer. values ( ) . as_ptr ( ) ;
191+ let null_offset = null_buffer. offset ( ) ;
192+
193+ // Efficiently extend null buffer
194+ // SAFETY: indices iterator reports correct length
195+ unsafe {
196+ self . nulls . extend_from_trusted_len_iter (
197+ indices
198+ . iter ( )
199+ . map ( |& idx| bit_util:: get_bit_raw ( null_ptr, idx + null_offset) ) ,
200+ ) ;
201+ }
202+
203+ // Copy values
204+ // SAFETY: indices are derived from filter predicate
205+ self . current
206+ . extend ( indices. iter ( ) . map ( |& idx| unsafe { * values. get_unchecked ( idx) } ) ) ;
187207 } else {
188208 self . nulls . append_n_non_nulls ( count) ;
189209 // SAFETY: indices are derived from filter predicate
0 commit comments