Consume the accumulator and produce the final `Value`.
(self, agg: &AggregateSpec)
| 9 | impl AggAccum { |
| 10 | /// Consume the accumulator and produce the final `Value`. |
| 11 | pub(crate) fn finalize(self, agg: &AggregateSpec) -> Value { |
| 12 | match self { |
| 13 | AggAccum::Count { n } => Value::Integer(n as i64), |
| 14 | AggAccum::SumAvg { sum, n, .. } => { |
| 15 | if agg.function == "avg" { |
| 16 | if n == 0 { |
| 17 | Value::Null |
| 18 | } else { |
| 19 | Value::Float(sum / n as f64) |
| 20 | } |
| 21 | } else { |
| 22 | Value::Float(sum) |
| 23 | } |
| 24 | } |
| 25 | AggAccum::SumAvgDistinct { seen } => { |
| 26 | let n = seen.len(); |
| 27 | // Kahan-compensated sum over the deduped values. Iteration |
| 28 | // order is arbitrary, but a DISTINCT sum is order-independent |
| 29 | // so the result is deterministic regardless. |
| 30 | let mut sum = 0.0f64; |
| 31 | let mut comp = 0.0f64; |
| 32 | for &v in seen.values() { |
| 33 | let y = v - comp; |
| 34 | let t = sum + y; |
| 35 | comp = (t - sum) - y; |
| 36 | sum = t; |
| 37 | } |
| 38 | if agg.function == "avg_distinct" { |
| 39 | if n == 0 { |
| 40 | Value::Null |
| 41 | } else { |
| 42 | Value::Float(sum / n as f64) |
| 43 | } |
| 44 | } else { |
| 45 | Value::Float(sum) |
| 46 | } |
| 47 | } |
| 48 | AggAccum::Min { best } => best.unwrap_or(Value::Null), |
| 49 | AggAccum::Max { best } => best.unwrap_or(Value::Null), |
| 50 | AggAccum::CountDistinct { seen } => Value::Integer(seen.len() as i64), |
| 51 | AggAccum::Welford { n, mean: _, m2 } => { |
| 52 | if n < 2 { |
| 53 | return Value::Null; |
| 54 | } |
| 55 | let population = matches!( |
| 56 | agg.function.as_str(), |
| 57 | "stddev" | "stddev_pop" | "variance" | "var_pop" |
| 58 | ); |
| 59 | let divisor = if population { n as f64 } else { (n - 1) as f64 }; |
| 60 | let variance = m2 / divisor; |
| 61 | let result = if agg.function.contains("stddev") { |
| 62 | variance.sqrt() |
| 63 | } else { |
| 64 | variance |
| 65 | }; |
| 66 | Value::Float(result) |
| 67 | } |
| 68 | AggAccum::Hll { hll } => Value::Integer(hll.estimate().round() as i64), |
nothing calls this directly
no test coverage detected