datafusion_functions_aggregate_common/aggregate/avg_distinct/
decimal.rs1use arrow::{
19 array::{ArrayRef, ArrowNativeTypeOp, ArrowNumericType},
20 compute::DecimalCast,
21 datatypes::{ArrowNativeType, DecimalType},
22};
23use datafusion_common::{Result, ScalarValue, exec_datafusion_err, exec_err};
24use datafusion_expr_common::accumulator::Accumulator;
25use std::fmt::Debug;
26use std::marker::PhantomData;
27use std::mem::size_of_val;
28
29use crate::aggregate::sum_distinct::DistinctSumAccumulator;
30use crate::utils::DecimalAverager;
31
32#[derive(Debug)]
39pub struct DecimalDistinctAvgAccumulator<
40 I: DecimalType + Debug,
41 S: DecimalType + Debug = I,
42> {
43 sum_accumulator: DistinctSumAccumulator<I>,
44 sum_scale: i8,
45 target_precision: u8,
46 target_scale: i8,
47 _sum_type: PhantomData<S>,
48}
49
50impl<I: DecimalType + Debug, S: DecimalType + Debug> DecimalDistinctAvgAccumulator<I, S> {
51 pub fn with_decimal_params(
52 sum_scale: i8,
53 target_precision: u8,
54 target_scale: i8,
55 ) -> Self {
56 let data_type = I::TYPE_CONSTRUCTOR(I::MAX_PRECISION, sum_scale);
57
58 Self {
59 sum_accumulator: DistinctSumAccumulator::new(&data_type),
60 sum_scale,
61 target_precision,
62 target_scale,
63 _sum_type: PhantomData,
64 }
65 }
66}
67
68impl<I, S> Accumulator for DecimalDistinctAvgAccumulator<I, S>
69where
70 I: DecimalType + ArrowNumericType + Debug,
71 S: DecimalType + ArrowNumericType + Debug,
72 I::Native: Into<S::Native> + DecimalCast,
73 S::Native: DecimalCast,
74{
75 fn state(&mut self) -> Result<Vec<ScalarValue>> {
76 self.sum_accumulator.state()
77 }
78
79 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
80 self.sum_accumulator.update_batch(values)
81 }
82
83 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
84 self.sum_accumulator.merge_batch(states)
85 }
86
87 fn evaluate(&mut self) -> Result<ScalarValue> {
88 let out_type = I::TYPE_CONSTRUCTOR(self.target_precision, self.target_scale);
89 let count = self.sum_accumulator.distinct_count();
90 if count == 0 {
91 return ScalarValue::new_primitive::<I>(None, &out_type);
92 }
93
94 let mut sum = S::Native::usize_as(0);
97 for value in self.sum_accumulator.distinct_values() {
98 sum = sum.add_wrapping(value.into());
99 }
100
101 let Some(count) = S::Native::from_usize(count) else {
102 return exec_err!(
103 "Arithmetic overflow in avg: the distinct count {count} cannot \
104 be represented in the sum type"
105 );
106 };
107
108 let averager = DecimalAverager::<S>::try_new(
109 self.sum_scale,
110 self.target_precision,
111 self.target_scale,
112 )?;
113 let avg =
118 I::Native::from_decimal(averager.avg(sum, count)?).ok_or_else(|| {
119 exec_datafusion_err!(
120 "Arithmetic overflow in avg: the computed average does not fit \
121 the output type"
122 )
123 })?;
124 ScalarValue::new_primitive::<I>(Some(avg), &out_type)
125 }
126
127 fn size(&self) -> usize {
128 let fixed_size = size_of_val(self);
129
130 fixed_size + self.sum_accumulator.size()
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138 use arrow::array::{
139 Decimal32Array, Decimal64Array, Decimal128Array, Decimal256Array,
140 };
141 use arrow::datatypes::{
142 Decimal32Type, Decimal64Type, Decimal128Type, Decimal256Type, i256,
143 };
144 use std::sync::Arc;
145
146 #[test]
147 fn test_decimal32_distinct_avg_accumulator() -> Result<()> {
148 let precision = 5_u8;
149 let scale = 2_i8;
150 let array = Decimal32Array::from(vec![
151 Some(10_00),
152 Some(12_50),
153 Some(17_50),
154 Some(20_00),
155 Some(20_00),
156 Some(30_00),
157 None,
158 None,
159 ])
160 .with_precision_and_scale(precision, scale)?;
161
162 let mut accumulator =
163 DecimalDistinctAvgAccumulator::<Decimal32Type>::with_decimal_params(
164 scale, 9, 6,
165 );
166 accumulator.update_batch(&[Arc::new(array)])?;
167
168 let result = accumulator.evaluate()?;
169 let expected_result = ScalarValue::Decimal32(Some(18000000), 9, 6);
170 assert_eq!(result, expected_result);
171
172 Ok(())
173 }
174
175 #[test]
176 fn test_decimal64_distinct_avg_accumulator() -> Result<()> {
177 let precision = 10_u8;
178 let scale = 4_i8;
179 let array = Decimal64Array::from(vec![
180 Some(100_0000),
181 Some(125_0000),
182 Some(175_0000),
183 Some(200_0000),
184 Some(200_0000),
185 Some(300_0000),
186 None,
187 None,
188 ])
189 .with_precision_and_scale(precision, scale)?;
190
191 let mut accumulator =
192 DecimalDistinctAvgAccumulator::<Decimal64Type>::with_decimal_params(
193 scale, 14, 8,
194 );
195 accumulator.update_batch(&[Arc::new(array)])?;
196
197 let result = accumulator.evaluate()?;
198 let expected_result = ScalarValue::Decimal64(Some(180_00000000), 14, 8);
199 assert_eq!(result, expected_result);
200
201 Ok(())
202 }
203
204 #[test]
205 fn test_decimal128_distinct_avg_accumulator() -> Result<()> {
206 let precision = 10_u8;
207 let scale = 4_i8;
208 let array = Decimal128Array::from(vec![
209 Some(100_0000),
210 Some(125_0000),
211 Some(175_0000),
212 Some(200_0000),
213 Some(200_0000),
214 Some(300_0000),
215 None,
216 None,
217 ])
218 .with_precision_and_scale(precision, scale)?;
219
220 let mut accumulator =
221 DecimalDistinctAvgAccumulator::<Decimal128Type>::with_decimal_params(
222 scale, 14, 8,
223 );
224 accumulator.update_batch(&[Arc::new(array)])?;
225
226 let result = accumulator.evaluate()?;
227 let expected_result = ScalarValue::Decimal128(Some(180_00000000), 14, 8);
228 assert_eq!(result, expected_result);
229
230 Ok(())
231 }
232
233 #[test]
234 fn test_decimal256_distinct_avg_accumulator() -> Result<()> {
235 let precision = 50_u8;
236 let scale = 2_i8;
237
238 let array = Decimal256Array::from(vec![
239 Some(i256::from_i128(10_000)),
240 Some(i256::from_i128(12_500)),
241 Some(i256::from_i128(17_500)),
242 Some(i256::from_i128(20_000)),
243 Some(i256::from_i128(20_000)),
244 Some(i256::from_i128(30_000)),
245 None,
246 None,
247 ])
248 .with_precision_and_scale(precision, scale)?;
249
250 let mut accumulator =
251 DecimalDistinctAvgAccumulator::<Decimal256Type>::with_decimal_params(
252 scale, 54, 6,
253 );
254 accumulator.update_batch(&[Arc::new(array)])?;
255
256 let result = accumulator.evaluate()?;
257 let expected_result =
258 ScalarValue::Decimal256(Some(i256::from_i128(180_000000)), 54, 6);
259 assert_eq!(result, expected_result);
260
261 Ok(())
262 }
263
264 #[test]
269 fn test_decimal32_distinct_avg_widens_to_decimal64() -> Result<()> {
270 let array = Decimal32Array::from_iter_values(28525..=71475)
273 .with_precision_and_scale(5, 0)?;
274
275 let mut accumulator = DecimalDistinctAvgAccumulator::<
276 Decimal32Type,
277 Decimal64Type,
278 >::with_decimal_params(0, 9, 4);
279 accumulator.update_batch(&[Arc::new(array)])?;
280
281 assert_eq!(
282 accumulator.evaluate()?,
283 ScalarValue::Decimal32(Some(500_000_000), 9, 4)
284 );
285
286 Ok(())
287 }
288
289 #[test]
290 fn test_decimal32_distinct_avg_widens_to_decimal128() -> Result<()> {
291 let array = Decimal32Array::from_iter_values(89261..=110737)
294 .with_precision_and_scale(9, 0)?;
295
296 let mut accumulator = DecimalDistinctAvgAccumulator::<
297 Decimal32Type,
298 Decimal128Type,
299 >::with_decimal_params(0, 9, 4);
300 accumulator.update_batch(&[Arc::new(array)])?;
301
302 assert_eq!(
303 accumulator.evaluate()?,
304 ScalarValue::Decimal32(Some(999_990_000), 9, 4)
305 );
306
307 Ok(())
308 }
309
310 #[test]
311 fn test_decimal64_distinct_avg_widens_to_decimal128() -> Result<()> {
312 let center: i64 = 100_000_000_000_000 - 1;
315 let array = Decimal64Array::from_iter_values(center - 46117..=center + 46117)
316 .with_precision_and_scale(18, 0)?;
317
318 let mut accumulator = DecimalDistinctAvgAccumulator::<
319 Decimal64Type,
320 Decimal128Type,
321 >::with_decimal_params(0, 18, 4);
322 accumulator.update_batch(&[Arc::new(array)])?;
323
324 assert_eq!(
325 accumulator.evaluate()?,
326 ScalarValue::Decimal64(Some(999_999_999_999_990_000), 18, 4)
327 );
328
329 Ok(())
330 }
331
332 #[test]
333 fn test_decimal128_distinct_avg_widens_to_decimal256() -> Result<()> {
334 let center: i128 = 10_i128.pow(34) - 10739;
337 let array = Decimal128Array::from_iter_values(center - 10738..=center + 10738)
338 .with_precision_and_scale(34, 0)?;
339
340 let mut accumulator = DecimalDistinctAvgAccumulator::<
341 Decimal128Type,
342 Decimal256Type,
343 >::with_decimal_params(0, 38, 4);
344 accumulator.update_batch(&[Arc::new(array)])?;
345
346 assert_eq!(
347 accumulator.evaluate()?,
348 ScalarValue::Decimal128(Some(center * 10_000), 38, 4)
349 );
350
351 Ok(())
352 }
353}