1use arrow::{
19 array::{Array, ArrayRef, AsArray, BooleanArray, Int64Array, PrimitiveArray},
20 buffer::BooleanBuffer,
21 compute,
22 datatypes::{
23 DataType, Date32Type, Date64Type, Decimal128Type, Decimal256Type, Field,
24 FieldRef, Float16Type, Float32Type, Float64Type, Int8Type, Int16Type, Int32Type,
25 Int64Type, Time32MillisecondType, Time32SecondType, Time64MicrosecondType,
26 Time64NanosecondType, TimeUnit, TimestampMicrosecondType,
27 TimestampMillisecondType, TimestampNanosecondType, TimestampSecondType,
28 UInt8Type, UInt16Type, UInt32Type, UInt64Type,
29 },
30};
31use datafusion_common::hash_utils::RandomState;
32use datafusion_common::heap_size::{DFHeapSize, DFHeapSizeCtx};
33use datafusion_common::{
34 HashMap, Result, ScalarValue, downcast_value, exec_err, internal_err, not_impl_err,
35 stats::Precision, utils::expr::COUNT_STAR_EXPANSION,
36};
37use datafusion_expr::{
38 Accumulator, AggregateUDFImpl, Documentation, EmitTo, Expr, GroupsAccumulator,
39 ReversedUDAF, SetMonotonicity, Signature, StatisticsArgs, TypeSignature, Volatility,
40 WindowFunctionDefinition,
41 expr::WindowFunction,
42 function::{AccumulatorArgs, StateFieldsArgs},
43 utils::format_state_name,
44};
45use datafusion_functions_aggregate_common::aggregate::count_distinct::PrimitiveDistinctCountGroupsAccumulator;
46use datafusion_functions_aggregate_common::aggregate::{
47 count_distinct::Bitmap65536DistinctCountAccumulator,
48 count_distinct::Bitmap65536DistinctCountAccumulatorI16,
49 count_distinct::BoolArray256DistinctCountAccumulator,
50 count_distinct::BoolArray256DistinctCountAccumulatorI8,
51 count_distinct::BytesDistinctCountAccumulator,
52 count_distinct::BytesViewDistinctCountAccumulator,
53 count_distinct::DictionaryCountAccumulator,
54 count_distinct::FloatDistinctCountAccumulator,
55 count_distinct::PrimitiveDistinctCountAccumulator,
56 groups_accumulator::accumulate::accumulate_indices,
57};
58use datafusion_macros::user_doc;
59use datafusion_physical_expr::expressions;
60use datafusion_physical_expr_common::binary_map::OutputType;
61use std::{
62 collections::HashSet,
63 fmt::Debug,
64 mem::{size_of, size_of_val},
65 ops::BitAnd,
66 sync::Arc,
67};
68
69make_udaf_expr_and_func!(
70 Count,
71 count,
72 expr,
73 "Count the number of non-null values in the column",
74 count_udaf
75);
76
77pub fn count_distinct(expr: Expr) -> Expr {
78 Expr::AggregateFunction(datafusion_expr::expr::AggregateFunction::new_udf(
79 count_udaf(),
80 vec![expr],
81 true,
82 None,
83 vec![],
84 None,
85 ))
86}
87
88pub fn count_all() -> Expr {
106 count(Expr::Literal(COUNT_STAR_EXPANSION, None)).alias("count(*)")
107}
108
109pub fn count_all_window() -> Expr {
129 Expr::from(WindowFunction::new(
130 WindowFunctionDefinition::AggregateUDF(count_udaf()),
131 vec![Expr::Literal(COUNT_STAR_EXPANSION, None)],
132 ))
133}
134
135#[user_doc(
136 doc_section(label = "General Functions"),
137 description = "Returns the number of non-null values in the specified column. To include null values in the total count, use `count(*)`.",
138 syntax_example = "count(expression)",
139 sql_example = r#"```sql
140> SELECT count(column_name) FROM table_name;
141+-----------------------+
142| count(column_name) |
143+-----------------------+
144| 100 |
145+-----------------------+
146
147> SELECT count(*) FROM table_name;
148+------------------+
149| count(*) |
150+------------------+
151| 120 |
152+------------------+
153```"#,
154 standard_argument(name = "expression",)
155)]
156#[derive(PartialEq, Eq, Hash, Debug)]
157pub struct Count {
158 signature: Signature,
159}
160
161impl Default for Count {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167impl Count {
168 pub fn new() -> Self {
169 Self {
170 signature: Signature::one_of(
171 vec![TypeSignature::VariadicAny, TypeSignature::Nullary],
172 Volatility::Immutable,
173 ),
174 }
175 }
176}
177fn get_count_accumulator(data_type: &DataType) -> Box<dyn Accumulator> {
178 match data_type {
179 DataType::Int32 => Box::new(PrimitiveDistinctCountAccumulator::<Int32Type>::new(
181 data_type,
182 )),
183 DataType::Int64 => Box::new(PrimitiveDistinctCountAccumulator::<Int64Type>::new(
184 data_type,
185 )),
186 DataType::UInt32 => Box::new(
187 PrimitiveDistinctCountAccumulator::<UInt32Type>::new(data_type),
188 ),
189 DataType::UInt64 => Box::new(
190 PrimitiveDistinctCountAccumulator::<UInt64Type>::new(data_type),
191 ),
192 DataType::UInt8 | DataType::Int8 | DataType::UInt16 | DataType::Int16 => {
194 get_small_int_accumulator(data_type).unwrap()
195 }
196 DataType::Decimal128(_, _) => Box::new(PrimitiveDistinctCountAccumulator::<
197 Decimal128Type,
198 >::new(data_type)),
199 DataType::Decimal256(_, _) => Box::new(PrimitiveDistinctCountAccumulator::<
200 Decimal256Type,
201 >::new(data_type)),
202
203 DataType::Date32 => Box::new(
204 PrimitiveDistinctCountAccumulator::<Date32Type>::new(data_type),
205 ),
206 DataType::Date64 => Box::new(
207 PrimitiveDistinctCountAccumulator::<Date64Type>::new(data_type),
208 ),
209 DataType::Time32(TimeUnit::Millisecond) => Box::new(
210 PrimitiveDistinctCountAccumulator::<Time32MillisecondType>::new(data_type),
211 ),
212 DataType::Time32(TimeUnit::Second) => Box::new(
213 PrimitiveDistinctCountAccumulator::<Time32SecondType>::new(data_type),
214 ),
215 DataType::Time64(TimeUnit::Microsecond) => Box::new(
216 PrimitiveDistinctCountAccumulator::<Time64MicrosecondType>::new(data_type),
217 ),
218 DataType::Time64(TimeUnit::Nanosecond) => Box::new(
219 PrimitiveDistinctCountAccumulator::<Time64NanosecondType>::new(data_type),
220 ),
221 DataType::Timestamp(TimeUnit::Microsecond, _) => Box::new(
222 PrimitiveDistinctCountAccumulator::<TimestampMicrosecondType>::new(data_type),
223 ),
224 DataType::Timestamp(TimeUnit::Millisecond, _) => Box::new(
225 PrimitiveDistinctCountAccumulator::<TimestampMillisecondType>::new(data_type),
226 ),
227 DataType::Timestamp(TimeUnit::Nanosecond, _) => Box::new(
228 PrimitiveDistinctCountAccumulator::<TimestampNanosecondType>::new(data_type),
229 ),
230 DataType::Timestamp(TimeUnit::Second, _) => Box::new(
231 PrimitiveDistinctCountAccumulator::<TimestampSecondType>::new(data_type),
232 ),
233
234 DataType::Float16 => {
235 Box::new(FloatDistinctCountAccumulator::<Float16Type>::new())
236 }
237 DataType::Float32 => {
238 Box::new(FloatDistinctCountAccumulator::<Float32Type>::new())
239 }
240 DataType::Float64 => {
241 Box::new(FloatDistinctCountAccumulator::<Float64Type>::new())
242 }
243
244 DataType::Utf8 => {
245 Box::new(BytesDistinctCountAccumulator::<i32>::new(OutputType::Utf8))
246 }
247 DataType::Utf8View => {
248 Box::new(BytesViewDistinctCountAccumulator::new(OutputType::Utf8View))
249 }
250 DataType::LargeUtf8 => {
251 Box::new(BytesDistinctCountAccumulator::<i64>::new(OutputType::Utf8))
252 }
253 DataType::Binary => Box::new(BytesDistinctCountAccumulator::<i32>::new(
254 OutputType::Binary,
255 )),
256 DataType::BinaryView => Box::new(BytesViewDistinctCountAccumulator::new(
257 OutputType::BinaryView,
258 )),
259 DataType::LargeBinary => Box::new(BytesDistinctCountAccumulator::<i64>::new(
260 OutputType::Binary,
261 )),
262
263 _ => Box::new(DistinctCountAccumulator {
265 values: HashSet::default(),
266 state_data_type: data_type.clone(),
267 }),
268 }
269}
270
271#[cold]
273fn get_small_int_accumulator(data_type: &DataType) -> Result<Box<dyn Accumulator>> {
274 match data_type {
275 DataType::UInt8 => Ok(Box::new(BoolArray256DistinctCountAccumulator::new())),
276 DataType::Int8 => Ok(Box::new(BoolArray256DistinctCountAccumulatorI8::new())),
277 DataType::UInt16 => Ok(Box::new(Bitmap65536DistinctCountAccumulator::new())),
278 DataType::Int16 => Ok(Box::new(Bitmap65536DistinctCountAccumulatorI16::new())),
279 _ => exec_err!("unsupported accumulator for datatype: {}", data_type),
280 }
281}
282
283impl AggregateUDFImpl for Count {
284 fn name(&self) -> &str {
285 "count"
286 }
287
288 fn signature(&self) -> &Signature {
289 &self.signature
290 }
291
292 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
293 Ok(DataType::Int64)
294 }
295
296 fn is_nullable(&self) -> bool {
297 false
298 }
299
300 fn state_fields(&self, args: StateFieldsArgs) -> Result<Vec<FieldRef>> {
301 if args.is_distinct {
302 let dtype: DataType = match &args.input_fields[0].data_type() {
303 DataType::Dictionary(_, values_type) => (**values_type).clone(),
304 &dtype => dtype.clone(),
305 };
306
307 Ok(vec![
308 Field::new_list(
309 format_state_name(args.name, "count distinct"),
310 Field::new_list_field(dtype, true),
312 false,
313 )
314 .into(),
315 ])
316 } else {
317 Ok(vec![
318 Field::new(
319 format_state_name(args.name, "count"),
320 DataType::Int64,
321 false,
322 )
323 .into(),
324 ])
325 }
326 }
327
328 fn accumulator(&self, acc_args: AccumulatorArgs) -> Result<Box<dyn Accumulator>> {
329 if !acc_args.is_distinct {
330 return Ok(Box::new(CountAccumulator::new()));
331 }
332
333 if acc_args.exprs.len() > 1 {
334 return not_impl_err!("COUNT DISTINCT with multiple arguments");
335 }
336
337 let data_type = acc_args.expr_fields[0].data_type();
338
339 Ok(match data_type {
340 DataType::Dictionary(_, values_type) => {
341 let inner = get_count_accumulator(values_type);
342 Box::new(DictionaryCountAccumulator::new(inner))
343 }
344 _ => get_count_accumulator(data_type),
345 })
346 }
347
348 fn groups_accumulator_supported(&self, args: AccumulatorArgs) -> bool {
349 if args.exprs.len() != 1 {
350 return false;
351 }
352 if !args.is_distinct {
353 return true;
354 }
355 matches!(
356 args.expr_fields[0].data_type(),
357 DataType::Int8
358 | DataType::Int16
359 | DataType::Int32
360 | DataType::Int64
361 | DataType::UInt8
362 | DataType::UInt16
363 | DataType::UInt32
364 | DataType::UInt64
365 )
366 }
367
368 fn create_groups_accumulator(
369 &self,
370 args: AccumulatorArgs,
371 ) -> Result<Box<dyn GroupsAccumulator>> {
372 if !args.is_distinct {
373 return Ok(Box::new(CountGroupsAccumulator::new()));
374 }
375 create_distinct_count_groups_accumulator(&args)
376 }
377
378 fn reverse_expr(&self) -> ReversedUDAF {
379 ReversedUDAF::Identical
380 }
381
382 fn default_value(&self, _data_type: &DataType) -> Result<ScalarValue> {
383 Ok(ScalarValue::Int64(Some(0)))
384 }
385
386 fn value_from_stats(&self, statistics_args: &StatisticsArgs) -> Option<ScalarValue> {
387 let [expr] = statistics_args.exprs else {
388 return None;
389 };
390 let col_stats = &statistics_args.statistics.column_statistics;
391
392 if statistics_args.is_distinct {
393 let col_expr = expr.downcast_ref::<expressions::Column>()?;
396 if let Precision::Exact(dc) = col_stats[col_expr.index()].distinct_count {
397 let dc = i64::try_from(dc).ok()?;
398 return Some(ScalarValue::Int64(Some(dc)));
399 }
400 return None;
401 }
402
403 let Precision::Exact(num_rows) = statistics_args.statistics.num_rows else {
404 return None;
405 };
406
407 if let Some(col_expr) = expr.downcast_ref::<expressions::Column>() {
409 if let Precision::Exact(val) = col_stats[col_expr.index()].null_count {
410 let count = i64::try_from(num_rows - val).ok()?;
411 return Some(ScalarValue::Int64(Some(count)));
412 }
413 } else if let Some(lit_expr) = expr.downcast_ref::<expressions::Literal>()
414 && lit_expr.value() == &COUNT_STAR_EXPANSION
415 {
416 let num_rows = i64::try_from(num_rows).ok()?;
417 return Some(ScalarValue::Int64(Some(num_rows)));
418 }
419
420 None
421 }
422
423 fn documentation(&self) -> Option<&Documentation> {
424 self.doc()
425 }
426
427 fn set_monotonicity(&self, _data_type: &DataType) -> SetMonotonicity {
428 SetMonotonicity::Increasing
431 }
432
433 fn create_sliding_accumulator(
434 &self,
435 args: AccumulatorArgs,
436 ) -> Result<Box<dyn Accumulator>> {
437 if args.is_distinct {
438 let acc =
439 SlidingDistinctCountAccumulator::try_new(args.return_field.data_type())?;
440 Ok(Box::new(acc))
441 } else {
442 let acc = CountAccumulator::new();
443 Ok(Box::new(acc))
444 }
445 }
446}
447
448#[cold]
449fn create_distinct_count_groups_accumulator(
450 args: &AccumulatorArgs,
451) -> Result<Box<dyn GroupsAccumulator>> {
452 let data_type = args.expr_fields[0].data_type();
453 match data_type {
454 DataType::Int8 => Ok(Box::new(
455 PrimitiveDistinctCountGroupsAccumulator::<Int8Type>::new(),
456 )),
457 DataType::Int16 => Ok(Box::new(PrimitiveDistinctCountGroupsAccumulator::<
458 Int16Type,
459 >::new())),
460 DataType::Int32 => Ok(Box::new(PrimitiveDistinctCountGroupsAccumulator::<
461 Int32Type,
462 >::new())),
463 DataType::Int64 => Ok(Box::new(PrimitiveDistinctCountGroupsAccumulator::<
464 Int64Type,
465 >::new())),
466 DataType::UInt8 => Ok(Box::new(PrimitiveDistinctCountGroupsAccumulator::<
467 UInt8Type,
468 >::new())),
469 DataType::UInt16 => Ok(Box::new(PrimitiveDistinctCountGroupsAccumulator::<
470 UInt16Type,
471 >::new())),
472 DataType::UInt32 => Ok(Box::new(PrimitiveDistinctCountGroupsAccumulator::<
473 UInt32Type,
474 >::new())),
475 DataType::UInt64 => Ok(Box::new(PrimitiveDistinctCountGroupsAccumulator::<
476 UInt64Type,
477 >::new())),
478 _ => not_impl_err!(
479 "GroupsAccumulator not supported for COUNT(DISTINCT) with {}",
480 data_type
481 ),
482 }
483}
484
485#[derive(Debug)]
489pub struct SlidingDistinctCountAccumulator {
490 counts: HashMap<ScalarValue, usize, RandomState>,
491 data_type: DataType,
492}
493
494impl SlidingDistinctCountAccumulator {
495 pub fn try_new(data_type: &DataType) -> Result<Self> {
496 Ok(Self {
497 counts: HashMap::default(),
498 data_type: data_type.clone(),
499 })
500 }
501}
502
503impl Accumulator for SlidingDistinctCountAccumulator {
504 fn state(&mut self) -> Result<Vec<ScalarValue>> {
505 let keys = self.counts.keys().cloned().collect::<Vec<_>>();
506 Ok(vec![ScalarValue::List(ScalarValue::new_list_nullable(
507 keys.as_slice(),
508 &self.data_type,
509 ))])
510 }
511
512 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
513 let arr = &values[0];
514 for i in 0..arr.len() {
515 let v = ScalarValue::try_from_array(arr, i)?;
516 if !v.is_null() {
517 *self.counts.entry(v).or_default() += 1;
518 }
519 }
520 Ok(())
521 }
522
523 fn retract_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
524 let arr = &values[0];
525 for i in 0..arr.len() {
526 let v = ScalarValue::try_from_array(arr, i)?;
527 if !v.is_null()
528 && let Some(cnt) = self.counts.get_mut(&v)
529 {
530 *cnt -= 1;
531 if *cnt == 0 {
532 self.counts.remove(&v);
533 }
534 }
535 }
536 Ok(())
537 }
538
539 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
540 let list_arr = states[0].as_list::<i32>();
541 for inner in list_arr.iter().flatten() {
542 for j in 0..inner.len() {
543 let v = ScalarValue::try_from_array(&*inner, j)?;
544 *self.counts.entry(v).or_default() += 1;
545 }
546 }
547 Ok(())
548 }
549
550 fn evaluate(&mut self) -> Result<ScalarValue> {
551 Ok(ScalarValue::Int64(Some(self.counts.len() as i64)))
552 }
553
554 fn supports_retract_batch(&self) -> bool {
555 true
556 }
557
558 fn size(&self) -> usize {
559 size_of_val(self)
562 + (size_of::<ScalarValue>() + size_of::<usize>()) * self.counts.capacity()
563 + self
564 .counts
565 .keys()
566 .map(|k| k.size() - size_of_val(k))
567 .sum::<usize>()
568 + self.data_type.size()
569 - size_of_val(&self.data_type)
570 }
571}
572
573#[derive(Debug)]
574struct CountAccumulator {
575 count: i64,
576}
577
578impl CountAccumulator {
579 pub fn new() -> Self {
581 Self { count: 0 }
582 }
583}
584
585impl Accumulator for CountAccumulator {
586 fn state(&mut self) -> Result<Vec<ScalarValue>> {
587 Ok(vec![ScalarValue::Int64(Some(self.count))])
588 }
589
590 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
591 let array = &values[0];
592 self.count += (array.len() - null_count_for_multiple_cols(values)) as i64;
593 Ok(())
594 }
595
596 fn retract_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
597 let array = &values[0];
598 self.count -= (array.len() - null_count_for_multiple_cols(values)) as i64;
599 Ok(())
600 }
601
602 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
603 let counts = downcast_value!(states[0], Int64Array);
604 let delta = &compute::sum(counts);
605 if let Some(d) = delta {
606 self.count += *d;
607 }
608 Ok(())
609 }
610
611 fn evaluate(&mut self) -> Result<ScalarValue> {
612 Ok(ScalarValue::Int64(Some(self.count)))
613 }
614
615 fn supports_retract_batch(&self) -> bool {
616 true
617 }
618
619 fn size(&self) -> usize {
620 size_of_val(self)
621 }
622}
623
624#[derive(Debug)]
631struct CountGroupsAccumulator {
632 counts: Vec<i64>,
639}
640
641impl CountGroupsAccumulator {
642 pub fn new() -> Self {
643 Self { counts: vec![] }
644 }
645}
646
647impl GroupsAccumulator for CountGroupsAccumulator {
648 fn update_batch(
649 &mut self,
650 values: &[ArrayRef],
651 group_indices: &[usize],
652 opt_filter: Option<&BooleanArray>,
653 total_num_groups: usize,
654 ) -> Result<()> {
655 assert_eq!(values.len(), 1, "single argument to update_batch");
656 let values = &values[0];
657
658 self.counts.resize(total_num_groups, 0);
661 accumulate_indices(
662 group_indices,
663 values.logical_nulls().as_ref(),
664 opt_filter,
665 |group_index| {
666 let count = unsafe { self.counts.get_unchecked_mut(group_index) };
668 *count += 1;
669 },
670 );
671
672 Ok(())
673 }
674
675 fn merge_batch(
676 &mut self,
677 values: &[ArrayRef],
678 group_indices: &[usize],
679 total_num_groups: usize,
680 ) -> Result<()> {
681 assert_eq!(values.len(), 1, "one argument to merge_batch");
682 let partial_counts = values[0].as_primitive::<Int64Type>();
684
685 assert_eq!(partial_counts.null_count(), 0);
687 let partial_counts = partial_counts.values();
688
689 self.counts.resize(total_num_groups, 0);
691 group_indices.iter().zip(partial_counts.iter()).for_each(
692 |(&group_index, partial_count)| {
693 self.counts[group_index] += partial_count;
694 },
695 );
696
697 Ok(())
698 }
699
700 fn evaluate(&mut self, emit_to: EmitTo) -> Result<ArrayRef> {
701 let counts = emit_to.take_needed(&mut self.counts);
702
703 let nulls = None;
705 let array = PrimitiveArray::<Int64Type>::new(counts.into(), nulls);
706
707 Ok(Arc::new(array))
708 }
709
710 fn state(&mut self, emit_to: EmitTo) -> Result<Vec<ArrayRef>> {
712 let counts = emit_to.take_needed(&mut self.counts);
713 let counts: PrimitiveArray<Int64Type> = Int64Array::from(counts); Ok(vec![Arc::new(counts) as ArrayRef])
715 }
716
717 fn convert_to_state(
723 &self,
724 values: &[ArrayRef],
725 opt_filter: Option<&BooleanArray>,
726 ) -> Result<Vec<ArrayRef>> {
727 let values = &values[0];
728
729 let state_array = match (values.logical_nulls(), opt_filter) {
730 (None, None) => {
731 Arc::new(Int64Array::from_value(1, values.len()))
733 }
734 (Some(nulls), None) => {
735 let nulls = BooleanArray::new(nulls.into_inner(), None);
738 compute::cast(&nulls, &DataType::Int64)?
739 }
740 (None, Some(filter)) => {
741 let (filter_values, filter_nulls) = filter.clone().into_parts();
746
747 let state_buf = match filter_nulls {
748 Some(filter_nulls) => &filter_values & filter_nulls.inner(),
749 None => filter_values,
750 };
751
752 let boolean_state = BooleanArray::new(state_buf, None);
753 compute::cast(&boolean_state, &DataType::Int64)?
754 }
755 (Some(nulls), Some(filter)) => {
756 let (filter_values, filter_nulls) = filter.clone().into_parts();
763
764 let filter_buf = match filter_nulls {
765 Some(filter_nulls) => &filter_values & filter_nulls.inner(),
766 None => filter_values,
767 };
768 let state_buf = &filter_buf & nulls.inner();
769
770 let boolean_state = BooleanArray::new(state_buf, None);
771 compute::cast(&boolean_state, &DataType::Int64)?
772 }
773 };
774
775 Ok(vec![state_array])
776 }
777 fn size(&self) -> usize {
778 self.counts.heap_size(&mut DFHeapSizeCtx::default())
779 }
780}
781
782fn null_count_for_multiple_cols(values: &[ArrayRef]) -> usize {
785 if values.len() > 1 {
786 let result_bool_buf: Option<BooleanBuffer> = values
787 .iter()
788 .map(|a| a.logical_nulls())
789 .fold(None, |acc, b| match (acc, b) {
790 (Some(acc), Some(b)) => Some(acc.bitand(b.inner())),
791 (Some(acc), None) => Some(acc),
792 (None, Some(b)) => Some(b.into_inner()),
793 _ => None,
794 });
795 result_bool_buf.map_or(0, |b| values[0].len() - b.count_set_bits())
796 } else {
797 values[0]
798 .logical_nulls()
799 .map_or(0, |nulls| nulls.null_count())
800 }
801}
802
803#[derive(Debug)]
812struct DistinctCountAccumulator {
813 values: HashSet<ScalarValue, RandomState>,
814 state_data_type: DataType,
815}
816
817impl DistinctCountAccumulator {
818 fn fixed_size(&self) -> usize {
822 size_of_val(self)
823 + (size_of::<ScalarValue>() * self.values.capacity())
824 + self
825 .values
826 .iter()
827 .next()
828 .map(|vals| ScalarValue::size(vals) - size_of_val(vals))
829 .unwrap_or(0)
830 + size_of::<DataType>()
831 }
832
833 fn full_size(&self) -> usize {
836 size_of_val(self)
837 + (size_of::<ScalarValue>() * self.values.capacity())
838 + self
839 .values
840 .iter()
841 .map(|vals| ScalarValue::size(vals) - size_of_val(vals))
842 .sum::<usize>()
843 + size_of::<DataType>()
844 }
845}
846
847impl Accumulator for DistinctCountAccumulator {
848 fn state(&mut self) -> Result<Vec<ScalarValue>> {
850 let scalars = self.values.iter().cloned().collect::<Vec<_>>();
851 let arr =
852 ScalarValue::new_list_nullable(scalars.as_slice(), &self.state_data_type);
853 Ok(vec![ScalarValue::List(arr)])
854 }
855
856 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
857 if values.is_empty() {
858 return Ok(());
859 }
860
861 let arr = &values[0];
862 if arr.data_type() == &DataType::Null {
863 return Ok(());
864 }
865
866 (0..arr.len()).try_for_each(|index| {
867 let scalar = ScalarValue::try_from_array(arr, index)?;
868 if !scalar.is_null() {
869 self.values.insert(scalar);
870 }
871 Ok(())
872 })
873 }
874
875 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
881 if states.is_empty() {
882 return Ok(());
883 }
884 assert_eq!(states.len(), 1, "array_agg states must be singleton!");
885 let array = &states[0];
886 let list_array = array.as_list::<i32>();
887 for inner_array in list_array.iter() {
888 let Some(inner_array) = inner_array else {
889 return internal_err!(
890 "Intermediate results of COUNT DISTINCT should always be non null"
891 );
892 };
893 self.update_batch(&[inner_array])?;
894 }
895 Ok(())
896 }
897
898 fn evaluate(&mut self) -> Result<ScalarValue> {
899 Ok(ScalarValue::Int64(Some(self.values.len() as i64)))
900 }
901
902 fn size(&self) -> usize {
903 match &self.state_data_type {
904 DataType::Boolean | DataType::Null => self.fixed_size(),
905 d if d.is_primitive() => self.fixed_size(),
906 _ => self.full_size(),
907 }
908 }
909}
910
911#[cfg(test)]
912mod tests {
913
914 use super::*;
915 use arrow::{
916 array::{DictionaryArray, Int32Array, NullArray, StringArray},
917 datatypes::{DataType, Field, Int32Type, Schema},
918 };
919 use datafusion_expr::function::AccumulatorArgs;
920 use datafusion_physical_expr::{PhysicalExpr, expressions::Column};
921 use std::sync::Arc;
922 fn create_dictionary_with_null_values() -> Result<DictionaryArray<Int32Type>> {
928 let values = StringArray::from(vec![Some("a"), None, Some("c")]);
929 let keys = Int32Array::from(vec![0, 1, 2, 0, 1]); Ok(DictionaryArray::<Int32Type>::try_new(
931 keys,
932 Arc::new(values),
933 )?)
934 }
935
936 #[test]
937 fn count_groups_size_includes_vec_capacity() -> Result<()> {
938 let mut acc = CountGroupsAccumulator::new();
939 let empty_size = acc.size();
940 assert_eq!(empty_size, 0);
941 let values: ArrayRef = Arc::new(Int64Array::from(vec![1, 2, 3]));
942 acc.update_batch(&[values], &[0, 1, 2], None, 3)?;
943
944 assert!(acc.counts.capacity() > 0);
945 let allocated_size = acc.counts.heap_size(&mut DFHeapSizeCtx::default());
946 assert_eq!(allocated_size, acc.counts.capacity() * size_of::<i64>());
947 assert_eq!(acc.size(), allocated_size);
948 assert!(acc.size() > empty_size);
949
950 Ok(())
951 }
952
953 #[test]
954 fn count_accumulator_nulls() -> Result<()> {
955 let mut accumulator = CountAccumulator::new();
956 accumulator.update_batch(&[Arc::new(NullArray::new(10))])?;
957 assert_eq!(accumulator.evaluate()?, ScalarValue::Int64(Some(0)));
958 Ok(())
959 }
960
961 #[test]
962 fn test_nested_dictionary() -> Result<()> {
963 let schema = Arc::new(Schema::new(vec![Field::new(
964 "dict_col",
965 DataType::Dictionary(
966 Box::new(DataType::Int32),
967 Box::new(DataType::Dictionary(
968 Box::new(DataType::Int32),
969 Box::new(DataType::Utf8),
970 )),
971 ),
972 true,
973 )]));
974
975 let count = Count::new();
977 let expr = Arc::new(Column::new("dict_col", 0));
978 let expr_field = expr.return_field(&schema)?;
979 let args = AccumulatorArgs {
980 schema: &schema,
981 expr_fields: &[expr_field],
982 exprs: &[expr],
983 is_distinct: true,
984 name: "count",
985 ignore_nulls: false,
986 is_reversed: false,
987 return_field: Arc::new(Field::new_list_field(DataType::Int64, true)),
988 order_bys: &[],
989 };
990
991 let inner_dict =
992 DictionaryArray::<Int32Type>::from_iter(["a", "b", "c", "d", "a", "b"]);
993
994 let keys = Int32Array::from(vec![0, 1, 2, 0, 3, 1]);
995 let dict_of_dict =
996 DictionaryArray::<Int32Type>::try_new(keys, Arc::new(inner_dict))?;
997
998 let mut acc = count.accumulator(args)?;
999 acc.update_batch(&[Arc::new(dict_of_dict)])?;
1000 assert_eq!(acc.evaluate()?, ScalarValue::Int64(Some(4)));
1001
1002 Ok(())
1003 }
1004
1005 #[test]
1006 fn count_distinct_accumulator_dictionary_with_null_values() -> Result<()> {
1007 let dict_array = create_dictionary_with_null_values()?;
1008
1009 let mut accumulator = DistinctCountAccumulator {
1012 values: HashSet::default(),
1013 state_data_type: dict_array.data_type().clone(),
1014 };
1015
1016 accumulator.update_batch(&[Arc::new(dict_array)])?;
1017
1018 assert_eq!(accumulator.evaluate()?, ScalarValue::Int64(Some(2)));
1020 Ok(())
1021 }
1022
1023 #[test]
1024 fn count_accumulator_dictionary_with_null_values() -> Result<()> {
1025 let dict_array = create_dictionary_with_null_values()?;
1026
1027 let mut accumulator = CountAccumulator::new();
1029
1030 accumulator.update_batch(&[Arc::new(dict_array)])?;
1031
1032 assert_eq!(accumulator.evaluate()?, ScalarValue::Int64(Some(3)));
1035 Ok(())
1036 }
1037
1038 #[test]
1039 fn count_distinct_accumulator_dictionary_all_null_values() -> Result<()> {
1040 let dict_values = StringArray::from(vec![None, Some("abc")]);
1042 let dict_indices = Int32Array::from(vec![0; 5]);
1043 let dict_array =
1044 DictionaryArray::<Int32Type>::try_new(dict_indices, Arc::new(dict_values))?;
1045
1046 let mut accumulator = DistinctCountAccumulator {
1047 values: HashSet::default(),
1048 state_data_type: dict_array.data_type().clone(),
1049 };
1050
1051 accumulator.update_batch(&[Arc::new(dict_array)])?;
1052
1053 assert_eq!(accumulator.evaluate()?, ScalarValue::Int64(Some(0)));
1055 Ok(())
1056 }
1057
1058 #[test]
1059 fn sliding_distinct_count_accumulator_basic() -> Result<()> {
1060 let mut acc = SlidingDistinctCountAccumulator::try_new(&DataType::Int32)?;
1062 let values: ArrayRef = Arc::new(Int32Array::from(vec![
1064 Some(1),
1065 Some(2),
1066 Some(2),
1067 Some(3),
1068 None,
1069 ]));
1070 acc.update_batch(&[values])?;
1071 assert_eq!(acc.evaluate()?, ScalarValue::Int64(Some(3)));
1073 Ok(())
1074 }
1075
1076 #[test]
1077 fn sliding_distinct_count_accumulator_retract() -> Result<()> {
1078 let mut acc = SlidingDistinctCountAccumulator::try_new(&DataType::Utf8)?;
1080 let arr1 = Arc::new(StringArray::from(vec![Some("a"), Some("b"), Some("a")]))
1082 as ArrayRef;
1083 acc.update_batch(&[arr1])?;
1084 assert_eq!(acc.evaluate()?, ScalarValue::Int64(Some(2))); let arr2 =
1088 Arc::new(StringArray::from(vec![Some("a"), None, Some("b")])) as ArrayRef;
1089 acc.retract_batch(&[arr2])?;
1090 assert_eq!(acc.evaluate()?, ScalarValue::Int64(Some(1)));
1092 Ok(())
1093 }
1094
1095 #[test]
1096 fn sliding_distinct_count_accumulator_merge_states() -> Result<()> {
1097 let mut acc1 = SlidingDistinctCountAccumulator::try_new(&DataType::Int32)?;
1099 let mut acc2 = SlidingDistinctCountAccumulator::try_new(&DataType::Int32)?;
1100 acc1.update_batch(&[Arc::new(Int32Array::from(vec![Some(1), Some(2)]))])?;
1102 acc2.update_batch(&[Arc::new(Int32Array::from(vec![Some(2), Some(3)]))])?;
1104 let state_sv1 = acc1.state()?;
1106 let state_sv2 = acc2.state()?;
1107 let state_arr1: Vec<ArrayRef> = state_sv1
1110 .into_iter()
1111 .map(|sv| sv.to_array())
1112 .collect::<Result<_>>()?;
1113 let state_arr2: Vec<ArrayRef> = state_sv2
1114 .into_iter()
1115 .map(|sv| sv.to_array())
1116 .collect::<Result<_>>()?;
1117 let mut merged = SlidingDistinctCountAccumulator::try_new(&DataType::Int32)?;
1119 merged.merge_batch(&state_arr1)?;
1120 merged.merge_batch(&state_arr2)?;
1121 assert_eq!(merged.evaluate()?, ScalarValue::Int64(Some(3)));
1123 Ok(())
1124 }
1125}