1use std::{cmp::Ordering, fmt, mem, ops::Range, sync::Arc};
9
10#[cfg(feature = "decimal")]
11use rust_decimal::{Decimal, prelude::ToPrimitive as _};
12
13use super::{
14 Projection, ViewSpec,
15 display::{AggregateValues, GroupData},
16};
17use crate::{
18 model::{CellValue, ColumnSet, GridColumns, GridRow, OwnedValue},
19 store::{RowId, StoreSnapshot},
20};
21
22pub trait AggregateFn<R: GridRow>: Send + Sync + 'static {
26 fn aggregate(&self, column: R::Column, rows: &mut dyn Iterator<Item = &R>) -> OwnedValue;
29
30 fn combine(&self, _parts: &[&OwnedValue]) -> Option<OwnedValue> {
34 None
35 }
36
37 fn depends_on(&self, column: R::Column) -> ColumnSet {
40 let mut columns = ColumnSet::EMPTY;
41 columns.insert(column.ix());
42 columns
43 }
44
45 fn name(&self) -> &str {
48 ""
49 }
50}
51
52#[non_exhaustive]
56pub enum Aggregate<R: GridRow> {
57 Sum,
63 Avg,
67 Min,
69 Max,
71 Count,
74 Custom(Arc<dyn AggregateFn<R>>),
76}
77
78impl<R: GridRow> Clone for Aggregate<R> {
79 fn clone(&self) -> Self {
80 match self {
81 Self::Sum => Self::Sum,
82 Self::Avg => Self::Avg,
83 Self::Min => Self::Min,
84 Self::Max => Self::Max,
85 Self::Count => Self::Count,
86 Self::Custom(function) => Self::Custom(function.clone()),
87 }
88 }
89}
90
91impl<R: GridRow> fmt::Debug for Aggregate<R> {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 match self {
94 Self::Sum => f.write_str("Sum"),
95 Self::Avg => f.write_str("Avg"),
96 Self::Min => f.write_str("Min"),
97 Self::Max => f.write_str("Max"),
98 Self::Count => f.write_str("Count"),
99 Self::Custom(function) => f.debug_tuple("Custom").field(&function.name()).finish(),
100 }
101 }
102}
103
104impl<R: GridRow> Aggregate<R> {
105 pub(super) fn depends_on(&self, column: R::Column) -> ColumnSet {
107 match self {
108 Self::Custom(function) => function.depends_on(column),
109 Self::Sum | Self::Avg | Self::Min | Self::Max | Self::Count => {
110 let mut columns = ColumnSet::EMPTY;
111 columns.insert(column.ix());
112 columns
113 }
114 }
115 }
116}
117
118impl<R: GridRow> ViewSpec<R> {
119 pub fn with_aggregates(
124 mut self,
125 aggregates: impl IntoIterator<Item = (R::Column, Aggregate<R>)>,
126 ) -> Self {
127 let mut unique: Vec<(R::Column, Aggregate<R>)> = Vec::new();
128 for (column, aggregate) in aggregates {
129 match unique.iter_mut().find(|(kept, _)| *kept == column) {
130 Some(kept) => kept.1 = aggregate,
131 None => unique.push((column, aggregate)),
132 }
133 }
134 self.aggregates = (!unique.is_empty()).then(|| unique.into());
135 self
136 }
137
138 pub fn aggregates(&self) -> &[(R::Column, Aggregate<R>)] {
140 self.aggregates.as_deref().unwrap_or_default()
141 }
142
143 pub fn aggregate_columns(&self) -> ColumnSet {
146 let mut columns = ColumnSet::EMPTY;
147 for (column, aggregate) in self.aggregates() {
148 columns.union_with(aggregate.depends_on(*column));
149 }
150 columns
151 }
152}
153
154pub(super) struct ViewAggregates<'s, R: GridRow> {
157 columns: ColumnSet,
158 list: Vec<(R::Column, &'s Aggregate<R>)>,
159 built_in: Vec<usize>,
161 custom: Vec<(usize, &'s dyn AggregateFn<R>)>,
163}
164
165impl<'s, R: GridRow> ViewAggregates<'s, R> {
166 pub(super) fn new(spec: &'s ViewSpec<R>) -> Self {
167 let mut list: Vec<(R::Column, &Aggregate<R>)> = spec
168 .aggregates()
169 .iter()
170 .map(|(column, aggregate)| (*column, aggregate))
171 .collect();
172 list.sort_by_key(|(column, _)| column.ix());
173 let mut columns = ColumnSet::EMPTY;
174 let mut built_in = Vec::new();
175 let mut custom = Vec::new();
176 for (ix, (column, aggregate)) in list.iter().enumerate() {
177 columns.insert(column.ix());
178 match aggregate {
179 Aggregate::Custom(function) => custom.push((ix, &**function)),
180 Aggregate::Sum
181 | Aggregate::Avg
182 | Aggregate::Min
183 | Aggregate::Max
184 | Aggregate::Count => built_in.push(ix),
185 }
186 }
187 Self {
188 columns,
189 list,
190 built_in,
191 custom,
192 }
193 }
194
195 pub(super) fn columns(&self) -> ColumnSet {
197 self.columns
198 }
199
200 pub(super) fn is_empty(&self) -> bool {
202 self.list.is_empty()
203 }
204
205 fn start<'a>(&self) -> impl Iterator<Item = Partial<'a>> + '_ {
207 self.list
208 .iter()
209 .map(|(_, aggregate)| Partial::start(aggregate))
210 }
211
212 #[inline]
214 fn add<'a>(&self, partials: &mut [Partial<'a>], row: &'a R) {
215 for &ix in &self.built_in {
216 partials[ix].add(row.value(self.list[ix].0));
217 }
218 }
219
220 fn merge<'a>(&self, partials: &mut [Partial<'a>], part: &[Partial<'a>]) {
222 for &ix in &self.built_in {
223 partials[ix].merge(&part[ix]);
224 }
225 }
226
227 fn finish(&self, partials: &[Partial<'_>], values: &mut [OwnedValue]) {
229 for &ix in &self.built_in {
230 values[ix] = partials[ix].finish();
231 }
232 }
233}
234
235#[derive(Clone, Copy, Debug)]
239enum Partial<'a> {
240 Sum(Numbers),
241 Avg(Numbers),
242 Min(CellValue<'a>),
244 Max(CellValue<'a>),
246 Count(u64),
248 Custom,
250}
251
252#[derive(Clone, Copy, Debug, Default)]
256struct Numbers {
257 int: i128,
258 float: f64,
259 has_float: bool,
260 count: u64,
261 #[cfg(feature = "decimal")]
262 decimal: Decimals,
263}
264
265impl Numbers {
266 fn add(&mut self, value: CellValue<'_>) {
267 match value {
268 CellValue::Int(value) => {
269 self.int += i128::from(value);
270 self.count += 1;
271 }
272 CellValue::Float(value) => {
273 self.float += value;
274 self.has_float = true;
275 self.count += 1;
276 }
277 #[cfg(feature = "decimal")]
278 CellValue::Decimal(value) => {
279 self.decimal.add(value);
280 self.count += 1;
281 }
282 _ => {}
284 }
285 }
286
287 fn merge(&mut self, other: &Self) {
288 self.int += other.int;
289 self.float += other.float;
290 self.has_float |= other.has_float;
291 self.count += other.count;
292 #[cfg(feature = "decimal")]
293 self.decimal.merge(&other.decimal);
294 }
295
296 fn sum(&self) -> OwnedValue {
300 if self.count == 0 {
301 return OwnedValue::Empty;
302 }
303 #[cfg(feature = "decimal")]
304 if self.decimal.has_values && !self.has_float {
305 return self
306 .decimal
307 .exact_sum(self.int)
308 .map_or_else(OwnedValue::Float, OwnedValue::Decimal);
309 }
310 if self.has_float {
311 OwnedValue::Float(self.float_sum())
312 } else {
313 i64::try_from(self.int).map_or(OwnedValue::Float(self.int as f64), OwnedValue::Int)
314 }
315 }
316
317 fn mean(&self) -> OwnedValue {
320 if self.count == 0 {
321 return OwnedValue::Empty;
322 }
323 #[cfg(feature = "decimal")]
324 if self.decimal.has_values && !self.has_float {
325 return self
326 .decimal
327 .mean(self.int, self.count)
328 .map_or_else(OwnedValue::Float, OwnedValue::Decimal);
329 }
330 OwnedValue::Float(self.float_sum() / self.count as f64)
331 }
332
333 fn float_sum(&self) -> f64 {
335 let sum = self.float + self.int as f64;
336 #[cfg(feature = "decimal")]
337 if self.decimal.has_values {
338 return sum + self.decimal.sum.to_f64();
339 }
340 sum
341 }
342}
343
344#[cfg(feature = "decimal")]
346#[derive(Clone, Copy, Debug, Default)]
347struct Decimals {
348 sum: DecimalSum,
349 scale: u32,
351 has_values: bool,
352}
353
354#[cfg(feature = "decimal")]
357#[derive(Clone, Copy, Debug)]
358enum DecimalSum {
359 Exact(Decimal),
360 Overflow(f64),
361}
362
363#[cfg(feature = "decimal")]
364impl Default for DecimalSum {
365 fn default() -> Self {
366 Self::Exact(Decimal::ZERO)
367 }
368}
369
370#[cfg(feature = "decimal")]
371impl DecimalSum {
372 fn plus(self, other: Self) -> Self {
373 match (self, other) {
374 (Self::Exact(a), Self::Exact(b)) => a
375 .checked_add(b)
376 .map_or_else(|| Self::Overflow(as_f64(a) + as_f64(b)), Self::Exact),
377 (a, b) => Self::Overflow(a.to_f64() + b.to_f64()),
378 }
379 }
380
381 fn to_f64(self) -> f64 {
382 match self {
383 Self::Exact(sum) => as_f64(sum),
384 Self::Overflow(sum) => sum,
385 }
386 }
387}
388
389#[cfg(feature = "decimal")]
390fn as_f64(value: Decimal) -> f64 {
391 value.to_f64().unwrap_or_default()
392}
393
394#[cfg(feature = "decimal")]
395impl Decimals {
396 fn add(&mut self, value: Decimal) {
397 self.sum = self.sum.plus(DecimalSum::Exact(value));
398 self.scale = self.scale.max(value.scale());
399 self.has_values = true;
400 }
401
402 fn merge(&mut self, other: &Self) {
403 if other.has_values {
404 self.sum = self.sum.plus(other.sum);
405 self.scale = self.scale.max(other.scale);
406 self.has_values = true;
407 }
408 }
409
410 fn exact_sum(&self, int: i128) -> Result<Decimal, f64> {
413 let int = Decimal::try_from_i128_with_scale(int, 0)
414 .map_or_else(|_| DecimalSum::Overflow(int as f64), DecimalSum::Exact);
415 match self.sum.plus(int) {
416 DecimalSum::Exact(sum) => Ok(sum),
417 DecimalSum::Overflow(sum) => Err(sum),
418 }
419 }
420
421 fn mean(&self, int: i128, count: u64) -> Result<Decimal, f64> {
425 let sum = self.exact_sum(int).map_err(|sum| sum / count as f64)?;
426 sum.checked_div(Decimal::from(count))
427 .map(|mean| mean.round_dp(self.scale + 2))
428 .ok_or_else(|| as_f64(sum) / count as f64)
429 }
430}
431
432impl<'a> Partial<'a> {
433 fn start<R: GridRow>(aggregate: &Aggregate<R>) -> Self {
434 match aggregate {
435 Aggregate::Sum => Self::Sum(Numbers::default()),
436 Aggregate::Avg => Self::Avg(Numbers::default()),
437 Aggregate::Min => Self::Min(CellValue::Empty),
438 Aggregate::Max => Self::Max(CellValue::Empty),
439 Aggregate::Count => Self::Count(0),
440 Aggregate::Custom(_) => Self::Custom,
441 }
442 }
443
444 #[inline]
445 fn add(&mut self, value: CellValue<'a>) {
446 match self {
447 Self::Sum(numbers) | Self::Avg(numbers) => numbers.add(value),
448 Self::Min(min) => keep_extreme(min, value, Ordering::Less),
449 Self::Max(max) => keep_extreme(max, value, Ordering::Greater),
450 Self::Count(count) => *count += u64::from(!matches!(value, CellValue::Empty)),
451 Self::Custom => {}
452 }
453 }
454
455 fn merge(&mut self, other: &Self) {
456 match (self, other) {
457 (Self::Sum(numbers), Self::Sum(other)) | (Self::Avg(numbers), Self::Avg(other)) => {
458 numbers.merge(other)
459 }
460 (Self::Min(min), Self::Min(other)) => keep_extreme(min, *other, Ordering::Less),
461 (Self::Max(max), Self::Max(other)) => keep_extreme(max, *other, Ordering::Greater),
462 (Self::Count(count), Self::Count(other)) => *count += other,
463 _ => {}
464 }
465 }
466
467 fn finish(&self) -> OwnedValue {
468 match self {
469 Self::Sum(numbers) => numbers.sum(),
470 Self::Avg(numbers) => numbers.mean(),
471 Self::Min(value) | Self::Max(value) => OwnedValue::from_cell(*value),
472 Self::Count(count) => OwnedValue::Int(i64::try_from(*count).unwrap_or(i64::MAX)),
473 Self::Custom => OwnedValue::Empty,
474 }
475 }
476}
477
478#[inline]
481fn keep_extreme<'a>(extreme: &mut CellValue<'a>, value: CellValue<'a>, side: Ordering) {
482 if !matches!(value, CellValue::Empty)
483 && (matches!(extreme, CellValue::Empty) || value.cmp_total(extreme) == side)
484 {
485 *extreme = value;
486 }
487}
488
489#[derive(Clone, Debug)]
492pub(super) struct KeyedGroup {
493 pub(super) depth: u16,
494 pub(super) end: u32,
496 pub(super) rows: Range<u32>,
498}
499
500pub(super) struct GroupValues {
502 pub(super) values: Vec<OwnedValue>,
504 pub(super) live: Vec<u32>,
506 pub(super) totals: Vec<OwnedValue>,
508 pub(super) total_live: usize,
510}
511
512pub(super) fn aggregate_groups<'r, 'a, R: GridRow, T>(
522 aggregates: &ViewAggregates<'_, R>,
523 groups: &[KeyedGroup],
524 levels: u16,
525 rows: &'r [T],
526 row: impl Fn(&'r T) -> Option<&'a R> + Copy,
527) -> GroupValues {
528 let width = aggregates.list.len();
529 let is_leaf = |group: &KeyedGroup| usize::from(group.depth) + 1 == usize::from(levels);
530 let rows_of = |span: Range<usize>| {
532 groups[span]
533 .iter()
534 .filter(move |group| is_leaf(group))
535 .flat_map(move |group| {
536 rows[group.rows.start as usize..group.rows.end as usize]
537 .iter()
538 .filter_map(row)
539 })
540 };
541 let mut partials: Vec<Partial<'a>> = Vec::with_capacity(groups.len() * width);
542 for _ in groups {
543 partials.extend(aggregates.start());
544 }
545 let mut values = vec![OwnedValue::Empty; groups.len() * width];
546 let mut live = vec![0u32; groups.len()];
547
548 for (ix, group) in groups.iter().enumerate().rev() {
549 let run = ix * width..(ix + 1) * width;
550 if is_leaf(group) {
551 let partial = &mut partials[run.clone()];
552 for row in rows_of(ix..ix + 1) {
553 live[ix] += 1;
554 aggregates.add(partial, row);
555 }
556 for &(place, function) in &aggregates.custom {
557 let column = aggregates.list[place].0;
558 values[ix * width + place] = function.aggregate(column, &mut rows_of(ix..ix + 1));
559 }
560 } else {
561 let span = ix + 1..group.end as usize;
562 let (head, tail) = partials.split_at_mut((ix + 1) * width);
564 let mut child = span.start;
565 while child < span.end {
566 live[ix] += live[child];
567 let part = (child - span.start) * width;
568 aggregates.merge(&mut head[run.clone()], &tail[part..part + width]);
569 child = groups[child].end as usize;
570 }
571 for &(place, function) in &aggregates.custom {
572 let column = aggregates.list[place].0;
573 let (head, tail) = values.split_at_mut((ix + 1) * width);
574 let parts = children(groups, span.clone())
575 .map(|child| &tail[(child - span.start) * width + place])
576 .collect::<Vec<_>>();
577 head[ix * width + place] = function
578 .combine(&parts)
579 .unwrap_or_else(|| function.aggregate(column, &mut rows_of(span.clone())));
580 }
581 }
582 aggregates.finish(&partials[run.clone()], &mut values[run]);
583 }
584
585 let mut total: Vec<Partial<'a>> = aggregates.start().collect();
587 let mut total_live = 0;
588 for top in children(groups, 0..groups.len()) {
589 total_live += live[top] as usize;
590 aggregates.merge(&mut total, &partials[top * width..(top + 1) * width]);
591 }
592 let mut totals = vec![OwnedValue::Empty; width];
593 aggregates.finish(&total, &mut totals);
594 for &(place, function) in &aggregates.custom {
595 let column = aggregates.list[place].0;
596 let parts = children(groups, 0..groups.len())
597 .map(|top| &values[top * width + place])
598 .collect::<Vec<_>>();
599 totals[place] = (!parts.is_empty())
601 .then(|| function.combine(&parts))
602 .flatten()
603 .unwrap_or_else(|| function.aggregate(column, &mut rows_of(0..groups.len())));
604 }
605 GroupValues {
606 values,
607 live,
608 totals,
609 total_live,
610 }
611}
612
613fn children(groups: &[KeyedGroup], span: Range<usize>) -> impl Iterator<Item = usize> + '_ {
616 let mut next = span.start;
617 std::iter::from_fn(move || {
618 let child = next;
619 (child < span.end).then(|| {
620 next = groups[child].end as usize;
621 child
622 })
623 })
624}
625
626pub(super) fn flat_totals<'a, R: GridRow>(
630 aggregates: &ViewAggregates<'_, R>,
631 rows: impl Iterator<Item = &'a R> + Clone,
632) -> (Vec<OwnedValue>, usize) {
633 let mut partials: Vec<Partial<'a>> = aggregates.start().collect();
634 let mut count = 0;
635 for row in rows.clone() {
636 count += 1;
637 aggregates.add(&mut partials, row);
638 }
639 let mut totals = vec![OwnedValue::Empty; aggregates.list.len()];
640 aggregates.finish(&partials, &mut totals);
641 for &(place, function) in &aggregates.custom {
642 let column = aggregates.list[place].0;
643 totals[place] = function.aggregate(column, &mut rows.clone());
644 }
645 (totals, count)
646}
647
648pub(super) fn refresh<R: GridRow>(
654 previous: &Projection,
655 snapshot: &StoreSnapshot<R>,
656 spec: &ViewSpec<R>,
657) -> Projection {
658 let aggregates = ViewAggregates::new(spec);
659 let row = |id: &RowId| snapshot.row(*id).map(|row| &**row);
660 let Some(data) = previous.group_data() else {
661 let (totals, live) = flat_totals(&aggregates, previous.rows().iter().filter_map(row));
662 return previous
663 .duplicate()
664 .with_store_version(snapshot.version())
665 .with_row_count(live)
666 .with_totals(AggregateValues::new(aggregates.columns(), totals));
667 };
668
669 let mut key_order: Vec<usize> = (0..data.groups.len()).collect();
671 key_order.sort_unstable_by_key(|&ix| data.groups[ix].key_ix);
672 let mut keyed: Vec<KeyedGroup> = key_order
673 .iter()
674 .map(|&ix| {
675 let group = &data.groups[ix];
676 KeyedGroup {
677 depth: group.depth(),
678 end: 0,
679 rows: group.rows.clone(),
680 }
681 })
682 .collect();
683 let mut open: Vec<usize> = Vec::new();
686 for ix in 0..keyed.len() {
687 while let Some(&top) = open.last()
688 && keyed[top].depth >= keyed[ix].depth
689 {
690 keyed[top].end = ix as u32;
691 open.pop();
692 }
693 open.push(ix);
694 }
695 for top in open {
696 keyed[top].end = keyed.len() as u32;
697 }
698
699 let mut computed = aggregate_groups(&aggregates, &keyed, data.levels, previous.rows(), row);
700 let width = aggregates.columns().len();
701 let mut groups = data.groups.clone();
702 let mut values = vec![OwnedValue::Empty; groups.len() * width];
703 for (key_ix, &ix) in key_order.iter().enumerate() {
704 groups[ix].live = computed.live[key_ix];
705 for (value, computed) in values[ix * width..(ix + 1) * width]
706 .iter_mut()
707 .zip(&mut computed.values[key_ix * width..(key_ix + 1) * width])
708 {
709 *value = mem::replace(computed, OwnedValue::Empty);
710 }
711 }
712 let columns = aggregates.columns();
713 previous.with_group_values(
714 GroupData::new(data.levels, groups, AggregateValues::new(columns, values)),
715 AggregateValues::new(columns, computed.totals),
716 computed.total_live,
717 snapshot.version(),
718 )
719}