Skip to main content

datafusion_functions_aggregate/
first_last.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Defines the FIRST_VALUE/LAST_VALUE aggregations.
19
20use 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
59/// Returns the first value in a group of values.
60pub 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        // guaranteed to be `Expr::AggregateFunction`
66        .unwrap()
67}
68
69/// Returns the last value in a group of values.
70pub 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        // guaranteed to be `Expr::AggregateFunction`
76        .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        // Nested / composite types fall through to a generic ScalarValue-backed
175        // state. Slower per-batch than the primitive/bytes fast paths but still
176        // avoids the per-row ScalarValue churn of the per-group `Accumulator`
177        // path: winner extraction happens once per group per batch, not once
178        // per candidate row.
179        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        // Preserve metadata from the first argument field
289        Ok(Arc::new(
290            Field::new(
291                self.name(),
292                arg_fields[0].data_type().clone(),
293                true, // always nullable, there may be no rows
294            )
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 ===========
381    state: S,
382    // Stores ordering values, of the aggregator requirement corresponding to first value
383    // of the aggregator.
384    // The `orderings` are stored row-wise, meaning that `orderings[group_idx]`
385    // represents the ordering values corresponding to the `group_idx`-th group.
386    orderings: Vec<Vec<ScalarValue>>,
387    // At the beginning, `is_sets[group_idx]` is false, which means `first` is not seen yet.
388    // Once we see the first value, we set the `is_sets[group_idx]` flag
389    is_sets: BooleanBufferBuilder,
390    // size of `self.orderings`
391    // Calculating the memory usage of `self.orderings` using `ScalarValue::size_of_vec` is quite costly.
392    // Therefore, we cache it and compute `size_of` only after each update
393    // to avoid calling `ScalarValue::size_of_vec` by Self.size.
394    size_of_orderings: usize,
395
396    // buffer for `get_filtered_extreme_of_each_group`
397    // filter_min_of_each_group_buf.0[group_idx] -> idx_in_val
398    // only valid if filter_min_of_each_group_buf.1[group_idx] == true
399    extreme_of_each_group_buf: (Vec<usize>, BooleanBufferBuilder),
400
401    // =========== option ============
402
403    // Stores the applicable ordering requirement.
404    ordering_req: LexOrdering,
405    // true: take first element in an aggregation group according to the requested ordering.
406    // false: take last element in an aggregation group according to the requested ordering.
407    pick_first_in_group: bool,
408    // derived from `ordering_req`.
409    sort_options: Vec<SortOptions>,
410    // Ignore null values.
411    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                    // Note: In some cases (such as in the unit test below)
490                    // ScalarValue::size_of_vec(&self.default_orderings) != ScalarValue::size_of_vec(&self.default_orderings.clone())
491                    // This may be caused by the different vec.capacity() values?
492                    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    // should be used in test only
538    #[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    /// Returns a vector of tuples `(group_idx, idx_in_val)` representing the index of the
546    /// minimum value in `orderings` for each group, using lexicographical comparison.
547    /// Values are filtered using `opt_filter` and `is_set_arr` if provided.
548    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        // Set all values in min_of_each_group_buf.1 to false.
557        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        // No need to call `clear` since `self.min_of_each_group_buf.0[group_idx]`
563        // is only valid when `self.min_of_each_group_buf.1[group_idx] == true`.
564
565        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            // A row passes the FILTER clause only when the predicate is
583            // `true`; rows whose predicate evaluates to `null` are excluded.
584            let passed_filter =
585                opt_filter.is_none_or(|x| x.is_valid(idx_in_val) && x.value(idx_in_val));
586            // `is_set_arr` carries the user FILTER clause (including its
587            // nulls) when the state was produced by `convert_to_state`, so
588            // the validity check is required here as well (#22666).
589            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        // e.g. first_value(a order by b): values_and_order_cols will be [a, b]
632        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        // The overhead of calling `extract_row_at_idx_to_buf` is somewhat high, so we need to minimize its calls as much as possible.
644        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        // The overhead of calling `extract_row_at_idx_to_buf` is somewhat high, so we need to minimize its calls as much as possible.
720        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 // capacity is in bits, so convert to bytes
742            + 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/// This accumulator is used when there is no ordering specified for the
766/// `FIRST_VALUE` aggregation. It simply returns the first value it sees
767/// according to the pre-existing ordering of the input data, and provides
768/// a fast path for this case without needing to maintain any ordering state.
769#[derive(Debug)]
770pub struct TrivialFirstValueAccumulator {
771    first: ScalarValue,
772    // Whether we have seen the first value yet.
773    is_set: bool,
774    // Ignore null values.
775    ignore_nulls: bool,
776}
777
778impl TrivialFirstValueAccumulator {
779    /// Creates a new `TrivialFirstValueAccumulator` for the given `data_type`.
780    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            // Get first entry according to the pre-existing ordering (0th index):
797            let value = &values[0];
798            let mut first_idx = None;
799            if self.ignore_nulls {
800                // If ignoring nulls, find the first non-null value.
801                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                // If not ignoring nulls, return the first value if it exists.
809                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        // FIRST_VALUE(first1, first2, first3, ...)
822        // Second index contains is_set flag.
823        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    // Whether we have seen the first value yet.
852    is_set: bool,
853    // Stores values of the ordering columns corresponding to the first value.
854    // These values are used during merging of multiple partitions.
855    orderings: Vec<ScalarValue>,
856    // Stores the applicable ordering requirement.
857    ordering_req: LexOrdering,
858    // derived from `ordering_req`.
859    sort_options: Vec<SortOptions>,
860    // Stores whether incoming data already satisfies the ordering requirement.
861    is_input_pre_ordered: bool,
862    // Ignore null values.
863    ignore_nulls: bool,
864}
865
866impl FirstValueAccumulator {
867    /// Creates a new `FirstValueAccumulator` for the given `data_type`.
868    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    // Updates state with the values in the given row.
892    fn update_with_new_row(&mut self, mut row: Vec<ScalarValue>) {
893        // Ensure any Array based scalars hold have a single value to reduce memory pressure
894        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            // Get first entry according to the pre-existing ordering (0th index):
908            if self.ignore_nulls {
909                // If ignoring nulls, find the first non-null value.
910                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                // If not ignoring nulls, return the first value if it exists.
918                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        // FIRST_VALUE(first1, first2, first3, ...)
969        // last index contains is_set flag.
970        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        // 1..is_set_idx range corresponds to ordering section
977        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            // When collecting orderings, we exclude the is_set flag from the state.
986            let first_ordering = &first_row[1..is_set_idx];
987            // Either there is no existing value, or there is an earlier version in new data.
988            if !self.is_set
989                || compare_rows(&self.orderings, first_ordering, &self.sort_options)?
990                    .is_gt()
991            {
992                // Update with first value in the state. Note that we should exclude the
993                // is_set flag from the state. Otherwise, we will end up with a state
994                // containing two is_set flags.
995                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        // Preserve metadata from the first argument field
1065        Ok(Arc::new(
1066            Field::new(
1067                self.name(),
1068                arg_fields[0].data_type().clone(),
1069                true, // always nullable, there may be no rows
1070            )
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/// This accumulator is used when there is no ordering specified for the
1156/// `LAST_VALUE` aggregation. It simply updates the last value it sees
1157/// according to the pre-existing ordering of the input data, and provides
1158/// a fast path for this case without needing to maintain any ordering state.
1159#[derive(Debug)]
1160pub struct TrivialLastValueAccumulator {
1161    last: ScalarValue,
1162    // The `is_set` flag keeps track of whether the last value is finalized.
1163    // This information is used to discriminate genuine NULLs and NULLS that
1164    // occur due to empty partitions.
1165    is_set: bool,
1166    // Ignore null values.
1167    ignore_nulls: bool,
1168}
1169
1170impl TrivialLastValueAccumulator {
1171    /// Creates a new `TrivialLastValueAccumulator` for the given `data_type`.
1172    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        // Get last entry according to the pre-existing ordering (0th index):
1188        let value = &values[0];
1189        let mut last_idx = None;
1190        if self.ignore_nulls {
1191            // If ignoring nulls, find the last non-null value.
1192            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            // If not ignoring nulls, return the last value if it exists.
1200            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        // LAST_VALUE(last1, last2, last3, ...)
1212        // Second index contains is_set flag.
1213        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    // The `is_set` flag keeps track of whether the last value is finalized.
1239    // This information is used to discriminate genuine NULLs and NULLS that
1240    // occur due to empty partitions.
1241    is_set: bool,
1242    // Stores values of the ordering columns corresponding to the first value.
1243    // These values are used during merging of multiple partitions.
1244    orderings: Vec<ScalarValue>,
1245    // Stores the applicable ordering requirement.
1246    ordering_req: LexOrdering,
1247    // derived from `ordering_req`.
1248    sort_options: Vec<SortOptions>,
1249    // Stores whether incoming data already satisfies the ordering requirement.
1250    is_input_pre_ordered: bool,
1251    // Ignore null values.
1252    ignore_nulls: bool,
1253}
1254
1255impl LastValueAccumulator {
1256    /// Creates a new `LastValueAccumulator` for the given `data_type`.
1257    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    // Updates state with the values in the given row.
1281    fn update_with_new_row(&mut self, mut row: Vec<ScalarValue>) {
1282        // Ensure any Array based scalars hold have a single value to reduce memory pressure
1283        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            // Get last entry according to the order of data:
1297            if self.ignore_nulls {
1298                // If ignoring nulls, find the last non-null value.
1299                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            // Update when there is a more recent entry
1345            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        // LAST_VALUE(last1, last2, last3, ...)
1357        // last index contains is_set flag.
1358        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        // 1..is_set_idx range corresponds to ordering section
1365        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            // When collecting orderings, we exclude the is_set flag from the state.
1374            let last_ordering = &last_row[1..is_set_idx];
1375            // Either there is no existing value, or there is a newer (latest)
1376            // version in the new data:
1377            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                // Update with last value in the state. Note that we should exclude the
1383                // is_set flag from the state. Otherwise, we will end up with a state
1384                // containing two is_set flags.
1385                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
1405/// Validates that `is_set flags` do not contain NULL values.
1406fn 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
1415/// Filters states according to the `is_set` flag at the last column and returns
1416/// the resulting states.
1417fn 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
1427/// Combines array refs and their corresponding orderings to construct `SortColumn`s.
1428fn 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        // first value in the tuple is start of the range (inclusive),
1459        // second value in the tuple is end of the range (exclusive)
1460        let ranges: Vec<(i64, i64)> = vec![(0, 10), (1, 11), (2, 13)];
1461        // create 3 ArrayRefs between each interval e.g from 0 to 9, 1 to 10, 2 to 12
1462        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            // Once first_value is set, accumulator should remember it.
1470            // It shouldn't update first_value for each new batch
1471            first_accumulator.update_batch(&[Arc::clone(&arr)])?;
1472            // last_value should be updated for each new batch.
1473            last_accumulator.update_batch(&[arr])?;
1474        }
1475        // First Value comes from the first value of the first batch which is 0
1476        assert_eq!(first_accumulator.evaluate()?, ScalarValue::Int64(Some(0)));
1477        // Last value comes from the last value of the last batch which is 12
1478        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        // create 3 ArrayRefs between each interval e.g from 0 to 9, 1 to 10, 2 to 12
1486        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        // FirstValueAccumulator
1494        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        // LastValueAccumulator
1524        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        // group 0 keeps merged value=1 (ordering=1).
1647        // group 1 keeps merged value=-6 (ordering=-6 < 6, so -6 is "first").
1648        // group 2 had no merged value (is_set=false), so update_batch value=6 wins.
1649        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        // group 0: merged value=1 (ordering=1, is_set=true), update not called.
1806        // group 1: merged value=-6 (ordering=-6, is_set=true); update ordering=66 > -6
1807        //          → LAST_VALUE keeps the higher ordering, so group 1 becomes 66.
1808        // group 2: is_set=false after merge; update_batch sets it to 6.
1809        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    /// Rows whose FILTER predicate evaluates to `null` must not pass the
1818    /// filter, even when the underlying value bit at the null slot is `true`
1819    /// (#22666).
1820    #[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        // Row 0: predicate is null (but its value bit is true, as produced by
1846        // kernels such as `b < 1` when the null slot's underlying value is 0)
1847        // Row 1: predicate is false
1848        // Row 2: predicate is true
1849        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        // Group 0 has no row with a `true` predicate, so it must stay unset.
1864        // Group 1 takes the only row with a `true` predicate.
1865        let expect: PrimitiveArray<Int64Type> = Int64Array::from(vec![None, Some(30)]);
1866        assert_eq!(eval_result, &expect);
1867
1868        Ok(())
1869    }
1870
1871    /// `convert_to_state` stores the user FILTER clause (including its nulls)
1872    /// in the `is_set` state column, so `merge_batch` must not treat a null
1873    /// `is_set` entry with a set value bit as "is set" (#22666).
1874    #[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        // Same null-with-set-value-bit filter as above, carried into the state
1900        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        // Only the second row is valid and passes; the null-predicate row must
1922        // be skipped even though its value bit is true.
1923        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        // Test data with corrupted is_set flag
1984        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        // Test TrivialFirstValueAccumulator
1988        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        // Test FirstValueAccumulator (with ordering)
2001        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        // Test data with corrupted is_set flag
2031        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        // Test TrivialLastValueAccumulator
2035        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        // Test LastValueAccumulator (with ordering)
2048        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    /// End-to-end integration test for the nested-type support added to
2076    /// [`FirstLastGroupsAccumulator`]: build the accumulator directly with a
2077    /// [`GenericValueState`] for `List<Int32>` and verify that winners are
2078    /// selected correctly across multiple batches.
2079    ///
2080    /// Mirrors the shape produced by SQL like:
2081    /// ```sql
2082    /// SELECT first_value(list_col ORDER BY o DESC) FROM t GROUP BY p
2083    /// ```
2084    /// which previously fell back to the per-group `Accumulator` path and
2085    /// blew up on wide payloads.
2086    #[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            /* pick_first = */ true,
2108        )?;
2109
2110        // Batch 1: four rows across two groups.
2111        // Winners (largest ord per group with pick_first=true + DESC):
2112        //   group 0 -> ord=30 -> [3, 3, 3]
2113        //   group 1 -> ord=40 -> [4, 4, 4, 4]
2114        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        // Batch 2: group 0 gets a new winner ord=50 -> [9, 9]; group 1
2132        // keeps its previous winner (5 < 40).
2133        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    /// Regression test for the wide-payload memory blow-up: run the full
2166    /// aggregate loop over a batch large enough that the per-group
2167    /// `Accumulator` path would have generated N * batch-worth of state
2168    /// (via `ScalarValue::List` clones) and verify that the reported
2169    /// accumulator size stays proportional to `#groups`, not `#rows`.
2170    #[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        // 10 groups × 10_000 candidate rows per group (100_000 total). Each
2194        // list value has ~10 elements. Under the old per-group `Accumulator`
2195        // + Arc-slice code path this would pin every batch in memory.
2196        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        // Sanity: the retained size must be small — well under what a single
2216        // input batch worth of list buffers would occupy. The exact number is
2217        // implementation-dependent, but should be O(GROUPS * per-list), not
2218        // O(N * per-list).
2219        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        // Winner per group is the row with the largest ord — with our layout
2226        // that's the last row assigned to each group.
2227        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    /// End-to-end memory-savings regression test.
2242    ///
2243    /// Streams many independent batches of wide `List<Int32>` payload through
2244    /// the accumulator, dropping each source batch immediately after feeding
2245    /// it in. The test then verifies three things:
2246    ///
2247    ///   1. The accumulator still emits the correct winners after every
2248    ///      source batch has been dropped (proves that stored values are
2249    ///      owned copies, not `Arc` slices into batches that no longer
2250    ///      exist).
2251    ///   2. No buffer of any past source batch is shared by the emitted
2252    ///      output — the raw data-buffer pointer of every source batch is
2253    ///      recorded, and the final output's buffers must not alias any of
2254    ///      them (proves `compact()` copied the winners into owned memory).
2255    ///   3. The accumulator's reported `size()` stays bounded by
2256    ///      `#groups * per-group-cost`, independent of `#batches * #rows`.
2257    ///
2258    /// This is the regression test for the wide-payload pinning behaviour
2259    /// that motivated this PR.
2260    #[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        // Record the raw pointer of each source batch's Int32 value-data
2288        // buffer. If `compact()` did its job, the accumulator's final
2289        // output must not share any of these pointers — every winner
2290        // value should have been copied into an owned buffer.
2291        let mut source_value_ptrs: Vec<*const u8> = Vec::with_capacity(BATCHES);
2292
2293        // Track the running-max ord we have fed to each group so the test's
2294        // "expected winner" oracle matches the accumulator's choice.
2295        let mut expected_ord = [i64::MIN; GROUPS];
2296        let mut expected_val_repeat = [0_i32; GROUPS];
2297
2298        for batch in 0..BATCHES {
2299            // Each batch's list values are `[batch as i32; group_idx + 1]`
2300            // — a distinct payload per (batch, row) so we can verify the
2301            // winner by content.
2302            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            // Update the oracle: the last row in this batch that hits each
2317            // group has the largest ord for that group in this batch.
2318            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            // Capture the raw pointer of this batch's Int32 value-data
2328            // buffer *before* handing ownership to the accumulator. Int32
2329            // arrays have a single value buffer at index 0.
2330            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            // Drop happens implicitly at end of scope.
2343        }
2344
2345        // (2) Size is bounded by #groups. The exact number is
2346        // implementation-dependent but should be orders of magnitude below
2347        // `BATCHES * ROWS_PER_BATCH * per-list-cost` (the amount that would
2348        // be retained under the old Arc-slice pinning bug).
2349        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        // (1) Winners are still readable and match the oracle.
2357        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        // (3) The critical byte-level check: the emitted output's Int32
2374        // value-data buffer must NOT share a raw pointer with any of the
2375        // source batches. If `compact()` were omitted, `list_array.value(i)`
2376        // would yield a slice whose backing buffer points into the source
2377        // batch — the accumulator would then either pin the batch or emit
2378        // an output that shares its buffer.
2379        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}