1use std::fmt::Debug;
21use std::hash::Hash;
22use std::mem::size_of_val;
23use std::sync::Arc;
24
25use arrow::array::{Array, ArrayRef, AsArray, BooleanArray, BooleanBufferBuilder};
26use arrow::buffer::BooleanBuffer;
27use arrow::compute::{self, LexicographicalComparator, SortColumn, SortOptions};
28use arrow::datatypes::{
29 DataType, Date32Type, Date64Type, Decimal32Type, Decimal64Type, Decimal128Type,
30 Decimal256Type, Field, FieldRef, Float16Type, Float32Type, Float64Type, Int8Type,
31 Int16Type, Int32Type, Int64Type, Time32MillisecondType, Time32SecondType,
32 Time64MicrosecondType, Time64NanosecondType, TimeUnit, TimestampMicrosecondType,
33 TimestampMillisecondType, TimestampNanosecondType, TimestampSecondType, UInt8Type,
34 UInt16Type, UInt32Type, UInt64Type,
35};
36use datafusion_common::cast::as_boolean_array;
37use datafusion_common::utils::{compare_rows, extract_row_at_idx_to_buf, get_row_at_idx};
38use datafusion_common::{
39 DataFusionError, Result, ScalarValue, arrow_datafusion_err, internal_err,
40 not_impl_err,
41};
42use datafusion_expr::function::{AccumulatorArgs, StateFieldsArgs};
43use datafusion_expr::utils::{AggregateOrderSensitivity, format_state_name};
44use datafusion_expr::{
45 Accumulator, AggregateUDFImpl, Documentation, EmitTo, Expr, ExprFunctionExt,
46 GroupsAccumulator, ReversedUDAF, Signature, SortExpr, Volatility,
47};
48use datafusion_functions_aggregate_common::utils::get_sort_options;
49use datafusion_macros::user_doc;
50use datafusion_physical_expr_common::sort_expr::LexOrdering;
51
52mod state;
53
54use state::{BytesValueState, GenericValueState, PrimitiveValueState, ValueState};
55
56create_func!(FirstValue, first_value_udaf);
57create_func!(LastValue, last_value_udaf);
58
59pub fn first_value(expression: Expr, order_by: Vec<SortExpr>) -> Expr {
61 first_value_udaf()
62 .call(vec![expression])
63 .order_by(order_by)
64 .build()
65 .unwrap()
67}
68
69pub fn last_value(expression: Expr, order_by: Vec<SortExpr>) -> Expr {
71 last_value_udaf()
72 .call(vec![expression])
73 .order_by(order_by)
74 .build()
75 .unwrap()
77}
78
79fn create_groups_accumulator_helper<S: ValueState + 'static>(
80 args: &AccumulatorArgs,
81 is_first: bool,
82 state: S,
83) -> Result<Box<dyn GroupsAccumulator>> {
84 let Some(ordering) = LexOrdering::new(args.order_bys.to_vec()) else {
85 return internal_err!("Groups accumulator must have an ordering.");
86 };
87
88 let ordering_dtypes = ordering
89 .iter()
90 .map(|e| e.expr.data_type(args.schema))
91 .collect::<Result<Vec<_>>>()?;
92
93 Ok(Box::new(FirstLastGroupsAccumulator::try_new(
94 state,
95 ordering,
96 args.ignore_nulls,
97 &ordering_dtypes,
98 is_first,
99 )?))
100}
101
102fn create_groups_accumulator(
103 args: &AccumulatorArgs,
104 is_first: bool,
105 function_name: &str,
106) -> Result<Box<dyn GroupsAccumulator>> {
107 let data_type = args.return_field.data_type();
108
109 macro_rules! instantiate_primitive {
110 ($t:ty) => {
111 create_groups_accumulator_helper(
112 args,
113 is_first,
114 PrimitiveValueState::<$t>::new(data_type.clone()),
115 )
116 };
117 }
118
119 match data_type {
120 DataType::Int8 => instantiate_primitive!(Int8Type),
121 DataType::Int16 => instantiate_primitive!(Int16Type),
122 DataType::Int32 => instantiate_primitive!(Int32Type),
123 DataType::Int64 => instantiate_primitive!(Int64Type),
124 DataType::UInt8 => instantiate_primitive!(UInt8Type),
125 DataType::UInt16 => instantiate_primitive!(UInt16Type),
126 DataType::UInt32 => instantiate_primitive!(UInt32Type),
127 DataType::UInt64 => instantiate_primitive!(UInt64Type),
128 DataType::Float16 => instantiate_primitive!(Float16Type),
129 DataType::Float32 => instantiate_primitive!(Float32Type),
130 DataType::Float64 => instantiate_primitive!(Float64Type),
131
132 DataType::Decimal32(_, _) => instantiate_primitive!(Decimal32Type),
133 DataType::Decimal64(_, _) => instantiate_primitive!(Decimal64Type),
134 DataType::Decimal128(_, _) => instantiate_primitive!(Decimal128Type),
135 DataType::Decimal256(_, _) => instantiate_primitive!(Decimal256Type),
136
137 DataType::Timestamp(TimeUnit::Second, _) => {
138 instantiate_primitive!(TimestampSecondType)
139 }
140 DataType::Timestamp(TimeUnit::Millisecond, _) => {
141 instantiate_primitive!(TimestampMillisecondType)
142 }
143 DataType::Timestamp(TimeUnit::Microsecond, _) => {
144 instantiate_primitive!(TimestampMicrosecondType)
145 }
146 DataType::Timestamp(TimeUnit::Nanosecond, _) => {
147 instantiate_primitive!(TimestampNanosecondType)
148 }
149
150 DataType::Date32 => instantiate_primitive!(Date32Type),
151 DataType::Date64 => instantiate_primitive!(Date64Type),
152 DataType::Time32(TimeUnit::Second) => instantiate_primitive!(Time32SecondType),
153 DataType::Time32(TimeUnit::Millisecond) => {
154 instantiate_primitive!(Time32MillisecondType)
155 }
156 DataType::Time64(TimeUnit::Microsecond) => {
157 instantiate_primitive!(Time64MicrosecondType)
158 }
159 DataType::Time64(TimeUnit::Nanosecond) => {
160 instantiate_primitive!(Time64NanosecondType)
161 }
162
163 DataType::Utf8
164 | DataType::LargeUtf8
165 | DataType::Utf8View
166 | DataType::Binary
167 | DataType::LargeBinary
168 | DataType::BinaryView => create_groups_accumulator_helper(
169 args,
170 is_first,
171 BytesValueState::try_new(data_type.clone())?,
172 ),
173
174 DataType::List(_)
180 | DataType::LargeList(_)
181 | DataType::ListView(_)
182 | DataType::LargeListView(_)
183 | DataType::FixedSizeList(_, _)
184 | DataType::Struct(_)
185 | DataType::Map(_, _) => create_groups_accumulator_helper(
186 args,
187 is_first,
188 GenericValueState::new(data_type.clone()),
189 ),
190
191 _ => internal_err!(
192 "GroupsAccumulator not supported for {}({})",
193 function_name,
194 data_type
195 ),
196 }
197}
198
199fn groups_accumulator_supported(args: &AccumulatorArgs) -> bool {
200 use DataType::*;
201 !args.order_bys.is_empty()
202 && matches!(
203 args.return_field.data_type(),
204 Int8 | Int16
205 | Int32
206 | Int64
207 | UInt8
208 | UInt16
209 | UInt32
210 | UInt64
211 | Float16
212 | Float32
213 | Float64
214 | Decimal32(_, _)
215 | Decimal64(_, _)
216 | Decimal128(_, _)
217 | Decimal256(_, _)
218 | Date32
219 | Date64
220 | Time32(_)
221 | Time64(_)
222 | Timestamp(_, _)
223 | Utf8
224 | LargeUtf8
225 | Utf8View
226 | Binary
227 | LargeBinary
228 | BinaryView
229 | List(_)
230 | LargeList(_)
231 | ListView(_)
232 | LargeListView(_)
233 | FixedSizeList(_, _)
234 | Struct(_)
235 | Map(_, _)
236 )
237}
238
239#[user_doc(
240 doc_section(label = "General Functions"),
241 description = "Returns the first element in an aggregation group according to the requested ordering. If no ordering is given, returns an arbitrary element from the group.",
242 syntax_example = "first_value(expression [ORDER BY expression])",
243 sql_example = r#"```sql
244> SELECT first_value(column_name ORDER BY other_column) FROM table_name;
245+-----------------------------------------------+
246| first_value(column_name ORDER BY other_column)|
247+-----------------------------------------------+
248| first_element |
249+-----------------------------------------------+
250```"#,
251 standard_argument(name = "expression",)
252)]
253#[derive(PartialEq, Eq, Hash, Debug)]
254pub struct FirstValue {
255 signature: Signature,
256 is_input_pre_ordered: bool,
257}
258
259impl Default for FirstValue {
260 fn default() -> Self {
261 Self::new()
262 }
263}
264
265impl FirstValue {
266 pub fn new() -> Self {
267 Self {
268 signature: Signature::any(1, Volatility::Immutable),
269 is_input_pre_ordered: false,
270 }
271 }
272}
273
274impl AggregateUDFImpl for FirstValue {
275 fn name(&self) -> &str {
276 "first_value"
277 }
278
279 fn signature(&self) -> &Signature {
280 &self.signature
281 }
282
283 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
284 not_impl_err!("Not called because the return_field_from_args is implemented")
285 }
286
287 fn return_field(&self, arg_fields: &[FieldRef]) -> Result<FieldRef> {
288 Ok(Arc::new(
290 Field::new(
291 self.name(),
292 arg_fields[0].data_type().clone(),
293 true, )
295 .with_metadata(arg_fields[0].metadata().clone()),
296 ))
297 }
298
299 fn accumulator(&self, acc_args: AccumulatorArgs) -> Result<Box<dyn Accumulator>> {
300 let Some(ordering) = LexOrdering::new(acc_args.order_bys.to_vec()) else {
301 return TrivialFirstValueAccumulator::try_new(
302 acc_args.return_field.data_type(),
303 acc_args.ignore_nulls,
304 )
305 .map(|acc| Box::new(acc) as _);
306 };
307 let ordering_dtypes = ordering
308 .iter()
309 .map(|e| e.expr.data_type(acc_args.schema))
310 .collect::<Result<Vec<_>>>()?;
311 Ok(Box::new(FirstValueAccumulator::try_new(
312 acc_args.return_field.data_type(),
313 &ordering_dtypes,
314 ordering,
315 self.is_input_pre_ordered,
316 acc_args.ignore_nulls,
317 )?))
318 }
319
320 fn state_fields(&self, args: StateFieldsArgs) -> Result<Vec<FieldRef>> {
321 let mut fields = vec![
322 Field::new(
323 format_state_name(args.name, "first_value"),
324 args.return_type().clone(),
325 true,
326 )
327 .into(),
328 ];
329 fields.extend(args.ordering_fields.iter().cloned());
330 fields.push(
331 Field::new(
332 format_state_name(args.name, "first_value_is_set"),
333 DataType::Boolean,
334 true,
335 )
336 .into(),
337 );
338 Ok(fields)
339 }
340
341 fn groups_accumulator_supported(&self, args: AccumulatorArgs) -> bool {
342 groups_accumulator_supported(&args)
343 }
344
345 fn create_groups_accumulator(
346 &self,
347 args: AccumulatorArgs,
348 ) -> Result<Box<dyn GroupsAccumulator>> {
349 create_groups_accumulator(&args, true, self.name())
350 }
351
352 fn with_beneficial_ordering(
353 self: Arc<Self>,
354 beneficial_ordering: bool,
355 ) -> Result<Option<Arc<dyn AggregateUDFImpl>>> {
356 Ok(Some(Arc::new(Self {
357 signature: self.signature.clone(),
358 is_input_pre_ordered: beneficial_ordering,
359 })))
360 }
361
362 fn order_sensitivity(&self) -> AggregateOrderSensitivity {
363 AggregateOrderSensitivity::Beneficial
364 }
365
366 fn reverse_expr(&self) -> ReversedUDAF {
367 ReversedUDAF::Reversed(last_value_udaf())
368 }
369
370 fn supports_null_handling_clause(&self) -> bool {
371 true
372 }
373
374 fn documentation(&self) -> Option<&Documentation> {
375 self.doc()
376 }
377}
378
379struct FirstLastGroupsAccumulator<S: ValueState> {
380 state: S,
382 orderings: Vec<Vec<ScalarValue>>,
387 is_sets: BooleanBufferBuilder,
390 size_of_orderings: usize,
395
396 extreme_of_each_group_buf: (Vec<usize>, BooleanBufferBuilder),
400
401 ordering_req: LexOrdering,
405 pick_first_in_group: bool,
408 sort_options: Vec<SortOptions>,
410 ignore_nulls: bool,
412 default_orderings: Vec<ScalarValue>,
413}
414
415impl<S: ValueState> FirstLastGroupsAccumulator<S> {
416 fn try_new(
417 state: S,
418 ordering_req: LexOrdering,
419 ignore_nulls: bool,
420 ordering_dtypes: &[DataType],
421 pick_first_in_group: bool,
422 ) -> Result<Self> {
423 let default_orderings = ordering_dtypes
424 .iter()
425 .map(ScalarValue::try_from)
426 .collect::<Result<_>>()?;
427
428 let sort_options = get_sort_options(&ordering_req);
429
430 Ok(Self {
431 ordering_req,
432 sort_options,
433 ignore_nulls,
434 default_orderings,
435 state,
436 orderings: Vec::new(),
437 is_sets: BooleanBufferBuilder::new(0),
438 size_of_orderings: 0,
439 extreme_of_each_group_buf: (Vec::new(), BooleanBufferBuilder::new(0)),
440 pick_first_in_group,
441 })
442 }
443
444 fn should_update_state(
445 &self,
446 group_idx: usize,
447 new_ordering_values: &[ScalarValue],
448 ) -> Result<bool> {
449 if !self.is_sets.get_bit(group_idx) {
450 return Ok(true);
451 }
452
453 debug_assert!(new_ordering_values.len() == self.ordering_req.len());
454 let current_ordering = &self.orderings[group_idx];
455 compare_rows(current_ordering, new_ordering_values, &self.sort_options).map(|x| {
456 if self.pick_first_in_group {
457 x.is_gt()
458 } else {
459 x.is_lt()
460 }
461 })
462 }
463
464 fn take_orderings(&mut self, emit_to: EmitTo) -> Vec<Vec<ScalarValue>> {
465 let result = emit_to.take_needed(&mut self.orderings);
466
467 match emit_to {
468 EmitTo::All => self.size_of_orderings = 0,
469 EmitTo::First(_) => {
470 self.size_of_orderings -=
471 result.iter().map(ScalarValue::size_of_vec).sum::<usize>()
472 }
473 }
474
475 result
476 }
477
478 fn resize_states(&mut self, new_size: usize) {
479 self.state.resize(new_size);
480
481 if self.orderings.len() < new_size {
482 let current_len = self.orderings.len();
483
484 self.orderings
485 .resize(new_size, self.default_orderings.clone());
486
487 self.size_of_orderings += (new_size - current_len)
488 * ScalarValue::size_of_vec(
489 self.orderings.last().unwrap(),
493 );
494 }
495
496 self.is_sets.resize(new_size);
497
498 self.extreme_of_each_group_buf.0.resize(new_size, 0);
499 self.extreme_of_each_group_buf.1.resize(new_size);
500 }
501
502 fn update_state(
503 &mut self,
504 group_idx: usize,
505 orderings: &[ScalarValue],
506 array: &ArrayRef,
507 idx: usize,
508 ) -> Result<()> {
509 self.state.update(group_idx, array, idx)?;
510 self.is_sets.set_bit(group_idx, true);
511
512 debug_assert!(orderings.len() == self.ordering_req.len());
513 let old_size = ScalarValue::size_of_vec(&self.orderings[group_idx]);
514 self.orderings[group_idx].clear();
515 self.orderings[group_idx].extend_from_slice(orderings);
516 let new_size = ScalarValue::size_of_vec(&self.orderings[group_idx]);
517 self.size_of_orderings = self.size_of_orderings - old_size + new_size;
518 Ok(())
519 }
520
521 fn take_state(
522 &mut self,
523 emit_to: EmitTo,
524 ) -> Result<(ArrayRef, Vec<Vec<ScalarValue>>, BooleanBuffer)> {
525 emit_to.take_needed(&mut self.extreme_of_each_group_buf.0);
526 self.extreme_of_each_group_buf
527 .1
528 .truncate(self.extreme_of_each_group_buf.0.len());
529
530 Ok((
531 self.state.take(emit_to)?,
532 self.take_orderings(emit_to),
533 state::take_need(&mut self.is_sets, emit_to),
534 ))
535 }
536
537 #[cfg(test)]
539 fn compute_size_of_orderings(&self) -> usize {
540 self.orderings
541 .iter()
542 .map(ScalarValue::size_of_vec)
543 .sum::<usize>()
544 }
545 fn get_filtered_extreme_of_each_group(
549 &mut self,
550 orderings: &[ArrayRef],
551 group_indices: &[usize],
552 opt_filter: Option<&BooleanArray>,
553 vals: &ArrayRef,
554 is_set_arr: Option<&BooleanArray>,
555 ) -> Result<Vec<(usize, usize)>> {
556 self.extreme_of_each_group_buf.1.truncate(0);
558 self.extreme_of_each_group_buf
559 .1
560 .append_n(self.is_sets.len(), false);
561
562 let comparator = {
566 assert_eq!(orderings.len(), self.ordering_req.len());
567 let sort_columns = orderings
568 .iter()
569 .zip(self.ordering_req.iter())
570 .map(|(array, req)| SortColumn {
571 values: Arc::clone(array),
572 options: Some(req.options),
573 })
574 .collect::<Vec<_>>();
575
576 LexicographicalComparator::try_new(&sort_columns)?
577 };
578
579 for (idx_in_val, group_idx) in group_indices.iter().enumerate() {
580 let group_idx = *group_idx;
581
582 let passed_filter =
585 opt_filter.is_none_or(|x| x.is_valid(idx_in_val) && x.value(idx_in_val));
586 let is_set =
590 is_set_arr.is_none_or(|x| x.is_valid(idx_in_val) && x.value(idx_in_val));
591
592 if !passed_filter || !is_set {
593 continue;
594 }
595
596 if self.ignore_nulls && vals.is_null(idx_in_val) {
597 continue;
598 }
599
600 let is_valid = self.extreme_of_each_group_buf.1.get_bit(group_idx);
601
602 if !is_valid {
603 self.extreme_of_each_group_buf.1.set_bit(group_idx, true);
604 self.extreme_of_each_group_buf.0[group_idx] = idx_in_val;
605 } else {
606 let ordering = comparator
607 .compare(self.extreme_of_each_group_buf.0[group_idx], idx_in_val);
608
609 if (ordering.is_gt() && self.pick_first_in_group)
610 || (ordering.is_lt() && !self.pick_first_in_group)
611 {
612 self.extreme_of_each_group_buf.0[group_idx] = idx_in_val;
613 }
614 }
615 }
616
617 Ok(self
618 .extreme_of_each_group_buf
619 .0
620 .iter()
621 .enumerate()
622 .filter(|(group_idx, _)| self.extreme_of_each_group_buf.1.get_bit(*group_idx))
623 .map(|(group_idx, idx_in_val)| (group_idx, *idx_in_val))
624 .collect::<Vec<_>>())
625 }
626}
627
628impl<S: ValueState + 'static> GroupsAccumulator for FirstLastGroupsAccumulator<S> {
629 fn update_batch(
630 &mut self,
631 values_and_order_cols: &[ArrayRef],
633 group_indices: &[usize],
634 opt_filter: Option<&BooleanArray>,
635 total_num_groups: usize,
636 ) -> Result<()> {
637 self.resize_states(total_num_groups);
638
639 let vals = &values_and_order_cols[0];
640
641 let mut ordering_buf = Vec::with_capacity(self.ordering_req.len());
642
643 for (group_idx, idx) in self
645 .get_filtered_extreme_of_each_group(
646 &values_and_order_cols[1..],
647 group_indices,
648 opt_filter,
649 vals,
650 None,
651 )?
652 .into_iter()
653 {
654 extract_row_at_idx_to_buf(
655 &values_and_order_cols[1..],
656 idx,
657 &mut ordering_buf,
658 )?;
659
660 if self.should_update_state(group_idx, &ordering_buf)? {
661 self.update_state(group_idx, &ordering_buf, vals, idx)?;
662 }
663 }
664
665 Ok(())
666 }
667
668 fn evaluate(&mut self, emit_to: EmitTo) -> Result<ArrayRef> {
669 Ok(self.take_state(emit_to)?.0)
670 }
671
672 fn state(&mut self, emit_to: EmitTo) -> Result<Vec<ArrayRef>> {
673 let (val_arr, orderings, is_sets) = self.take_state(emit_to)?;
674 let mut result = Vec::with_capacity(self.orderings.len() + 2);
675
676 result.push(val_arr);
677
678 let ordering_cols = {
679 let mut ordering_cols = Vec::with_capacity(self.ordering_req.len());
680 for _ in 0..self.ordering_req.len() {
681 ordering_cols.push(Vec::with_capacity(self.orderings.len()));
682 }
683 for row in orderings.into_iter() {
684 debug_assert!(row.len() == self.ordering_req.len());
685 for (col_idx, ordering) in row.into_iter().enumerate() {
686 ordering_cols[col_idx].push(ordering);
687 }
688 }
689
690 ordering_cols
691 };
692 for ordering_col in ordering_cols {
693 result.push(ScalarValue::iter_to_array(ordering_col)?);
694 }
695
696 result.push(Arc::new(BooleanArray::new(is_sets, None)));
697
698 Ok(result)
699 }
700
701 fn merge_batch(
702 &mut self,
703 values: &[ArrayRef],
704 group_indices: &[usize],
705 total_num_groups: usize,
706 ) -> Result<()> {
707 self.resize_states(total_num_groups);
708
709 let mut ordering_buf = Vec::with_capacity(self.ordering_req.len());
710
711 let (is_set_arr, val_and_order_cols) = match values.split_last() {
712 Some(result) => result,
713 None => return internal_err!("Empty row in FIRST_VALUE"),
714 };
715
716 let is_set_arr = as_boolean_array(is_set_arr)?;
717
718 let vals = &values[0];
719 let groups = self.get_filtered_extreme_of_each_group(
721 &val_and_order_cols[1..],
722 group_indices,
723 None,
724 vals,
725 Some(is_set_arr),
726 )?;
727
728 for (group_idx, idx) in groups.into_iter() {
729 extract_row_at_idx_to_buf(&val_and_order_cols[1..], idx, &mut ordering_buf)?;
730
731 if self.should_update_state(group_idx, &ordering_buf)? {
732 self.update_state(group_idx, &ordering_buf, vals, idx)?;
733 }
734 }
735
736 Ok(())
737 }
738
739 fn size(&self) -> usize {
740 self.state.size()
741 + self.is_sets.capacity() / 8 + self.size_of_orderings
743 + self.extreme_of_each_group_buf.0.capacity() * size_of::<usize>()
744 + self.extreme_of_each_group_buf.1.capacity() / 8
745 }
746 fn convert_to_state(
747 &self,
748 values: &[ArrayRef],
749 opt_filter: Option<&BooleanArray>,
750 ) -> Result<Vec<ArrayRef>> {
751 let mut result = values.to_vec();
752 match opt_filter {
753 Some(f) => {
754 result.push(Arc::new(f.clone()));
755 Ok(result)
756 }
757 None => {
758 result.push(Arc::new(BooleanArray::from(vec![true; values[0].len()])));
759 Ok(result)
760 }
761 }
762 }
763}
764
765#[derive(Debug)]
770pub struct TrivialFirstValueAccumulator {
771 first: ScalarValue,
772 is_set: bool,
774 ignore_nulls: bool,
776}
777
778impl TrivialFirstValueAccumulator {
779 pub fn try_new(data_type: &DataType, ignore_nulls: bool) -> Result<Self> {
781 ScalarValue::try_from(data_type).map(|first| Self {
782 first,
783 is_set: false,
784 ignore_nulls,
785 })
786 }
787}
788
789impl Accumulator for TrivialFirstValueAccumulator {
790 fn state(&mut self) -> Result<Vec<ScalarValue>> {
791 Ok(vec![self.first.clone(), ScalarValue::from(self.is_set)])
792 }
793
794 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
795 if !self.is_set {
796 let value = &values[0];
798 let mut first_idx = None;
799 if self.ignore_nulls {
800 for i in 0..value.len() {
802 if !value.is_null(i) {
803 first_idx = Some(i);
804 break;
805 }
806 }
807 } else if !value.is_empty() {
808 first_idx = Some(0);
810 }
811 if let Some(first_idx) = first_idx {
812 self.first = ScalarValue::try_from_array(&values[0], first_idx)?;
813 self.first.compact();
814 self.is_set = true;
815 }
816 }
817 Ok(())
818 }
819
820 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
821 if !self.is_set {
824 let flags = states[1].as_boolean();
825 validate_is_set_flags(flags, "first_value")?;
826
827 let filtered_states =
828 filter_states_according_to_is_set(&states[0..1], flags)?;
829 if let Some(first) = filtered_states.first()
830 && !first.is_empty()
831 {
832 self.first = ScalarValue::try_from_array(first, 0)?;
833 self.is_set = true;
834 }
835 }
836 Ok(())
837 }
838
839 fn evaluate(&mut self) -> Result<ScalarValue> {
840 Ok(self.first.clone())
841 }
842
843 fn size(&self) -> usize {
844 size_of_val(self) - size_of_val(&self.first) + self.first.size()
845 }
846}
847
848#[derive(Debug)]
849pub struct FirstValueAccumulator {
850 first: ScalarValue,
851 is_set: bool,
853 orderings: Vec<ScalarValue>,
856 ordering_req: LexOrdering,
858 sort_options: Vec<SortOptions>,
860 is_input_pre_ordered: bool,
862 ignore_nulls: bool,
864}
865
866impl FirstValueAccumulator {
867 pub fn try_new(
869 data_type: &DataType,
870 ordering_dtypes: &[DataType],
871 ordering_req: LexOrdering,
872 is_input_pre_ordered: bool,
873 ignore_nulls: bool,
874 ) -> Result<Self> {
875 let orderings = ordering_dtypes
876 .iter()
877 .map(ScalarValue::try_from)
878 .collect::<Result<_>>()?;
879 let sort_options = get_sort_options(&ordering_req);
880 ScalarValue::try_from(data_type).map(|first| Self {
881 first,
882 is_set: false,
883 orderings,
884 ordering_req,
885 sort_options,
886 is_input_pre_ordered,
887 ignore_nulls,
888 })
889 }
890
891 fn update_with_new_row(&mut self, mut row: Vec<ScalarValue>) {
893 for s in row.iter_mut() {
895 s.compact();
896 }
897 self.first = row.remove(0);
898 self.orderings = row;
899 self.is_set = true;
900 }
901
902 fn get_first_idx(&self, values: &[ArrayRef]) -> Result<Option<usize>> {
903 let [value, ordering_values @ ..] = values else {
904 return internal_err!("Empty row in FIRST_VALUE");
905 };
906 if self.is_input_pre_ordered {
907 if self.ignore_nulls {
909 for i in 0..value.len() {
911 if !value.is_null(i) {
912 return Ok(Some(i));
913 }
914 }
915 return Ok(None);
916 } else {
917 return Ok((!value.is_empty()).then_some(0));
919 }
920 }
921
922 let sort_columns = ordering_values
923 .iter()
924 .zip(self.ordering_req.iter())
925 .map(|(values, req)| SortColumn {
926 values: Arc::clone(values),
927 options: Some(req.options),
928 })
929 .collect::<Vec<_>>();
930
931 let comparator = LexicographicalComparator::try_new(&sort_columns)?;
932
933 let min_index = if self.ignore_nulls {
934 (0..value.len())
935 .filter(|&index| !value.is_null(index))
936 .min_by(|&a, &b| comparator.compare(a, b))
937 } else {
938 (0..value.len()).min_by(|&a, &b| comparator.compare(a, b))
939 };
940
941 Ok(min_index)
942 }
943}
944
945impl Accumulator for FirstValueAccumulator {
946 fn state(&mut self) -> Result<Vec<ScalarValue>> {
947 let mut result = vec![self.first.clone()];
948 result.extend(self.orderings.iter().cloned());
949 result.push(ScalarValue::from(self.is_set));
950 Ok(result)
951 }
952
953 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
954 if let Some(first_idx) = self.get_first_idx(values)? {
955 let row = get_row_at_idx(values, first_idx)?;
956 if !self.is_set
957 || (!self.is_input_pre_ordered
958 && compare_rows(&self.orderings, &row[1..], &self.sort_options)?
959 .is_gt())
960 {
961 self.update_with_new_row(row);
962 }
963 }
964 Ok(())
965 }
966
967 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
968 let is_set_idx = states.len() - 1;
971 let flags = states[is_set_idx].as_boolean();
972 validate_is_set_flags(flags, "first_value")?;
973
974 let filtered_states =
975 filter_states_according_to_is_set(&states[0..is_set_idx], flags)?;
976 let sort_columns =
978 convert_to_sort_cols(&filtered_states[1..is_set_idx], &self.ordering_req);
979
980 let comparator = LexicographicalComparator::try_new(&sort_columns)?;
981 let min = (0..filtered_states[0].len()).min_by(|&a, &b| comparator.compare(a, b));
982
983 if let Some(first_idx) = min {
984 let mut first_row = get_row_at_idx(&filtered_states, first_idx)?;
985 let first_ordering = &first_row[1..is_set_idx];
987 if !self.is_set
989 || compare_rows(&self.orderings, first_ordering, &self.sort_options)?
990 .is_gt()
991 {
992 assert!(is_set_idx <= first_row.len());
996 first_row.resize(is_set_idx, ScalarValue::Null);
997 self.update_with_new_row(first_row);
998 }
999 }
1000 Ok(())
1001 }
1002
1003 fn evaluate(&mut self) -> Result<ScalarValue> {
1004 Ok(self.first.clone())
1005 }
1006
1007 fn size(&self) -> usize {
1008 size_of_val(self) - size_of_val(&self.first)
1009 + self.first.size()
1010 + ScalarValue::size_of_vec(&self.orderings)
1011 - size_of_val(&self.orderings)
1012 }
1013}
1014
1015#[user_doc(
1016 doc_section(label = "General Functions"),
1017 description = "Returns the last element in an aggregation group according to the requested ordering. If no ordering is given, returns an arbitrary element from the group.",
1018 syntax_example = "last_value(expression [ORDER BY expression])",
1019 sql_example = r#"```sql
1020> SELECT last_value(column_name ORDER BY other_column) FROM table_name;
1021+-----------------------------------------------+
1022| last_value(column_name ORDER BY other_column) |
1023+-----------------------------------------------+
1024| last_element |
1025+-----------------------------------------------+
1026```"#,
1027 standard_argument(name = "expression",)
1028)]
1029#[derive(PartialEq, Eq, Hash, Debug)]
1030pub struct LastValue {
1031 signature: Signature,
1032 is_input_pre_ordered: bool,
1033}
1034
1035impl Default for LastValue {
1036 fn default() -> Self {
1037 Self::new()
1038 }
1039}
1040
1041impl LastValue {
1042 pub fn new() -> Self {
1043 Self {
1044 signature: Signature::any(1, Volatility::Immutable),
1045 is_input_pre_ordered: false,
1046 }
1047 }
1048}
1049
1050impl AggregateUDFImpl for LastValue {
1051 fn name(&self) -> &str {
1052 "last_value"
1053 }
1054
1055 fn signature(&self) -> &Signature {
1056 &self.signature
1057 }
1058
1059 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
1060 not_impl_err!("Not called because the return_field_from_args is implemented")
1061 }
1062
1063 fn return_field(&self, arg_fields: &[FieldRef]) -> Result<FieldRef> {
1064 Ok(Arc::new(
1066 Field::new(
1067 self.name(),
1068 arg_fields[0].data_type().clone(),
1069 true, )
1071 .with_metadata(arg_fields[0].metadata().clone()),
1072 ))
1073 }
1074
1075 fn accumulator(&self, acc_args: AccumulatorArgs) -> Result<Box<dyn Accumulator>> {
1076 let Some(ordering) = LexOrdering::new(acc_args.order_bys.to_vec()) else {
1077 return TrivialLastValueAccumulator::try_new(
1078 acc_args.return_field.data_type(),
1079 acc_args.ignore_nulls,
1080 )
1081 .map(|acc| Box::new(acc) as _);
1082 };
1083 let ordering_dtypes = ordering
1084 .iter()
1085 .map(|e| e.expr.data_type(acc_args.schema))
1086 .collect::<Result<Vec<_>>>()?;
1087 Ok(Box::new(LastValueAccumulator::try_new(
1088 acc_args.return_field.data_type(),
1089 &ordering_dtypes,
1090 ordering,
1091 self.is_input_pre_ordered,
1092 acc_args.ignore_nulls,
1093 )?))
1094 }
1095
1096 fn state_fields(&self, args: StateFieldsArgs) -> Result<Vec<FieldRef>> {
1097 let mut fields = vec![
1098 Field::new(
1099 format_state_name(args.name, "last_value"),
1100 args.return_field.data_type().clone(),
1101 true,
1102 )
1103 .into(),
1104 ];
1105 fields.extend(args.ordering_fields.iter().cloned());
1106 fields.push(
1107 Field::new(
1108 format_state_name(args.name, "last_value_is_set"),
1109 DataType::Boolean,
1110 true,
1111 )
1112 .into(),
1113 );
1114 Ok(fields)
1115 }
1116
1117 fn with_beneficial_ordering(
1118 self: Arc<Self>,
1119 beneficial_ordering: bool,
1120 ) -> Result<Option<Arc<dyn AggregateUDFImpl>>> {
1121 Ok(Some(Arc::new(Self {
1122 signature: self.signature.clone(),
1123 is_input_pre_ordered: beneficial_ordering,
1124 })))
1125 }
1126
1127 fn order_sensitivity(&self) -> AggregateOrderSensitivity {
1128 AggregateOrderSensitivity::Beneficial
1129 }
1130
1131 fn reverse_expr(&self) -> ReversedUDAF {
1132 ReversedUDAF::Reversed(first_value_udaf())
1133 }
1134
1135 fn supports_null_handling_clause(&self) -> bool {
1136 true
1137 }
1138
1139 fn documentation(&self) -> Option<&Documentation> {
1140 self.doc()
1141 }
1142
1143 fn groups_accumulator_supported(&self, args: AccumulatorArgs) -> bool {
1144 groups_accumulator_supported(&args)
1145 }
1146
1147 fn create_groups_accumulator(
1148 &self,
1149 args: AccumulatorArgs,
1150 ) -> Result<Box<dyn GroupsAccumulator>> {
1151 create_groups_accumulator(&args, false, self.name())
1152 }
1153}
1154
1155#[derive(Debug)]
1160pub struct TrivialLastValueAccumulator {
1161 last: ScalarValue,
1162 is_set: bool,
1166 ignore_nulls: bool,
1168}
1169
1170impl TrivialLastValueAccumulator {
1171 pub fn try_new(data_type: &DataType, ignore_nulls: bool) -> Result<Self> {
1173 ScalarValue::try_from(data_type).map(|last| Self {
1174 last,
1175 is_set: false,
1176 ignore_nulls,
1177 })
1178 }
1179}
1180
1181impl Accumulator for TrivialLastValueAccumulator {
1182 fn state(&mut self) -> Result<Vec<ScalarValue>> {
1183 Ok(vec![self.last.clone(), ScalarValue::from(self.is_set)])
1184 }
1185
1186 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
1187 let value = &values[0];
1189 let mut last_idx = None;
1190 if self.ignore_nulls {
1191 for i in (0..value.len()).rev() {
1193 if !value.is_null(i) {
1194 last_idx = Some(i);
1195 break;
1196 }
1197 }
1198 } else if !value.is_empty() {
1199 last_idx = Some(value.len() - 1);
1201 }
1202 if let Some(last_idx) = last_idx {
1203 self.last = ScalarValue::try_from_array(&values[0], last_idx)?;
1204 self.last.compact();
1205 self.is_set = true;
1206 }
1207 Ok(())
1208 }
1209
1210 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
1211 let flags = states[1].as_boolean();
1214 validate_is_set_flags(flags, "last_value")?;
1215
1216 let filtered_states = filter_states_according_to_is_set(&states[0..1], flags)?;
1217 if let Some(last) = filtered_states.last()
1218 && !last.is_empty()
1219 {
1220 self.last = ScalarValue::try_from_array(last, last.len() - 1)?;
1221 self.is_set = true;
1222 }
1223 Ok(())
1224 }
1225
1226 fn evaluate(&mut self) -> Result<ScalarValue> {
1227 Ok(self.last.clone())
1228 }
1229
1230 fn size(&self) -> usize {
1231 size_of_val(self) - size_of_val(&self.last) + self.last.size()
1232 }
1233}
1234
1235#[derive(Debug)]
1236struct LastValueAccumulator {
1237 last: ScalarValue,
1238 is_set: bool,
1242 orderings: Vec<ScalarValue>,
1245 ordering_req: LexOrdering,
1247 sort_options: Vec<SortOptions>,
1249 is_input_pre_ordered: bool,
1251 ignore_nulls: bool,
1253}
1254
1255impl LastValueAccumulator {
1256 pub fn try_new(
1258 data_type: &DataType,
1259 ordering_dtypes: &[DataType],
1260 ordering_req: LexOrdering,
1261 is_input_pre_ordered: bool,
1262 ignore_nulls: bool,
1263 ) -> Result<Self> {
1264 let orderings = ordering_dtypes
1265 .iter()
1266 .map(ScalarValue::try_from)
1267 .collect::<Result<_>>()?;
1268 let sort_options = get_sort_options(&ordering_req);
1269 ScalarValue::try_from(data_type).map(|last| Self {
1270 last,
1271 is_set: false,
1272 orderings,
1273 ordering_req,
1274 sort_options,
1275 is_input_pre_ordered,
1276 ignore_nulls,
1277 })
1278 }
1279
1280 fn update_with_new_row(&mut self, mut row: Vec<ScalarValue>) {
1282 for s in row.iter_mut() {
1284 s.compact();
1285 }
1286 self.last = row.remove(0);
1287 self.orderings = row;
1288 self.is_set = true;
1289 }
1290
1291 fn get_last_idx(&self, values: &[ArrayRef]) -> Result<Option<usize>> {
1292 let [value, ordering_values @ ..] = values else {
1293 return internal_err!("Empty row in LAST_VALUE");
1294 };
1295 if self.is_input_pre_ordered {
1296 if self.ignore_nulls {
1298 for i in (0..value.len()).rev() {
1300 if !value.is_null(i) {
1301 return Ok(Some(i));
1302 }
1303 }
1304 return Ok(None);
1305 } else {
1306 return Ok((!value.is_empty()).then_some(value.len() - 1));
1307 }
1308 }
1309
1310 let sort_columns = ordering_values
1311 .iter()
1312 .zip(self.ordering_req.iter())
1313 .map(|(values, req)| SortColumn {
1314 values: Arc::clone(values),
1315 options: Some(req.options),
1316 })
1317 .collect::<Vec<_>>();
1318
1319 let comparator = LexicographicalComparator::try_new(&sort_columns)?;
1320 let max_ind = if self.ignore_nulls {
1321 (0..value.len())
1322 .filter(|&index| !(value.is_null(index)))
1323 .max_by(|&a, &b| comparator.compare(a, b))
1324 } else {
1325 (0..value.len()).max_by(|&a, &b| comparator.compare(a, b))
1326 };
1327
1328 Ok(max_ind)
1329 }
1330}
1331
1332impl Accumulator for LastValueAccumulator {
1333 fn state(&mut self) -> Result<Vec<ScalarValue>> {
1334 let mut result = vec![self.last.clone()];
1335 result.extend(self.orderings.clone());
1336 result.push(ScalarValue::from(self.is_set));
1337 Ok(result)
1338 }
1339
1340 fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
1341 if let Some(last_idx) = self.get_last_idx(values)? {
1342 let row = get_row_at_idx(values, last_idx)?;
1343 let orderings = &row[1..];
1344 if !self.is_set
1346 || self.is_input_pre_ordered
1347 || compare_rows(&self.orderings, orderings, &self.sort_options)?.is_lt()
1348 {
1349 self.update_with_new_row(row);
1350 }
1351 }
1352 Ok(())
1353 }
1354
1355 fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
1356 let is_set_idx = states.len() - 1;
1359 let flags = states[is_set_idx].as_boolean();
1360 validate_is_set_flags(flags, "last_value")?;
1361
1362 let filtered_states =
1363 filter_states_according_to_is_set(&states[0..is_set_idx], flags)?;
1364 let sort_columns =
1366 convert_to_sort_cols(&filtered_states[1..is_set_idx], &self.ordering_req);
1367
1368 let comparator = LexicographicalComparator::try_new(&sort_columns)?;
1369 let max = (0..filtered_states[0].len()).max_by(|&a, &b| comparator.compare(a, b));
1370
1371 if let Some(last_idx) = max {
1372 let mut last_row = get_row_at_idx(&filtered_states, last_idx)?;
1373 let last_ordering = &last_row[1..is_set_idx];
1375 if !self.is_set
1378 || self.is_input_pre_ordered
1379 || compare_rows(&self.orderings, last_ordering, &self.sort_options)?
1380 .is_lt()
1381 {
1382 assert!(is_set_idx <= last_row.len());
1386 last_row.resize(is_set_idx, ScalarValue::Null);
1387 self.update_with_new_row(last_row);
1388 }
1389 }
1390 Ok(())
1391 }
1392
1393 fn evaluate(&mut self) -> Result<ScalarValue> {
1394 Ok(self.last.clone())
1395 }
1396
1397 fn size(&self) -> usize {
1398 size_of_val(self) - size_of_val(&self.last)
1399 + self.last.size()
1400 + ScalarValue::size_of_vec(&self.orderings)
1401 - size_of_val(&self.orderings)
1402 }
1403}
1404
1405fn validate_is_set_flags(flags: &BooleanArray, function_name: &str) -> Result<()> {
1407 if flags.null_count() > 0 {
1408 return Err(DataFusionError::Internal(format!(
1409 "{function_name}: is_set flags contain nulls"
1410 )));
1411 }
1412 Ok(())
1413}
1414
1415fn filter_states_according_to_is_set(
1418 states: &[ArrayRef],
1419 flags: &BooleanArray,
1420) -> Result<Vec<ArrayRef>> {
1421 states
1422 .iter()
1423 .map(|state| compute::filter(state, flags).map_err(|e| arrow_datafusion_err!(e)))
1424 .collect()
1425}
1426
1427fn convert_to_sort_cols(arrs: &[ArrayRef], sort_exprs: &LexOrdering) -> Vec<SortColumn> {
1429 arrs.iter()
1430 .zip(sort_exprs.iter())
1431 .map(|(item, sort_expr)| SortColumn {
1432 values: Arc::clone(item),
1433 options: Some(sort_expr.options),
1434 })
1435 .collect()
1436}
1437
1438#[cfg(test)]
1439mod tests {
1440 use std::iter::repeat_with;
1441
1442 use arrow::{
1443 array::{BooleanArray, Int64Array, ListArray, PrimitiveArray, StringArray},
1444 buffer::NullBuffer,
1445 compute::SortOptions,
1446 datatypes::Schema,
1447 };
1448 use datafusion_physical_expr::{PhysicalSortExpr, expressions::col};
1449
1450 use super::*;
1451
1452 #[test]
1453 fn test_first_last_value_value() -> Result<()> {
1454 let mut first_accumulator =
1455 TrivialFirstValueAccumulator::try_new(&DataType::Int64, false)?;
1456 let mut last_accumulator =
1457 TrivialLastValueAccumulator::try_new(&DataType::Int64, false)?;
1458 let ranges: Vec<(i64, i64)> = vec![(0, 10), (1, 11), (2, 13)];
1461 let arrs = ranges
1463 .into_iter()
1464 .map(|(start, end)| {
1465 Arc::new(Int64Array::from((start..end).collect::<Vec<_>>())) as ArrayRef
1466 })
1467 .collect::<Vec<_>>();
1468 for arr in arrs {
1469 first_accumulator.update_batch(&[Arc::clone(&arr)])?;
1472 last_accumulator.update_batch(&[arr])?;
1474 }
1475 assert_eq!(first_accumulator.evaluate()?, ScalarValue::Int64(Some(0)));
1477 assert_eq!(last_accumulator.evaluate()?, ScalarValue::Int64(Some(12)));
1479 Ok(())
1480 }
1481
1482 #[test]
1483 fn test_first_last_state_after_merge() -> Result<()> {
1484 let ranges: Vec<(i64, i64)> = vec![(0, 10), (1, 11), (2, 13)];
1485 let arrs = ranges
1487 .into_iter()
1488 .map(|(start, end)| {
1489 Arc::new((start..end).collect::<Int64Array>()) as ArrayRef
1490 })
1491 .collect::<Vec<_>>();
1492
1493 let mut first_accumulator =
1495 TrivialFirstValueAccumulator::try_new(&DataType::Int64, false)?;
1496
1497 first_accumulator.update_batch(&[Arc::clone(&arrs[0])])?;
1498 let state1 = first_accumulator.state()?;
1499
1500 let mut first_accumulator =
1501 TrivialFirstValueAccumulator::try_new(&DataType::Int64, false)?;
1502 first_accumulator.update_batch(&[Arc::clone(&arrs[1])])?;
1503 let state2 = first_accumulator.state()?;
1504
1505 assert_eq!(state1.len(), state2.len());
1506
1507 let mut states = vec![];
1508
1509 for idx in 0..state1.len() {
1510 states.push(compute::concat(&[
1511 &state1[idx].to_array()?,
1512 &state2[idx].to_array()?,
1513 ])?);
1514 }
1515
1516 let mut first_accumulator =
1517 TrivialFirstValueAccumulator::try_new(&DataType::Int64, false)?;
1518 first_accumulator.merge_batch(&states)?;
1519
1520 let merged_state = first_accumulator.state()?;
1521 assert_eq!(merged_state.len(), state1.len());
1522
1523 let mut last_accumulator =
1525 TrivialLastValueAccumulator::try_new(&DataType::Int64, false)?;
1526
1527 last_accumulator.update_batch(&[Arc::clone(&arrs[0])])?;
1528 let state1 = last_accumulator.state()?;
1529
1530 let mut last_accumulator =
1531 TrivialLastValueAccumulator::try_new(&DataType::Int64, false)?;
1532 last_accumulator.update_batch(&[Arc::clone(&arrs[1])])?;
1533 let state2 = last_accumulator.state()?;
1534
1535 assert_eq!(state1.len(), state2.len());
1536
1537 let mut states = vec![];
1538
1539 for idx in 0..state1.len() {
1540 states.push(compute::concat(&[
1541 &state1[idx].to_array()?,
1542 &state2[idx].to_array()?,
1543 ])?);
1544 }
1545
1546 let mut last_accumulator =
1547 TrivialLastValueAccumulator::try_new(&DataType::Int64, false)?;
1548 last_accumulator.merge_batch(&states)?;
1549
1550 let merged_state = last_accumulator.state()?;
1551 assert_eq!(merged_state.len(), state1.len());
1552 assert_eq!(last_accumulator.evaluate()?, ScalarValue::Int64(Some(10)));
1553
1554 Ok(())
1555 }
1556
1557 #[test]
1558 fn test_trivial_last_value_merge_all_flags_false() -> Result<()> {
1559 let mut acc = TrivialLastValueAccumulator::try_new(&DataType::Int64, false)?;
1560 let states: Vec<ArrayRef> = vec![
1561 Arc::new(Int64Array::from(vec![None, None])),
1562 Arc::new(BooleanArray::from(vec![false, false])),
1563 ];
1564
1565 acc.merge_batch(&states)?;
1566 assert_eq!(acc.evaluate()?, ScalarValue::Int64(None));
1567 Ok(())
1568 }
1569
1570 #[test]
1571 fn test_first_group_acc() -> Result<()> {
1572 let schema = Arc::new(Schema::new(vec![
1573 Field::new("a", DataType::Int64, true),
1574 Field::new("b", DataType::Int64, true),
1575 Field::new("c", DataType::Int64, true),
1576 Field::new("d", DataType::Int32, true),
1577 Field::new("e", DataType::Boolean, true),
1578 ]));
1579
1580 let sort_keys = [PhysicalSortExpr {
1581 expr: col("c", &schema).unwrap(),
1582 options: SortOptions::default(),
1583 }];
1584
1585 let mut group_acc = FirstLastGroupsAccumulator::try_new(
1586 PrimitiveValueState::<Int64Type>::new(DataType::Int64),
1587 sort_keys.into(),
1588 true,
1589 &[DataType::Int64],
1590 true,
1591 )?;
1592
1593 let mut val_with_orderings = {
1594 let mut val_with_orderings = Vec::<ArrayRef>::new();
1595
1596 let vals = Arc::new(Int64Array::from(vec![Some(1), None, Some(3), Some(-6)]));
1597 let orderings = Arc::new(Int64Array::from(vec![1, -9, 3, -6]));
1598
1599 val_with_orderings.push(vals);
1600 val_with_orderings.push(orderings);
1601
1602 val_with_orderings
1603 };
1604
1605 group_acc.update_batch(
1606 &val_with_orderings,
1607 &[0, 1, 2, 1],
1608 Some(&BooleanArray::from(vec![true, true, false, true])),
1609 3,
1610 )?;
1611 assert_eq!(
1612 group_acc.size_of_orderings,
1613 group_acc.compute_size_of_orderings()
1614 );
1615
1616 let state = group_acc.state(EmitTo::All)?;
1617
1618 let expected_state: Vec<Arc<dyn Array>> = vec![
1619 Arc::new(Int64Array::from(vec![Some(1), Some(-6), None])),
1620 Arc::new(Int64Array::from(vec![Some(1), Some(-6), None])),
1621 Arc::new(BooleanArray::from(vec![true, true, false])),
1622 ];
1623 assert_eq!(state, expected_state);
1624
1625 assert_eq!(
1626 group_acc.size_of_orderings,
1627 group_acc.compute_size_of_orderings()
1628 );
1629
1630 group_acc.merge_batch(&state, &[0, 1, 2], 3)?;
1631
1632 assert_eq!(
1633 group_acc.size_of_orderings,
1634 group_acc.compute_size_of_orderings()
1635 );
1636
1637 val_with_orderings.clear();
1638 val_with_orderings.push(Arc::new(Int64Array::from(vec![6, 6])));
1639 val_with_orderings.push(Arc::new(Int64Array::from(vec![6, 6])));
1640
1641 group_acc.update_batch(&val_with_orderings, &[1, 2], None, 4)?;
1642
1643 let binding = group_acc.evaluate(EmitTo::All)?;
1644 let eval_result = binding.as_any().downcast_ref::<Int64Array>().unwrap();
1645
1646 let expect: PrimitiveArray<Int64Type> =
1650 Int64Array::from(vec![Some(1), Some(-6), Some(6), None]);
1651
1652 assert_eq!(eval_result, &expect);
1653
1654 assert_eq!(
1655 group_acc.size_of_orderings,
1656 group_acc.compute_size_of_orderings()
1657 );
1658
1659 Ok(())
1660 }
1661
1662 #[test]
1663 fn test_group_acc_size_of_ordering() -> Result<()> {
1664 let schema = Arc::new(Schema::new(vec![
1665 Field::new("a", DataType::Int64, true),
1666 Field::new("b", DataType::Int64, true),
1667 Field::new("c", DataType::Int64, true),
1668 Field::new("d", DataType::Int32, true),
1669 Field::new("e", DataType::Boolean, true),
1670 ]));
1671
1672 let sort_keys = [PhysicalSortExpr {
1673 expr: col("c", &schema).unwrap(),
1674 options: SortOptions::default(),
1675 }];
1676
1677 let mut group_acc = FirstLastGroupsAccumulator::try_new(
1678 PrimitiveValueState::<Int64Type>::new(DataType::Int64),
1679 sort_keys.into(),
1680 true,
1681 &[DataType::Int64],
1682 true,
1683 )?;
1684
1685 let val_with_orderings = {
1686 let mut val_with_orderings = Vec::<ArrayRef>::new();
1687
1688 let vals = Arc::new(Int64Array::from(vec![Some(1), None, Some(3), Some(-6)]));
1689 let orderings = Arc::new(Int64Array::from(vec![1, -9, 3, -6]));
1690
1691 val_with_orderings.push(vals);
1692 val_with_orderings.push(orderings);
1693
1694 val_with_orderings
1695 };
1696
1697 for _ in 0..10 {
1698 group_acc.update_batch(
1699 &val_with_orderings,
1700 &[0, 1, 2, 1],
1701 Some(&BooleanArray::from(vec![true, true, false, true])),
1702 100,
1703 )?;
1704 assert_eq!(
1705 group_acc.size_of_orderings,
1706 group_acc.compute_size_of_orderings()
1707 );
1708
1709 group_acc.state(EmitTo::First(2))?;
1710 assert_eq!(
1711 group_acc.size_of_orderings,
1712 group_acc.compute_size_of_orderings()
1713 );
1714
1715 let s = group_acc.state(EmitTo::All)?;
1716 assert_eq!(
1717 group_acc.size_of_orderings,
1718 group_acc.compute_size_of_orderings()
1719 );
1720
1721 group_acc.merge_batch(&s, &Vec::from_iter(0..s[0].len()), 100)?;
1722 assert_eq!(
1723 group_acc.size_of_orderings,
1724 group_acc.compute_size_of_orderings()
1725 );
1726
1727 group_acc.evaluate(EmitTo::First(2))?;
1728 assert_eq!(
1729 group_acc.size_of_orderings,
1730 group_acc.compute_size_of_orderings()
1731 );
1732
1733 group_acc.evaluate(EmitTo::All)?;
1734 assert_eq!(
1735 group_acc.size_of_orderings,
1736 group_acc.compute_size_of_orderings()
1737 );
1738 }
1739
1740 Ok(())
1741 }
1742
1743 #[test]
1744 fn test_last_group_acc() -> Result<()> {
1745 let schema = Arc::new(Schema::new(vec![
1746 Field::new("a", DataType::Int64, true),
1747 Field::new("b", DataType::Int64, true),
1748 Field::new("c", DataType::Int64, true),
1749 Field::new("d", DataType::Int32, true),
1750 Field::new("e", DataType::Boolean, true),
1751 ]));
1752
1753 let sort_keys = [PhysicalSortExpr {
1754 expr: col("c", &schema).unwrap(),
1755 options: SortOptions::default(),
1756 }];
1757
1758 let mut group_acc = FirstLastGroupsAccumulator::try_new(
1759 PrimitiveValueState::<Int64Type>::new(DataType::Int64),
1760 sort_keys.into(),
1761 true,
1762 &[DataType::Int64],
1763 false,
1764 )?;
1765
1766 let mut val_with_orderings = {
1767 let mut val_with_orderings = Vec::<ArrayRef>::new();
1768
1769 let vals = Arc::new(Int64Array::from(vec![Some(1), None, Some(3), Some(-6)]));
1770 let orderings = Arc::new(Int64Array::from(vec![1, -9, 3, -6]));
1771
1772 val_with_orderings.push(vals);
1773 val_with_orderings.push(orderings);
1774
1775 val_with_orderings
1776 };
1777
1778 group_acc.update_batch(
1779 &val_with_orderings,
1780 &[0, 1, 2, 1],
1781 Some(&BooleanArray::from(vec![true, true, false, true])),
1782 3,
1783 )?;
1784
1785 let state = group_acc.state(EmitTo::All)?;
1786
1787 let expected_state: Vec<Arc<dyn Array>> = vec![
1788 Arc::new(Int64Array::from(vec![Some(1), Some(-6), None])),
1789 Arc::new(Int64Array::from(vec![Some(1), Some(-6), None])),
1790 Arc::new(BooleanArray::from(vec![true, true, false])),
1791 ];
1792 assert_eq!(state, expected_state);
1793
1794 group_acc.merge_batch(&state, &[0, 1, 2], 3)?;
1795
1796 val_with_orderings.clear();
1797 val_with_orderings.push(Arc::new(Int64Array::from(vec![66, 6])));
1798 val_with_orderings.push(Arc::new(Int64Array::from(vec![66, 6])));
1799
1800 group_acc.update_batch(&val_with_orderings, &[1, 2], None, 4)?;
1801
1802 let binding = group_acc.evaluate(EmitTo::All)?;
1803 let eval_result = binding.as_any().downcast_ref::<Int64Array>().unwrap();
1804
1805 let expect: PrimitiveArray<Int64Type> =
1810 Int64Array::from(vec![Some(1), Some(66), Some(6), None]);
1811
1812 assert_eq!(eval_result, &expect);
1813
1814 Ok(())
1815 }
1816
1817 #[test]
1821 fn test_group_acc_filter_null_predicate() -> Result<()> {
1822 let schema = Arc::new(Schema::new(vec![
1823 Field::new("a", DataType::Int64, true),
1824 Field::new("c", DataType::Int64, true),
1825 ]));
1826
1827 let sort_keys = [PhysicalSortExpr {
1828 expr: col("c", &schema).unwrap(),
1829 options: SortOptions::default(),
1830 }];
1831
1832 let mut group_acc = FirstLastGroupsAccumulator::try_new(
1833 PrimitiveValueState::<Int64Type>::new(DataType::Int64),
1834 sort_keys.into(),
1835 true,
1836 &[DataType::Int64],
1837 true,
1838 )?;
1839
1840 let val_with_orderings: Vec<ArrayRef> = vec![
1841 Arc::new(Int64Array::from(vec![10, 20, 30])),
1842 Arc::new(Int64Array::from(vec![10, 20, 30])),
1843 ];
1844
1845 let filter = BooleanArray::new(
1850 BooleanBuffer::from(vec![false, true, false, true]),
1851 Some(NullBuffer::from(BooleanBuffer::from(vec![
1852 true, false, true, true,
1853 ]))),
1854 )
1855 .slice(1, 3);
1856 assert_eq!(filter.offset(), 1);
1857
1858 group_acc.update_batch(&val_with_orderings, &[0, 0, 1], Some(&filter), 2)?;
1859
1860 let binding = group_acc.evaluate(EmitTo::All)?;
1861 let eval_result = binding.as_any().downcast_ref::<Int64Array>().unwrap();
1862
1863 let expect: PrimitiveArray<Int64Type> = Int64Array::from(vec![None, Some(30)]);
1866 assert_eq!(eval_result, &expect);
1867
1868 Ok(())
1869 }
1870
1871 #[test]
1875 fn test_group_acc_merge_null_is_set() -> Result<()> {
1876 let schema = Arc::new(Schema::new(vec![
1877 Field::new("a", DataType::Int64, true),
1878 Field::new("c", DataType::Int64, true),
1879 ]));
1880
1881 let sort_keys = [PhysicalSortExpr {
1882 expr: col("c", &schema).unwrap(),
1883 options: SortOptions::default(),
1884 }];
1885
1886 let group_acc = FirstLastGroupsAccumulator::try_new(
1887 PrimitiveValueState::<Int64Type>::new(DataType::Int64),
1888 sort_keys.clone().into(),
1889 true,
1890 &[DataType::Int64],
1891 true,
1892 )?;
1893
1894 let val_with_orderings: Vec<ArrayRef> = vec![
1895 Arc::new(Int64Array::from(vec![10, 20])),
1896 Arc::new(Int64Array::from(vec![10, 20])),
1897 ];
1898
1899 let filter = BooleanArray::new(
1901 BooleanBuffer::from(vec![true, true]),
1902 Some(NullBuffer::from(BooleanBuffer::from(vec![false, true]))),
1903 );
1904
1905 let state = group_acc.convert_to_state(&val_with_orderings, Some(&filter))?;
1906 assert_eq!(state.len(), 3);
1907
1908 let mut merging_acc = FirstLastGroupsAccumulator::try_new(
1909 PrimitiveValueState::<Int64Type>::new(DataType::Int64),
1910 sort_keys.into(),
1911 true,
1912 &[DataType::Int64],
1913 true,
1914 )?;
1915
1916 merging_acc.merge_batch(&state, &[0, 0], 1)?;
1917
1918 let binding = merging_acc.evaluate(EmitTo::All)?;
1919 let eval_result = binding.as_any().downcast_ref::<Int64Array>().unwrap();
1920
1921 let expect: PrimitiveArray<Int64Type> = Int64Array::from(vec![Some(20)]);
1924 assert_eq!(eval_result, &expect);
1925
1926 Ok(())
1927 }
1928
1929 #[test]
1930 fn test_first_list_acc_size() -> Result<()> {
1931 fn size_after_batch(values: &[ArrayRef]) -> Result<usize> {
1932 let mut first_accumulator = TrivialFirstValueAccumulator::try_new(
1933 &DataType::List(Arc::new(Field::new_list_field(DataType::Int64, false))),
1934 false,
1935 )?;
1936
1937 first_accumulator.update_batch(values)?;
1938
1939 Ok(first_accumulator.size())
1940 }
1941
1942 let batch1 = ListArray::from_iter_primitive::<Int32Type, _, _>(
1943 repeat_with(|| Some(vec![Some(1)])).take(10000),
1944 );
1945 let batch2 =
1946 ListArray::from_iter_primitive::<Int32Type, _, _>([Some(vec![Some(1)])]);
1947
1948 let size1 = size_after_batch(&[Arc::new(batch1)])?;
1949 let size2 = size_after_batch(&[Arc::new(batch2)])?;
1950 assert_eq!(size1, size2);
1951
1952 Ok(())
1953 }
1954
1955 #[test]
1956 fn test_last_list_acc_size() -> Result<()> {
1957 fn size_after_batch(values: &[ArrayRef]) -> Result<usize> {
1958 let mut last_accumulator = TrivialLastValueAccumulator::try_new(
1959 &DataType::List(Arc::new(Field::new_list_field(DataType::Int64, false))),
1960 false,
1961 )?;
1962
1963 last_accumulator.update_batch(values)?;
1964
1965 Ok(last_accumulator.size())
1966 }
1967
1968 let batch1 = ListArray::from_iter_primitive::<Int32Type, _, _>(
1969 repeat_with(|| Some(vec![Some(1)])).take(10000),
1970 );
1971 let batch2 =
1972 ListArray::from_iter_primitive::<Int32Type, _, _>([Some(vec![Some(1)])]);
1973
1974 let size1 = size_after_batch(&[Arc::new(batch1)])?;
1975 let size2 = size_after_batch(&[Arc::new(batch2)])?;
1976 assert_eq!(size1, size2);
1977
1978 Ok(())
1979 }
1980
1981 #[test]
1982 fn test_first_value_merge_with_is_set_nulls() -> Result<()> {
1983 let value = Arc::new(StringArray::from(vec![Some("first_string")])) as ArrayRef;
1985 let corrupted_flag = Arc::new(BooleanArray::from(vec![None])) as ArrayRef;
1986
1987 let mut trivial_accumulator =
1989 TrivialFirstValueAccumulator::try_new(&DataType::Utf8, false)?;
1990 let trivial_states = vec![Arc::clone(&value), Arc::clone(&corrupted_flag)];
1991 let result = trivial_accumulator.merge_batch(&trivial_states);
1992 assert!(result.is_err());
1993 assert!(
1994 result
1995 .unwrap_err()
1996 .to_string()
1997 .contains("is_set flags contain nulls")
1998 );
1999
2000 let schema = Schema::new(vec![Field::new("ordering", DataType::Int64, false)]);
2002 let ordering_expr = col("ordering", &schema)?;
2003 let mut ordered_accumulator = FirstValueAccumulator::try_new(
2004 &DataType::Utf8,
2005 &[DataType::Int64],
2006 LexOrdering::new(vec![PhysicalSortExpr {
2007 expr: ordering_expr,
2008 options: SortOptions::default(),
2009 }])
2010 .unwrap(),
2011 false,
2012 false,
2013 )?;
2014 let ordering = Arc::new(Int64Array::from(vec![Some(1)])) as ArrayRef;
2015 let ordered_states = vec![value, ordering, corrupted_flag];
2016 let result = ordered_accumulator.merge_batch(&ordered_states);
2017 assert!(result.is_err());
2018 assert!(
2019 result
2020 .unwrap_err()
2021 .to_string()
2022 .contains("is_set flags contain nulls")
2023 );
2024
2025 Ok(())
2026 }
2027
2028 #[test]
2029 fn test_last_value_merge_with_is_set_nulls() -> Result<()> {
2030 let value = Arc::new(StringArray::from(vec![Some("last_string")])) as ArrayRef;
2032 let corrupted_flag = Arc::new(BooleanArray::from(vec![None])) as ArrayRef;
2033
2034 let mut trivial_accumulator =
2036 TrivialLastValueAccumulator::try_new(&DataType::Utf8, false)?;
2037 let trivial_states = vec![Arc::clone(&value), Arc::clone(&corrupted_flag)];
2038 let result = trivial_accumulator.merge_batch(&trivial_states);
2039 assert!(result.is_err());
2040 assert!(
2041 result
2042 .unwrap_err()
2043 .to_string()
2044 .contains("is_set flags contain nulls")
2045 );
2046
2047 let schema = Schema::new(vec![Field::new("ordering", DataType::Int64, false)]);
2049 let ordering_expr = col("ordering", &schema)?;
2050 let mut ordered_accumulator = LastValueAccumulator::try_new(
2051 &DataType::Utf8,
2052 &[DataType::Int64],
2053 LexOrdering::new(vec![PhysicalSortExpr {
2054 expr: ordering_expr,
2055 options: SortOptions::default(),
2056 }])
2057 .unwrap(),
2058 false,
2059 false,
2060 )?;
2061 let ordering = Arc::new(Int64Array::from(vec![Some(1)])) as ArrayRef;
2062 let ordered_states = vec![value, ordering, corrupted_flag];
2063 let result = ordered_accumulator.merge_batch(&ordered_states);
2064 assert!(result.is_err());
2065 assert!(
2066 result
2067 .unwrap_err()
2068 .to_string()
2069 .contains("is_set flags contain nulls")
2070 );
2071
2072 Ok(())
2073 }
2074
2075 #[test]
2087 fn test_first_group_acc_list_int32() -> Result<()> {
2088 let value_type =
2089 DataType::List(Arc::new(Field::new("item", DataType::Int32, true)));
2090 let schema = Arc::new(Schema::new(vec![
2091 Field::new("val", value_type.clone(), true),
2092 Field::new("ord", DataType::Int64, true),
2093 ]));
2094 let sort_keys = [PhysicalSortExpr {
2095 expr: col("ord", &schema)?,
2096 options: SortOptions {
2097 descending: true,
2098 nulls_first: false,
2099 },
2100 }];
2101
2102 let mut group_acc = FirstLastGroupsAccumulator::try_new(
2103 GenericValueState::new(value_type.clone()),
2104 sort_keys.into(),
2105 false,
2106 &[DataType::Int64],
2107 true,
2108 )?;
2109
2110 let values_1 = ListArray::from_iter_primitive::<Int32Type, _, _>([
2115 Some(vec![Some(1)]),
2116 Some(vec![Some(2), Some(2)]),
2117 Some(vec![Some(3), Some(3), Some(3)]),
2118 Some(vec![Some(4), Some(4), Some(4), Some(4)]),
2119 ]);
2120 let orderings_1 = Int64Array::from(vec![10, 20, 30, 40]);
2121 group_acc.update_batch(
2122 &[
2123 Arc::new(values_1) as ArrayRef,
2124 Arc::new(orderings_1) as ArrayRef,
2125 ],
2126 &[0, 1, 0, 1],
2127 None,
2128 2,
2129 )?;
2130
2131 let values_2 = ListArray::from_iter_primitive::<Int32Type, _, _>([
2134 Some(vec![Some(9), Some(9)]),
2135 Some(vec![Some(8)]),
2136 ]);
2137 let orderings_2 = Int64Array::from(vec![50, 5]);
2138 group_acc.update_batch(
2139 &[
2140 Arc::new(values_2) as ArrayRef,
2141 Arc::new(orderings_2) as ArrayRef,
2142 ],
2143 &[0, 1],
2144 None,
2145 2,
2146 )?;
2147
2148 let result = group_acc.evaluate(EmitTo::All)?;
2149 let result = result.as_list::<i32>();
2150 assert_eq!(result.len(), 2);
2151 let g0 = result.value(0);
2152 let g0 = g0.as_primitive::<Int32Type>();
2153 assert_eq!(g0.len(), 2);
2154 assert_eq!(g0.value(0), 9);
2155 assert_eq!(g0.value(1), 9);
2156 let g1 = result.value(1);
2157 let g1 = g1.as_primitive::<Int32Type>();
2158 assert_eq!(g1.len(), 4);
2159 for i in 0..4 {
2160 assert_eq!(g1.value(i), 4);
2161 }
2162 Ok(())
2163 }
2164
2165 #[test]
2171 fn test_first_group_acc_list_size_bounded_by_groups() -> Result<()> {
2172 let value_type =
2173 DataType::List(Arc::new(Field::new("item", DataType::Int32, true)));
2174 let schema = Arc::new(Schema::new(vec![
2175 Field::new("val", value_type.clone(), true),
2176 Field::new("ord", DataType::Int64, true),
2177 ]));
2178 let sort_keys = [PhysicalSortExpr {
2179 expr: col("ord", &schema)?,
2180 options: SortOptions {
2181 descending: true,
2182 nulls_first: false,
2183 },
2184 }];
2185 let mut group_acc = FirstLastGroupsAccumulator::try_new(
2186 GenericValueState::new(value_type),
2187 sort_keys.into(),
2188 false,
2189 &[DataType::Int64],
2190 true,
2191 )?;
2192
2193 const GROUPS: usize = 10;
2197 const ROWS_PER_GROUP: usize = 10_000;
2198 const N: usize = GROUPS * ROWS_PER_GROUP;
2199 let values = ListArray::from_iter_primitive::<Int32Type, _, _>(
2200 repeat_with(|| Some(vec![Some(1_i32); 10])).take(N),
2201 );
2202 let orderings = Int64Array::from((0..N as i64).collect::<Vec<_>>());
2203 let group_indices: Vec<usize> = (0..N).map(|i| i % GROUPS).collect();
2204
2205 group_acc.update_batch(
2206 &[
2207 Arc::new(values) as ArrayRef,
2208 Arc::new(orderings) as ArrayRef,
2209 ],
2210 &group_indices,
2211 None,
2212 GROUPS,
2213 )?;
2214
2215 let size = group_acc.size();
2220 assert!(
2221 size < 100_000,
2222 "accumulator size {size} bytes is not bounded by #groups (10 groups × ~10 int32 list elements)"
2223 );
2224
2225 let result = group_acc.evaluate(EmitTo::All)?;
2228 let result = result.as_list::<i32>();
2229 assert_eq!(result.len(), GROUPS);
2230 for g in 0..GROUPS {
2231 let winner = result.value(g);
2232 let winner = winner.as_primitive::<Int32Type>();
2233 assert_eq!(winner.len(), 10);
2234 for i in 0..10 {
2235 assert_eq!(winner.value(i), 1);
2236 }
2237 }
2238 Ok(())
2239 }
2240
2241 #[test]
2261 fn test_first_group_acc_list_no_source_batch_pinning() -> Result<()> {
2262 let value_type =
2263 DataType::List(Arc::new(Field::new("item", DataType::Int32, true)));
2264 let schema = Arc::new(Schema::new(vec![
2265 Field::new("val", value_type.clone(), true),
2266 Field::new("ord", DataType::Int64, true),
2267 ]));
2268 let sort_keys = [PhysicalSortExpr {
2269 expr: col("ord", &schema)?,
2270 options: SortOptions {
2271 descending: true,
2272 nulls_first: false,
2273 },
2274 }];
2275 let mut group_acc = FirstLastGroupsAccumulator::try_new(
2276 GenericValueState::new(value_type),
2277 sort_keys.into(),
2278 false,
2279 &[DataType::Int64],
2280 true,
2281 )?;
2282
2283 const GROUPS: usize = 4;
2284 const BATCHES: usize = 50;
2285 const ROWS_PER_BATCH: usize = 256;
2286
2287 let mut source_value_ptrs: Vec<*const u8> = Vec::with_capacity(BATCHES);
2292
2293 let mut expected_ord = [i64::MIN; GROUPS];
2296 let mut expected_val_repeat = [0_i32; GROUPS];
2297
2298 for batch in 0..BATCHES {
2299 let values = ListArray::from_iter_primitive::<Int32Type, _, _>(
2303 (0..ROWS_PER_BATCH).map(|i| {
2304 let g = i % GROUPS;
2305 Some(vec![Some(batch as i32); g + 1])
2306 }),
2307 );
2308 let orderings = Int64Array::from(
2309 (0..ROWS_PER_BATCH as i64)
2310 .map(|i| batch as i64 * ROWS_PER_BATCH as i64 + i)
2311 .collect::<Vec<_>>(),
2312 );
2313 let group_indices: Vec<usize> =
2314 (0..ROWS_PER_BATCH).map(|i| i % GROUPS).collect();
2315
2316 for i in (0..ROWS_PER_BATCH).rev() {
2319 let g = i % GROUPS;
2320 let ord = batch as i64 * ROWS_PER_BATCH as i64 + i as i64;
2321 if ord > expected_ord[g] {
2322 expected_ord[g] = ord;
2323 expected_val_repeat[g] = batch as i32;
2324 }
2325 }
2326
2327 source_value_ptrs.push(values.values().to_data().buffers()[0].as_ptr());
2331
2332 let values_arc: Arc<dyn Array> = Arc::new(values);
2333 let orderings_arc: Arc<dyn Array> = Arc::new(orderings);
2334
2335 group_acc.update_batch(
2336 &[values_arc, orderings_arc],
2337 &group_indices,
2338 None,
2339 GROUPS,
2340 )?;
2341
2342 }
2344
2345 let size = group_acc.size();
2350 assert!(
2351 size < 10_000,
2352 "accumulator size {size} bytes is not bounded by #groups \
2353 (expected O({GROUPS}) not O({BATCHES} * {ROWS_PER_BATCH}))"
2354 );
2355
2356 let result = group_acc.evaluate(EmitTo::All)?;
2358 let result_list = result.as_list::<i32>();
2359 assert_eq!(result_list.len(), GROUPS);
2360 for (g, expected_repeat) in expected_val_repeat.iter().enumerate().take(GROUPS) {
2361 let winner = result_list.value(g);
2362 let winner = winner.as_primitive::<Int32Type>();
2363 assert_eq!(winner.len(), g + 1, "winner list length for group {g}");
2364 for i in 0..winner.len() {
2365 assert_eq!(
2366 winner.value(i),
2367 *expected_repeat,
2368 "winner payload mismatch for group {g}"
2369 );
2370 }
2371 }
2372
2373 let result_values_ptr = result_list.values().to_data().buffers()[0].as_ptr();
2380 for (i, src_ptr) in source_value_ptrs.iter().enumerate() {
2381 assert_ne!(
2382 *src_ptr, result_values_ptr,
2383 "emitted result's Int32 value buffer aliases source batch \
2384 {i}'s buffer; compact() is not making an owned copy"
2385 );
2386 }
2387 Ok(())
2388 }
2389}