Evaluates the aggregate over an iterator of `(datum, diff)` pairs. Each aggregate consumes the multiplicity (`diff`) in whatever way is most efficient: `count` sums the diffs, multiplicity-insensitive aggregates (see `AggregateFunc::ignores_multiplicity`) ignore them, and everything else expands each datum into `diff` copies (see `expand_counts`).
(&self, datums: I, temp_storage: &'a RowArena)
| 2078 | /// (see `AggregateFunc::ignores_multiplicity`) ignore them, and everything |
| 2079 | /// else expands each datum into `diff` copies (see `expand_counts`). |
| 2080 | pub fn eval<'a, I>(&self, datums: I, temp_storage: &'a RowArena) -> Datum<'a> |
| 2081 | where |
| 2082 | I: IntoIterator<Item = (Datum<'a>, Diff)>, |
| 2083 | { |
| 2084 | // Accumulable aggregates consume multiplicity directly rather than |
| 2085 | // expanding each `(datum, diff)` into `diff` copies. The cases handled |
| 2086 | // here mirror the dataflow's accumulable reduction (`build_accumulable` |
| 2087 | // in `mz_compute::render::reduce`) so that constant folding produces the |
| 2088 | // same result the dataflow would. Signed integer sums are folded here; |
| 2089 | // unsigned sums are not, because their negative-accumulation case is a |
| 2090 | // query error in the dataflow that this `Datum`-returning path cannot |
| 2091 | // signal. Floats and numerics use bespoke fixed-point/wide-decimal |
| 2092 | // accumulators in the dataflow that `expand_counts` does not reproduce. |
| 2093 | match self { |
| 2094 | AggregateFunc::Count => count(datums), |
| 2095 | AggregateFunc::SumInt16 | AggregateFunc::SumInt32 => { |
| 2096 | // `finalize_accum` narrows these to `i64` with wrapping. |
| 2097 | sum_signed_int_counted(datums, |accum| { |
| 2098 | #[allow(clippy::as_conversions)] |
| 2099 | let narrowed = accum as i64; |
| 2100 | Datum::Int64(narrowed) |
| 2101 | }) |
| 2102 | } |
| 2103 | AggregateFunc::SumInt64 => sum_signed_int_counted(datums, Datum::from), |
| 2104 | _ if self.ignores_multiplicity() => { |
| 2105 | self.eval_datums(datums.into_iter().map(|(datum, _diff)| datum), temp_storage) |
| 2106 | } |
| 2107 | _ => self.eval_datums(expand_counts(datums), temp_storage), |
| 2108 | } |
| 2109 | } |
| 2110 | |
| 2111 | /// Evaluates the aggregate over a flat iterator of datums, ignoring multiplicity. |
| 2112 | fn eval_datums<'a, I>(&self, datums: I, temp_storage: &'a RowArena) -> Datum<'a> |