Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9bd157f

Browse files
committed
Clarify dense grouped aggregate ids
Signed-off-by: "Nicholas Gates" <[email protected]>
1 parent 6bdcd32 commit 9bd157f

4 files changed

Lines changed: 33 additions & 12 deletions

File tree

vortex-array/src/aggregate_fn/accumulator_grouped.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ pub type GroupedAccumulatorRef = Box<dyn DynGroupedAccumulator>;
2828

2929
/// An accumulator used for computing aggregates over dense group ids.
3030
///
31-
/// Group ids are dense `u32` slots in the range `0..num_groups`. The accumulator keeps one partial
32-
/// state per slot, so ordered and unordered grouping only differ in how the caller assigns ids.
31+
/// Group ids are caller-assigned `u32` ordinals in the dense range `0..num_groups`. Input batches
32+
/// may repeat, omit, and reorder those ids, but every id must identify a state slot rather than a
33+
/// raw group key. The accumulator keeps one partial state per slot, so ordered and unordered
34+
/// grouping only differ in how the caller assigns ids.
3335
pub struct GroupedAccumulator<V: AggregateFnVTable> {
3436
/// The vtable of the aggregate function.
3537
vtable: V,
@@ -167,6 +169,9 @@ impl<V: AggregateFnVTable> GroupedAccumulator<V> {
167169
/// aggregate function is not known at compile time.
168170
pub trait DynGroupedAccumulator: 'static + Send {
169171
/// Accumulate a values batch into dense group state.
172+
///
173+
/// `group_ids` is parallel to `batch`. Each id must be a caller-assigned group ordinal in
174+
/// `0..num_groups`; ids may repeat, appear out of order, or be absent from a given batch.
170175
fn accumulate(
171176
&mut self,
172177
batch: &ArrayRef,
@@ -176,6 +181,9 @@ pub trait DynGroupedAccumulator: 'static + Send {
176181
) -> VortexResult<()>;
177182

178183
/// Fold columnar partial states into dense group state.
184+
///
185+
/// `group_ids` is parallel to `partials` and follows the same dense ordinal contract as
186+
/// [`Self::accumulate`].
179187
fn accumulate_partials(
180188
&mut self,
181189
partials: &ArrayRef,

vortex-array/src/aggregate_fn/fns/count/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,16 @@ mod tests {
263263
Ok(())
264264
}
265265

266+
#[test]
267+
fn grouped_count_rejects_out_of_range_group_id() -> VortexResult<()> {
268+
let values = PrimitiveArray::new(buffer![1i32, 2], Validity::NonNullable).into_array();
269+
let mut acc = GroupedAccumulator::try_new(Count, EmptyOptions, values.dtype().clone())?;
270+
let mut ctx = LEGACY_SESSION.create_execution_ctx();
271+
272+
assert!(acc.accumulate(&values, &[0, 2], 2, &mut ctx).is_err());
273+
Ok(())
274+
}
275+
266276
#[test]
267277
fn grouped_count_accumulate_partials_and_merge_group() -> VortexResult<()> {
268278
let dtype = DType::Primitive(PType::I32, Nullability::Nullable);

vortex-array/src/aggregate_fn/kernels.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ pub trait DynAggregateKernel: 'static + Send + Sync + Debug {
3030
/// Partial grouped aggregate output produced by an encoding-specific grouped kernel.
3131
///
3232
/// `group_ids` is parallel to `partials`: each row in `partials` is a partial state for the
33-
/// corresponding dense group id. The grouped accumulator merges this batch through
34-
/// `accumulate_partials`.
33+
/// corresponding dense group ordinal. The ids may repeat, omit, and reorder groups, but must be
34+
/// valid slots in the accumulator's `0..num_groups` range. The grouped accumulator merges this
35+
/// batch through `accumulate_partials`.
3536
#[derive(Clone, Debug)]
3637
pub struct GroupedAggregateKernelResult {
3738
group_ids: Buffer<u32>,
@@ -57,13 +58,13 @@ impl GroupedAggregateKernelResult {
5758

5859
/// A pluggable kernel for batch aggregation of many groups.
5960
///
60-
/// The kernel is matched on the encoding of the values array. It receives the same dense group ids
61-
/// that the caller passed to the grouped accumulator and may aggregate directly in the encoded
62-
/// domain.
61+
/// The kernel is matched on the encoding of the values array. It receives the same dense group
62+
/// ordinals that the caller passed to the grouped accumulator and may aggregate directly in the
63+
/// encoded domain.
6364
///
6465
/// Return `Ok(None)` if the kernel cannot be applied to the given aggregate function.
6566
pub trait DynGroupedAggregateKernel: 'static + Send + Sync + Debug {
66-
/// Aggregate values into a partial-state batch keyed by dense group id.
67+
/// Aggregate values into a partial-state batch keyed by dense group ordinal.
6768
fn grouped_aggregate(
6869
&self,
6970
aggregate_fn: &AggregateFnRef,

vortex-array/src/aggregate_fn/vtable.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,9 @@ pub trait AggregateFnVTable: 'static + Sized + Clone + Send + Sync {
148148

149149
/// Try to accumulate a raw values batch into dense per-group states before decompression.
150150
///
151-
/// `group_ids` is parallel to `batch` and contains dense ids in `0..states.len()`. Returns
152-
/// `true` when the batch was fully handled.
151+
/// `group_ids` is parallel to `batch` and contains caller-assigned dense ordinals in
152+
/// `0..states.len()`. Ids may repeat, appear out of order, or be absent from the batch.
153+
/// Returns `true` when the batch was fully handled.
153154
fn try_accumulate_grouped(
154155
&self,
155156
_states: &mut [Self::Partial],
@@ -162,8 +163,9 @@ pub trait AggregateFnVTable: 'static + Sized + Clone + Send + Sync {
162163

163164
/// Accumulate a canonical values batch into dense per-group states.
164165
///
165-
/// `group_ids` is parallel to `batch` and contains dense ids in `0..states.len()`. Returns
166-
/// `true` when the batch was fully handled. The provided default preserves universal
166+
/// `group_ids` is parallel to `batch` and contains caller-assigned dense ordinals in
167+
/// `0..states.len()`. Ids may repeat, appear out of order, or be absent from the batch.
168+
/// Returns `true` when the batch was fully handled. The provided default preserves universal
167169
/// correctness through [`GroupedAccumulator`]'s fallback.
168170
fn accumulate_grouped(
169171
&self,

0 commit comments

Comments
 (0)