@@ -12,6 +12,7 @@ use vortex_array::ExecutionCtx;
1212use vortex_array:: IntoArray ;
1313use vortex_array:: LEGACY_SESSION ;
1414use vortex_array:: VortexSessionExecute ;
15+ use vortex_array:: aggregate_fn:: AggregateFnRef ;
1516use vortex_array:: aggregate_fn:: fns:: sum:: sum;
1617use vortex_array:: arrays:: ConstantArray ;
1718use vortex_array:: arrays:: StructArray ;
@@ -25,7 +26,6 @@ use vortex_array::dtype::Nullability;
2526use vortex_array:: dtype:: PType ;
2627use vortex_array:: expr:: stats:: Precision ;
2728use vortex_array:: expr:: stats:: Stat ;
28- use vortex_array:: expr:: stats:: StatsProvider ;
2929use vortex_array:: scalar:: Scalar ;
3030use vortex_array:: scalar:: ScalarTruncation ;
3131use vortex_array:: scalar:: lower_bound;
@@ -35,9 +35,12 @@ use vortex_array::validity::Validity;
3535use vortex_buffer:: BufferString ;
3636use vortex_buffer:: ByteBuffer ;
3737use vortex_error:: VortexResult ;
38+ use vortex_error:: vortex_ensure_eq;
3839
3940use crate :: layouts:: zoned:: schema:: MAX_IS_TRUNCATED ;
4041use crate :: layouts:: zoned:: schema:: MIN_IS_TRUNCATED ;
42+ use crate :: layouts:: zoned:: schema:: aggregate_descriptor;
43+ use crate :: layouts:: zoned:: schema:: aggregate_state_dtype;
4144
4245/// Accumulates write-time statistics for each logical zone.
4346pub struct StatsAccumulator {
@@ -74,18 +77,6 @@ impl StatsAccumulator {
7477 }
7578 }
7679
77- pub fn push_chunk_without_compute ( & mut self , array : & ArrayRef ) -> VortexResult < ( ) > {
78- for builder in & mut self . builders {
79- if let Precision :: Exact ( value) = array. statistics ( ) . get ( builder. stat ( ) ) {
80- builder. append_scalar ( value. cast ( & value. dtype ( ) . as_nullable ( ) ) ?) ?;
81- } else {
82- builder. append_null ( ) ;
83- }
84- }
85- self . length += 1 ;
86- Ok ( ( ) )
87- }
88-
8980 pub fn push_chunk ( & mut self , array : & ArrayRef , ctx : & mut ExecutionCtx ) -> VortexResult < ( ) > {
9081 for builder in & mut self . builders {
9182 if let Some ( value) = array. statistics ( ) . compute_stat ( builder. stat ( ) , ctx) ? {
@@ -176,6 +167,102 @@ fn supports_file_stats(dtype: &DType) -> bool {
176167 !matches ! ( dtype, DType :: Variant ( _) )
177168}
178169
170+ /// Accumulates aggregate-function partials for each logical zone.
171+ pub ( crate ) struct AggregateStatsAccumulator {
172+ builders : Vec < AggregateStatsArrayBuilder > ,
173+ length : usize ,
174+ }
175+
176+ impl AggregateStatsAccumulator {
177+ pub ( crate ) fn new ( dtype : & DType , aggregate_fns : & [ AggregateFnRef ] ) -> Self {
178+ let builders = aggregate_fns
179+ . iter ( )
180+ . filter_map ( |aggregate_fn| {
181+ aggregate_state_dtype ( dtype, aggregate_fn) . map ( |partial_dtype| {
182+ AggregateStatsArrayBuilder :: new (
183+ aggregate_fn. clone ( ) ,
184+ & partial_dtype. as_nullable ( ) ,
185+ 1024 ,
186+ )
187+ } )
188+ } )
189+ . collect :: < Vec < _ > > ( ) ;
190+
191+ Self {
192+ builders,
193+ length : 0 ,
194+ }
195+ }
196+
197+ pub ( crate ) fn aggregate_fns ( & self ) -> Arc < [ AggregateFnRef ] > {
198+ self . builders
199+ . iter ( )
200+ . map ( |builder| builder. aggregate_fn . clone ( ) )
201+ . collect :: < Vec < _ > > ( )
202+ . into ( )
203+ }
204+
205+ pub ( crate ) fn push_partials ( & mut self , partials : Vec < Scalar > ) -> VortexResult < ( ) > {
206+ vortex_ensure_eq ! (
207+ partials. len( ) ,
208+ self . builders. len( ) ,
209+ "aggregate partial count must match zone stats builder count"
210+ ) ;
211+
212+ for ( builder, value) in self . builders . iter_mut ( ) . zip_eq ( partials) {
213+ builder. append_scalar ( value) ?;
214+ }
215+ self . length += 1 ;
216+ Ok ( ( ) )
217+ }
218+
219+ pub ( crate ) fn as_array (
220+ & mut self ,
221+ ) -> VortexResult < Option < ( StructArray , Arc < [ AggregateFnRef ] > ) > > {
222+ let mut names = Vec :: new ( ) ;
223+ let mut fields = Vec :: new ( ) ;
224+ let mut aggregate_fns = Vec :: new ( ) ;
225+
226+ for builder in self
227+ . builders
228+ . iter_mut ( )
229+ . sorted_unstable_by ( |lhs, rhs| lhs. descriptor . cmp ( & rhs. descriptor ) )
230+ {
231+ let values = builder. finish ( ) ;
232+
233+ if values. all_invalid ( ) ? {
234+ continue ;
235+ }
236+
237+ aggregate_fns. push ( builder. aggregate_fn . clone ( ) ) ;
238+ names. extend ( values. names ) ;
239+ fields. extend ( values. arrays ) ;
240+ }
241+
242+ if names. is_empty ( ) {
243+ return Ok ( None ) ;
244+ }
245+
246+ let array = StructArray :: try_new ( names. into ( ) , fields, self . length , Validity :: NonNullable ) ?;
247+ Ok ( Some ( ( array, aggregate_fns. into ( ) ) ) )
248+ }
249+ }
250+
251+ pub ( crate ) fn aggregate_partials (
252+ array : & ArrayRef ,
253+ aggregate_fns : & [ AggregateFnRef ] ,
254+ ctx : & mut ExecutionCtx ,
255+ ) -> VortexResult < Vec < Scalar > > {
256+ aggregate_fns
257+ . iter ( )
258+ . map ( |aggregate_fn| {
259+ let mut accumulator = aggregate_fn. accumulator ( array. dtype ( ) ) ?;
260+ accumulator. accumulate ( array, ctx) ?;
261+ accumulator. partial_scalar ( )
262+ } )
263+ . collect ( )
264+ }
265+
179266fn stats_builder_with_capacity (
180267 stat : Stat ,
181268 dtype : & DType ,
@@ -214,6 +301,35 @@ fn stats_builder_with_capacity(
214301 }
215302}
216303
304+ struct AggregateStatsArrayBuilder {
305+ aggregate_fn : AggregateFnRef ,
306+ descriptor : String ,
307+ dtype : DType ,
308+ builder : Box < dyn ArrayBuilder > ,
309+ }
310+
311+ impl AggregateStatsArrayBuilder {
312+ fn new ( aggregate_fn : AggregateFnRef , dtype : & DType , capacity : usize ) -> Self {
313+ Self {
314+ descriptor : aggregate_descriptor ( & aggregate_fn) ,
315+ aggregate_fn,
316+ dtype : dtype. clone ( ) ,
317+ builder : builder_with_capacity ( dtype, capacity) ,
318+ }
319+ }
320+
321+ fn append_scalar ( & mut self , value : Scalar ) -> VortexResult < ( ) > {
322+ self . builder . append_scalar ( & value. cast ( & self . dtype ) ?)
323+ }
324+
325+ fn finish ( & mut self ) -> NamedArrays {
326+ NamedArrays {
327+ names : vec ! [ self . descriptor. clone( ) . into( ) ] ,
328+ arrays : vec ! [ self . builder. finish( ) ] ,
329+ }
330+ }
331+ }
332+
217333/// Arrays with their associated names, reduced version of a `StructArray`.
218334struct NamedArrays {
219335 names : Vec < FieldName > ,
0 commit comments