11// SPDX-License-Identifier: Apache-2.0
22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
4- use vortex_buffer:: BitBuffer ;
54use vortex_error:: VortexResult ;
65use vortex_error:: vortex_bail;
76use vortex_error:: vortex_err;
8- use vortex_mask:: AllOr ;
97use vortex_session:: VortexSession ;
108use vortex_session:: registry:: CachedId ;
119
@@ -16,23 +14,16 @@ use crate::ExecutionCtx;
1614use crate :: IntoArray ;
1715use crate :: aggregate_fn:: AggregateFnVTable ;
1816use crate :: aggregate_fn:: DynGroupedAccumulator ;
19- use crate :: aggregate_fn:: GroupRanges ;
2017use crate :: aggregate_fn:: GroupedAccumulator ;
21- use crate :: aggregate_fn:: GroupedArray ;
2218use crate :: aggregate_fn:: NumericalAggregateOpts ;
2319use crate :: aggregate_fn:: fns:: sum:: Sum ;
24- use crate :: arrays:: BoolArray ;
2520use crate :: arrays:: ConstantArray ;
26- use crate :: arrays:: FixedSizeList ;
27- use crate :: arrays:: ListView ;
28- use crate :: builtins:: ArrayBuiltins ;
2921use crate :: dtype:: DType ;
3022use crate :: scalar_fn:: Arity ;
3123use crate :: scalar_fn:: ChildName ;
3224use crate :: scalar_fn:: ExecutionArgs ;
3325use crate :: scalar_fn:: ScalarFnId ;
3426use crate :: scalar_fn:: ScalarFnVTable ;
35- use crate :: validity:: Validity ;
3627
3728/// Sum of the elements in each list of a `List` or `FixedSizeList` typed array.
3829///
@@ -100,7 +91,6 @@ impl ScalarFnVTable for ListSum {
10091 other => vortex_bail ! ( "list_sum() requires List or FixedSizeList, got {other}" ) ,
10192 } ;
10293
103- // `mask_empty_lists` needs access to list elements validity and sizes
10494 let columnar = input. execute :: < Columnar > ( ctx) ?;
10595
10696 match columnar {
@@ -131,8 +121,8 @@ impl ScalarFnVTable for ListSum {
131121
132122/// Sum each list of a canonical `array` into one value per list.
133123///
134- /// Note that we need to nullify sums produced by empty or all-null lists,
135- /// since grouped sum kernels default to 0 for these .
124+ /// The grouped [`Sum`] finalize already yields null for null, empty, and all-null lists
125+ /// (SQL `SUM` semantics), so no post-processing is needed .
136126fn list_sum_impl (
137127 canonical : ArrayRef ,
138128 elem_dtype : DType ,
@@ -141,50 +131,7 @@ fn list_sum_impl(
141131) -> VortexResult < ArrayRef > {
142132 let mut acc = GroupedAccumulator :: try_new ( Sum , * options, elem_dtype) ?;
143133 acc. accumulate_list ( & canonical, ctx) ?;
144- let sums = acc. finish ( ) ?;
145-
146- let grouped: GroupedArray = if let Some ( fsl) = canonical. as_opt :: < FixedSizeList > ( ) {
147- fsl. into_owned ( ) . into ( )
148- } else if let Some ( lv) = canonical. as_opt :: < ListView > ( ) {
149- lv. into_owned ( ) . into ( )
150- } else {
151- let dtype = canonical. dtype ( ) ;
152- vortex_bail ! ( "list_sum() requires List or FixedSizeList but got {dtype}" )
153- } ;
154-
155- mask_empty_lists ( grouped, sums, ctx)
156- }
157-
158- /// Applies a mask to `sums` that nullifies entries produced by lists without at least
159- /// one valid element. This is necessary because the grouped `Sum` aggregate only produces
160- /// nulls for null lists and sums that overflow.
161- fn mask_empty_lists (
162- grouped : GroupedArray ,
163- sums : ArrayRef ,
164- ctx : & mut ExecutionCtx ,
165- ) -> VortexResult < ArrayRef > {
166- let elements = grouped. elements ( ) ;
167- let elem_mask = elements. validity ( ) ?. execute_mask ( elements. len ( ) , ctx) ?;
168- let ranges = grouped. group_ranges ( ctx) ?;
169-
170- let has_valid_element: BitBuffer = match elem_mask. bit_buffer ( ) {
171- AllOr :: All => match & ranges {
172- // fixed-size lists of non-zero width cannot have empty lists.
173- GroupRanges :: FixedSizeList { size, .. } if * size > 0 => return Ok ( sums) ,
174- GroupRanges :: FixedSizeList { len, .. } => BitBuffer :: full ( false , * len) ,
175- GroupRanges :: ListView { ranges } => ranges. iter ( ) . map ( |& ( _, size) | size > 0 ) . collect ( ) ,
176- } ,
177- AllOr :: None => BitBuffer :: full ( false , ranges. len ( ) ) ,
178- AllOr :: Some ( bits) => ranges
179- . iter ( )
180- . map ( |( offset, size) | size > 0 && bits. count_range ( offset, offset + size) > 0 )
181- . collect ( ) ,
182- } ;
183- if has_valid_element. true_count ( ) == has_valid_element. len ( ) {
184- return Ok ( sums) ;
185- }
186-
187- sums. mask ( BoolArray :: new ( has_valid_element, Validity :: NonNullable ) . into_array ( ) )
134+ acc. finish ( ctx)
188135}
189136
190137#[ cfg( test) ]
0 commit comments