@@ -14,18 +14,21 @@ use vortex_array::arrays::PrimitiveArray;
1414use vortex_array:: arrays:: StructArray ;
1515use vortex_array:: arrays:: struct_:: StructArrayExt ;
1616use vortex_array:: dtype:: DType ;
17- use vortex_array:: dtype:: FieldName ;
18- use vortex_array:: dtype:: FieldNames ;
1917use vortex_array:: dtype:: Nullability ;
2018use vortex_array:: dtype:: PType ;
2119use vortex_array:: dtype:: StructFields ;
2220use vortex_array:: expr:: Expression ;
21+ use vortex_array:: expr:: get_item;
22+ use vortex_array:: expr:: merge;
23+ use vortex_array:: expr:: pack;
2324use vortex_array:: expr:: pruning:: ROW_COUNT_FIELD ;
25+ use vortex_array:: expr:: root;
2426use vortex_array:: expr:: stats:: Precision ;
2527use vortex_array:: expr:: stats:: Stat ;
2628use vortex_array:: expr:: stats:: StatsProvider ;
2729use vortex_array:: stats:: StatsSet ;
2830use vortex_array:: validity:: Validity ;
31+ use vortex_buffer:: buffer;
2932use vortex_error:: VortexExpect ;
3033use vortex_error:: VortexResult ;
3134use vortex_error:: vortex_bail;
@@ -188,7 +191,6 @@ impl ZoneMap {
188191 ) -> VortexResult < Mask > {
189192 let mut ctx = session. create_execution_ctx ( ) ;
190193 self . with_row_count_field ( zone_len, row_count, & mut ctx) ?
191- . into_array ( )
192194 . apply ( predicate) ?
193195 . execute :: < Mask > ( & mut ctx)
194196 }
@@ -200,21 +202,22 @@ impl ZoneMap {
200202 zone_len : u64 ,
201203 row_count : u64 ,
202204 ctx : & mut ExecutionCtx ,
203- ) -> VortexResult < StructArray > {
205+ ) -> VortexResult < ArrayRef > {
204206 let num_zones = self . array . len ( ) ;
205207 let row_count = self . row_count_array ( zone_len, row_count, num_zones, ctx) ?;
206-
207- let mut names: Vec < FieldName > = self . array . names ( ) . iter ( ) . cloned ( ) . collect ( ) ;
208- let mut fields: Vec < ArrayRef > = self . array . iter_unmasked_fields ( ) . cloned ( ) . collect ( ) ;
209- names. push ( FieldName :: from ( ZONE_ROW_COUNT_FIELD ) ) ;
210- fields. push ( row_count) ;
211-
212- StructArray :: try_new (
213- FieldNames :: from_iter ( names) ,
214- fields,
215- num_zones,
216- self . array . struct_validity ( ) ,
217- )
208+ let wrapper = StructArray :: from_fields ( & [
209+ ( "zone_map" , self . array . clone ( ) . into_array ( ) ) ,
210+ ( "row_count" , row_count) ,
211+ ] ) ?
212+ . into_array ( ) ;
213+ let expr = merge ( [
214+ get_item ( "zone_map" , root ( ) ) ,
215+ pack (
216+ [ ( ZONE_ROW_COUNT_FIELD , get_item ( "row_count" , root ( ) ) ) ] ,
217+ Nullability :: NonNullable ,
218+ ) ,
219+ ] ) ;
220+ wrapper. apply ( & expr)
218221 }
219222
220223 fn row_count_array (
@@ -228,18 +231,27 @@ impl ZoneMap {
228231 return Ok ( ConstantArray :: new ( 0u64 , 0 ) . into_array ( ) ) ;
229232 }
230233
231- let last_zone_len =
232- row_count. saturating_sub ( zone_len. saturating_mul ( ( num_zones - 1 ) as u64 ) ) ;
234+ let last_zone_len = row_count - ( zone_len. saturating_mul ( ( num_zones - 1 ) as u64 ) ) ;
233235
234236 if num_zones == 1 || last_zone_len == zone_len {
235- let ends = PrimitiveArray :: from_iter ( [ num_zones as u64 ] ) . into_array ( ) ;
236- let values = PrimitiveArray :: from_iter ( [ last_zone_len] ) . into_array ( ) ;
237- return Ok ( RunEnd :: try_new ( ends, values, ctx) ?. into_array ( ) ) ;
237+ return Ok ( ConstantArray :: new ( last_zone_len, num_zones) . into_array ( ) ) ;
238+ }
239+
240+ let ends = unsafe {
241+ PrimitiveArray :: new_unchecked (
242+ buffer ! [ num_zones as u64 - 1 , num_zones as u64 ] ,
243+ Validity :: NonNullable ,
244+ )
245+ }
246+ . into_array ( ) ;
247+ let values = unsafe {
248+ PrimitiveArray :: new_unchecked ( buffer ! [ zone_len, last_zone_len] , Validity :: NonNullable )
238249 }
250+ . into_array ( ) ;
239251
240- let ends = PrimitiveArray :: from_iter ( [ num_zones as u64 - 1 , num_zones as u64 ] ) . into_array ( ) ;
241- let values = PrimitiveArray :: from_iter ( [ zone_len , last_zone_len ] ) . into_array ( ) ;
242- Ok ( RunEnd :: try_new ( ends, values, ctx) ? . into_array ( ) )
252+ // SAFETY: ` ends` are strictly increasing, terminate at `num_zones`, and align one-to-one
253+ // with the non-null run values.
254+ Ok ( unsafe { RunEnd :: new_unchecked ( ends, values, 0 , num_zones , ctx) } . into_array ( ) )
243255 }
244256}
245257
0 commit comments