Skip to main content

datafusion_common/utils/
mod.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//! This module provides the bisect function, which implements binary search.
19
20pub(crate) mod aggregate;
21pub mod expr;
22pub mod hex;
23pub mod memory;
24pub mod proxy;
25pub mod string_utils;
26
27use crate::assert_or_internal_err;
28use crate::error::{_exec_datafusion_err, _exec_err, _internal_datafusion_err};
29use crate::{Result, ScalarValue};
30use arrow::array::{
31    Array, ArrayRef, FixedSizeListArray, LargeListArray, ListArray, OffsetSizeTrait,
32    cast::AsArray,
33};
34use arrow::array::{
35    ArrowPrimitiveType, BooleanArray, Datum, GenericListArray, Int32Array, Int64Array,
36    MutableArrayData, PrimitiveArray, make_array,
37};
38use arrow::array::{LargeListViewArray, ListViewArray};
39use arrow::buffer::{OffsetBuffer, ScalarBuffer};
40use arrow::compute::kernels::cmp::eq;
41use arrow::compute::kernels::length::length;
42use arrow::compute::{SortColumn, SortOptions, partition};
43use arrow::datatypes::{
44    ArrowNativeType, DataType, Field, Int32Type, Int64Type, SchemaRef,
45};
46#[cfg(feature = "sql")]
47use sqlparser::{ast::Ident, dialect::GenericDialect, parser::Parser};
48use std::borrow::{Borrow, Cow};
49use std::cmp::{Ordering, min};
50use std::collections::HashSet;
51use std::iter::repeat_n;
52use std::num::NonZero;
53use std::ops::Range;
54use std::sync::{Arc, LazyLock};
55use std::thread::available_parallelism;
56
57/// Applies an optional projection to a [`SchemaRef`], returning the
58/// projected schema
59///
60/// Example:
61/// ```
62/// use arrow::datatypes::{DataType, Field, Schema, SchemaRef};
63/// use datafusion_common::project_schema;
64///
65/// // Schema with columns 'a', 'b', and 'c'
66/// let schema = SchemaRef::new(Schema::new(vec![
67///     Field::new("a", DataType::Int32, true),
68///     Field::new("b", DataType::Int64, true),
69///     Field::new("c", DataType::Utf8, true),
70/// ]));
71///
72/// // Pick columns 'c' and 'b'
73/// let projection = Some(vec![2, 1]);
74/// let projected_schema = project_schema(&schema, projection.as_ref()).unwrap();
75///
76/// let expected_schema = SchemaRef::new(Schema::new(vec![
77///     Field::new("c", DataType::Utf8, true),
78///     Field::new("b", DataType::Int64, true),
79/// ]));
80///
81/// assert_eq!(projected_schema, expected_schema);
82/// ```
83pub fn project_schema(
84    schema: &SchemaRef,
85    projection: Option<&impl AsRef<[usize]>>,
86) -> Result<SchemaRef> {
87    let schema = match projection {
88        Some(columns) => Arc::new(schema.project(columns.as_ref())?),
89        None => Arc::clone(schema),
90    };
91    Ok(schema)
92}
93
94/// Extracts a row at the specified index from a set of columns and stores it in the provided buffer.
95pub fn extract_row_at_idx_to_buf(
96    columns: &[ArrayRef],
97    idx: usize,
98    buf: &mut Vec<ScalarValue>,
99) -> Result<()> {
100    buf.clear();
101
102    let iter = columns
103        .iter()
104        .map(|arr| ScalarValue::try_from_array(arr, idx));
105    for v in iter.into_iter() {
106        buf.push(v?);
107    }
108
109    Ok(())
110}
111/// Given column vectors, returns row at `idx`.
112pub fn get_row_at_idx(columns: &[ArrayRef], idx: usize) -> Result<Vec<ScalarValue>> {
113    columns
114        .iter()
115        .map(|arr| ScalarValue::try_from_array(arr, idx))
116        .collect()
117}
118
119/// This function compares two tuples depending on the given sort options.
120pub fn compare_rows(
121    x: &[ScalarValue],
122    y: &[ScalarValue],
123    sort_options: &[SortOptions],
124) -> Result<Ordering> {
125    let zip_it = x.iter().zip(y.iter()).zip(sort_options.iter());
126    // Preserving lexical ordering.
127    for ((lhs, rhs), sort_options) in zip_it {
128        // Consider all combinations of NULLS FIRST/LAST and ASC/DESC configurations.
129        let result = match (lhs.is_null(), rhs.is_null(), sort_options.nulls_first) {
130            (true, false, false) | (false, true, true) => Ordering::Greater,
131            (true, false, true) | (false, true, false) => Ordering::Less,
132            (false, false, _) => {
133                if sort_options.descending {
134                    rhs.try_cmp(lhs)?
135                } else {
136                    lhs.try_cmp(rhs)?
137                }
138            }
139            (true, true, _) => continue,
140        };
141        if result != Ordering::Equal {
142            return Ok(result);
143        }
144    }
145    Ok(Ordering::Equal)
146}
147
148/// This function searches for a tuple of given values (`target`) among the given
149/// rows (`item_columns`) using the bisection algorithm. It assumes that `item_columns`
150/// is sorted according to `sort_options` and returns the insertion index of `target`.
151/// Template argument `SIDE` being `true`/`false` means left/right insertion.
152pub fn bisect<const SIDE: bool>(
153    item_columns: &[ArrayRef],
154    target: &[ScalarValue],
155    sort_options: &[SortOptions],
156) -> Result<usize> {
157    let low: usize = 0;
158    let high: usize = item_columns
159        .first()
160        .ok_or_else(|| _internal_datafusion_err!("Column array shouldn't be empty"))?
161        .len();
162    let compare_fn = |current: &[ScalarValue], target: &[ScalarValue]| {
163        let cmp = compare_rows(current, target, sort_options)?;
164        Ok(if SIDE { cmp.is_lt() } else { cmp.is_le() })
165    };
166    find_bisect_point(item_columns, target, compare_fn, low, high)
167}
168
169/// This function searches for a tuple of given values (`target`) among a slice of
170/// the given rows (`item_columns`) using the bisection algorithm. The slice starts
171/// at the index `low` and ends at the index `high`. The boolean-valued function
172/// `compare_fn` specifies whether we bisect on the left (by returning `false`),
173/// or on the right (by returning `true`) when we compare the target value with
174/// the current value as we iteratively bisect the input.
175pub fn find_bisect_point<F>(
176    item_columns: &[ArrayRef],
177    target: &[ScalarValue],
178    compare_fn: F,
179    mut low: usize,
180    mut high: usize,
181) -> Result<usize>
182where
183    F: Fn(&[ScalarValue], &[ScalarValue]) -> Result<bool>,
184{
185    while low < high {
186        let mid = ((high - low) / 2) + low;
187        let val = get_row_at_idx(item_columns, mid)?;
188        if compare_fn(&val, target)? {
189            low = mid + 1;
190        } else {
191            high = mid;
192        }
193    }
194    Ok(low)
195}
196
197/// This function searches for a tuple of given values (`target`) among the given
198/// rows (`item_columns`) via a linear scan. It assumes that `item_columns` is sorted
199/// according to `sort_options` and returns the insertion index of `target`.
200/// Template argument `SIDE` being `true`/`false` means left/right insertion.
201pub fn linear_search<const SIDE: bool>(
202    item_columns: &[ArrayRef],
203    target: &[ScalarValue],
204    sort_options: &[SortOptions],
205) -> Result<usize> {
206    let low: usize = 0;
207    let high: usize = item_columns
208        .first()
209        .ok_or_else(|| _internal_datafusion_err!("Column array shouldn't be empty"))?
210        .len();
211    let compare_fn = |current: &[ScalarValue], target: &[ScalarValue]| {
212        let cmp = compare_rows(current, target, sort_options)?;
213        Ok(if SIDE { cmp.is_lt() } else { cmp.is_le() })
214    };
215    search_in_slice(item_columns, target, compare_fn, low, high)
216}
217
218/// This function searches for a tuple of given values (`target`) among a slice of
219/// the given rows (`item_columns`) via a linear scan. The slice starts at the index
220/// `low` and ends at the index `high`. The boolean-valued function `compare_fn`
221/// specifies the stopping criterion.
222pub fn search_in_slice<F>(
223    item_columns: &[ArrayRef],
224    target: &[ScalarValue],
225    compare_fn: F,
226    mut low: usize,
227    high: usize,
228) -> Result<usize>
229where
230    F: Fn(&[ScalarValue], &[ScalarValue]) -> Result<bool>,
231{
232    while low < high {
233        let val = get_row_at_idx(item_columns, low)?;
234        if !compare_fn(&val, target)? {
235            break;
236        }
237        low += 1;
238    }
239    Ok(low)
240}
241
242/// Given a list of 0 or more already sorted columns, finds the
243/// partition ranges that would partition equally across columns.
244///
245/// See [`partition`] for more details.
246pub fn evaluate_partition_ranges(
247    num_rows: usize,
248    partition_columns: &[SortColumn],
249) -> Result<Vec<Range<usize>>> {
250    Ok(if partition_columns.is_empty() {
251        vec![Range {
252            start: 0,
253            end: num_rows,
254        }]
255    } else {
256        let cols: Vec<_> = partition_columns
257            .iter()
258            .map(|x| Arc::clone(&x.values))
259            .collect();
260        partition(&cols)?.ranges()
261    })
262}
263
264/// Wraps identifier string in double quotes, escaping any double quotes in
265/// the identifier by replacing it with two double quotes
266///
267/// e.g. identifier `tab.le"name` becomes `"tab.le""name"`
268pub fn quote_identifier(s: &str) -> Cow<'_, str> {
269    if needs_quotes(s) {
270        Cow::Owned(format!("\"{}\"", s.replace('"', "\"\"")))
271    } else {
272        Cow::Borrowed(s)
273    }
274}
275
276/// returns true if this identifier needs quotes
277fn needs_quotes(s: &str) -> bool {
278    let mut chars = s.chars();
279
280    // first char can not be a number unless escaped
281    if let Some(first_char) = chars.next()
282        && !(first_char.is_ascii_lowercase() || first_char == '_')
283    {
284        return true;
285    }
286
287    !chars.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_')
288}
289
290#[cfg(feature = "sql")]
291pub(crate) fn parse_identifiers(s: &str) -> Result<Vec<Ident>> {
292    let dialect = GenericDialect;
293    let mut parser = Parser::new(&dialect).try_with_sql(s)?;
294    let idents = parser.parse_multipart_identifier()?;
295    Ok(idents)
296}
297
298/// Parse a string into a vector of identifiers.
299///
300/// Note: If ignore_case is false, the string will be normalized to lowercase.
301#[cfg(feature = "sql")]
302pub(crate) fn parse_identifiers_normalized(s: &str, ignore_case: bool) -> Vec<String> {
303    parse_identifiers(s)
304        .unwrap_or_default()
305        .into_iter()
306        .map(|id| match id.quote_style {
307            Some(_) => id.value,
308            None if ignore_case => id.value,
309            _ => id.value.to_ascii_lowercase(),
310        })
311        .collect::<Vec<_>>()
312}
313
314#[cfg(not(feature = "sql"))]
315pub(crate) fn parse_identifiers(s: &str) -> Result<Vec<String>> {
316    let mut result = Vec::new();
317    let mut current = String::new();
318    let mut in_quotes = false;
319
320    for ch in s.chars() {
321        match ch {
322            '"' => {
323                in_quotes = !in_quotes;
324                current.push(ch);
325            }
326            '.' if !in_quotes => {
327                result.push(current.clone());
328                current.clear();
329            }
330            _ => {
331                current.push(ch);
332            }
333        }
334    }
335
336    // Push the last part if it's not empty
337    if !current.is_empty() {
338        result.push(current);
339    }
340
341    Ok(result)
342}
343
344#[cfg(not(feature = "sql"))]
345pub(crate) fn parse_identifiers_normalized(s: &str, ignore_case: bool) -> Vec<String> {
346    parse_identifiers(s)
347        .unwrap_or_default()
348        .into_iter()
349        .map(|id| {
350            let is_double_quoted = if id.len() > 2 {
351                let mut chars = id.chars();
352                chars.next() == Some('"') && chars.last() == Some('"')
353            } else {
354                false
355            };
356            if is_double_quoted {
357                id[1..id.len() - 1].to_string().replace("\"\"", "\"")
358            } else if ignore_case {
359                id
360            } else {
361                id.to_ascii_lowercase()
362            }
363        })
364        .collect::<Vec<_>>()
365}
366
367/// This function "takes" the elements at `indices` from the slice `items`.
368pub fn get_at_indices<T: Clone, I: Borrow<usize>>(
369    items: &[T],
370    indices: impl IntoIterator<Item = I>,
371) -> Result<Vec<T>> {
372    indices
373        .into_iter()
374        .map(|idx| items.get(*idx.borrow()).cloned())
375        .collect::<Option<Vec<T>>>()
376        .ok_or_else(|| {
377            _exec_datafusion_err!("Expects indices to be in the range of searched vector")
378        })
379}
380
381/// This function finds the longest prefix of the form 0, 1, 2, ... within the
382/// collection `sequence`. Examples:
383/// - For 0, 1, 2, 4, 5; we would produce 3, meaning 0, 1, 2 is the longest satisfying
384///   prefix.
385/// - For 1, 2, 3, 4; we would produce 0, meaning there is no such prefix.
386pub fn longest_consecutive_prefix<T: Borrow<usize>>(
387    sequence: impl IntoIterator<Item = T>,
388) -> usize {
389    let mut count = 0;
390    for item in sequence {
391        if !count.eq(item.borrow()) {
392            break;
393        }
394        count += 1;
395    }
396    count
397}
398
399/// Splits `vec` at index `n`, returning the first `n` elements and leaving the
400/// remaining `vec.len() - n` elements in `vec`.
401///
402/// Allocates for whichever side is smaller, so the new allocation is
403/// `min(n, vec.len() - n)` rather than always `n` (as `vec.drain(0..n).collect()`
404/// would). This matters when the split emits a prefix under memory pressure,
405/// where `n` can be close to `vec.len()`.
406pub fn split_vec_min_alloc<T>(vec: &mut Vec<T>, n: usize) -> Vec<T> {
407    if n * 2 <= vec.len() {
408        vec.drain(0..n).collect()
409    } else {
410        let remaining = vec.split_off(n);
411        std::mem::replace(vec, remaining)
412    }
413}
414
415#[cfg(test)]
416mod split_vec_min_alloc_tests {
417    use super::split_vec_min_alloc;
418
419    #[test]
420    fn drain_branch() {
421        // n * 2 <= len  ->  drain+collect branch (allocates n elements)
422        let mut v = vec![1, 2, 3, 4, 5, 6];
423        let first = split_vec_min_alloc(&mut v, 2);
424        assert_eq!(first, vec![1, 2]);
425        assert_eq!(v, vec![3, 4, 5, 6]);
426    }
427
428    #[test]
429    fn split_off_branch() {
430        // remaining < n  ->  split_off+replace branch (allocates remaining elements)
431        let mut v = vec![1, 2, 3, 4, 5, 6];
432        let first = split_vec_min_alloc(&mut v, 4);
433        assert_eq!(first, vec![1, 2, 3, 4]);
434        assert_eq!(v, vec![5, 6]);
435    }
436
437    #[test]
438    fn exactly_half() {
439        // n * 2 == len  ->  drain branch (boundary)
440        let mut v = vec![1, 2, 3, 4];
441        let first = split_vec_min_alloc(&mut v, 2);
442        assert_eq!(first, vec![1, 2]);
443        assert_eq!(v, vec![3, 4]);
444    }
445
446    #[test]
447    fn take_all() {
448        let mut v = vec![1, 2, 3];
449        let first = split_vec_min_alloc(&mut v, 3);
450        assert_eq!(first, vec![1, 2, 3]);
451        assert!(v.is_empty());
452    }
453
454    #[test]
455    fn take_none() {
456        let mut v = vec![1, 2, 3];
457        let first = split_vec_min_alloc(&mut v, 0);
458        assert!(first.is_empty());
459        assert_eq!(v, vec![1, 2, 3]);
460    }
461
462    #[test]
463    fn emitted_prefix_does_not_realloc_on_push() {
464        // Demonstrates *why* the split-off branch must NOT call `shrink_to_fit`.
465        //
466        // Downstream callers (e.g. `multi_group_by/bytes.rs`, which does
467        // `first_n_offsets.push(offset_n)` right after the split) push onto the
468        // emitted prefix immediately. The split-off branch hands the original
469        // backing allocation to that prefix, so the prefix already has spare
470        // capacity for the very next push.
471        //
472        // If we shrank the prefix to fit, that next push would have to
473        // reallocate, and Vec's growth strategy would land it at a *larger*
474        // capacity than the original allocation we started with -- the opposite
475        // of the memory saving `shrink_to_fit` was meant to deliver.
476
477        // A Vec with a known, deliberately large capacity. n*2 > len, so this
478        // takes the split-off branch.
479        let mut v: Vec<u32> = Vec::with_capacity(64);
480        v.extend(0..10);
481        let original_capacity = v.capacity();
482        assert!(original_capacity >= 64);
483
484        // Emit a prefix that is most of the Vec (n = 8, remaining = 2).
485        let mut prefix = split_vec_min_alloc(&mut v, 8);
486        assert_eq!(prefix, vec![0, 1, 2, 3, 4, 5, 6, 7]);
487
488        // The split-off branch moved the original backing store into `prefix`,
489        // so it keeps the original (large) capacity -- no shrink happened.
490        assert_eq!(
491            prefix.capacity(),
492            original_capacity,
493            "split-off branch must hand the original allocation to the prefix"
494        );
495
496        // The caller's very next operation: push one element onto the prefix.
497        prefix.push(99);
498
499        // Because the capacity was preserved, the push reused the existing
500        // allocation: post-push capacity is unchanged and still <= original.
501        // This is the realloc that `shrink_to_fit` would have forced.
502        assert_eq!(
503            prefix.capacity(),
504            original_capacity,
505            "push must reuse the preserved allocation (no realloc)"
506        );
507        assert!(prefix.capacity() <= original_capacity);
508
509        // Counter-demonstration: had we shrunk the prefix to fit (capacity 8),
510        // the same push would have reallocated. Vec doubles on growth, so the
511        // post-push capacity (16) ends up LARGER than where a length-8 prefix
512        // started -- and we paid a realloc for it.
513        let mut shrunk: Vec<u32> = prefix[..8].to_vec();
514        shrunk.shrink_to_fit();
515        let shrunk_capacity = shrink_then_push_capacity(&mut shrunk);
516        assert!(
517            shrunk_capacity > 8,
518            "shrink-to-fit then push reallocates to a larger capacity"
519        );
520    }
521
522    /// Helper for the counter-demonstration above: push one element and report
523    /// the resulting capacity.
524    fn shrink_then_push_capacity(v: &mut Vec<u32>) -> usize {
525        v.push(99);
526        v.capacity()
527    }
528}
529
530/// Creates single element [`ListArray`], [`LargeListArray`] and
531/// [`FixedSizeListArray`] from other arrays
532///
533/// For example this builder can convert `[1, 2, 3]` into `[[1, 2, 3]]`
534///
535/// # Example
536/// ```
537/// # use std::sync::Arc;
538/// # use arrow::array::{Array, ListArray};
539/// # use arrow::array::types::Int64Type;
540/// # use datafusion_common::utils::SingleRowListArrayBuilder;
541/// // Array is [1, 2, 3]
542/// let arr = ListArray::from_iter_primitive::<Int64Type, _, _>(vec![Some(vec![
543///     Some(1),
544///     Some(2),
545///     Some(3),
546/// ])]);
547/// // Wrap as a list array: [[1, 2, 3]]
548/// let list_arr = SingleRowListArrayBuilder::new(Arc::new(arr)).build_list_array();
549/// assert_eq!(list_arr.len(), 1);
550/// ```
551#[derive(Debug, Clone)]
552pub struct SingleRowListArrayBuilder {
553    /// array to be wrapped
554    arr: ArrayRef,
555    /// Should the resulting array be nullable? Defaults to `true`.
556    nullable: bool,
557    /// Specify the field name for the resulting array. Defaults to value used in
558    /// [`Field::new_list_field`]
559    field_name: Option<String>,
560}
561
562impl SingleRowListArrayBuilder {
563    /// Create a new instance of [`SingleRowListArrayBuilder`]
564    pub fn new(arr: ArrayRef) -> Self {
565        Self {
566            arr,
567            nullable: true,
568            field_name: None,
569        }
570    }
571
572    /// Set the nullable flag
573    pub fn with_nullable(mut self, nullable: bool) -> Self {
574        self.nullable = nullable;
575        self
576    }
577
578    /// sets the field name for the resulting array
579    pub fn with_field_name(mut self, field_name: Option<String>) -> Self {
580        self.field_name = field_name;
581        self
582    }
583
584    /// Copies field name and nullable from the specified field
585    pub fn with_field(self, field: &Field) -> Self {
586        self.with_field_name(Some(field.name().to_owned()))
587            .with_nullable(field.is_nullable())
588    }
589
590    /// Build a single element [`ListArray`]
591    pub fn build_list_array(self) -> ListArray {
592        let (field, arr) = self.into_field_and_arr();
593        let offsets = OffsetBuffer::from_lengths([arr.len()]);
594        ListArray::new(field, offsets, arr, None)
595    }
596
597    /// Build a single element [`ListArray`] and wrap as [`ScalarValue::List`]
598    pub fn build_list_scalar(self) -> ScalarValue {
599        ScalarValue::List(Arc::new(self.build_list_array()))
600    }
601
602    /// Build a single element [`LargeListArray`]
603    pub fn build_large_list_array(self) -> LargeListArray {
604        let (field, arr) = self.into_field_and_arr();
605        let offsets = OffsetBuffer::from_lengths([arr.len()]);
606        LargeListArray::new(field, offsets, arr, None)
607    }
608
609    /// Build a single element [`LargeListArray`] and wrap as [`ScalarValue::LargeList`]
610    pub fn build_large_list_scalar(self) -> ScalarValue {
611        ScalarValue::LargeList(Arc::new(self.build_large_list_array()))
612    }
613
614    /// Build a single element [`FixedSizeListArray`]
615    pub fn build_fixed_size_list_array(self, list_size: usize) -> FixedSizeListArray {
616        let (field, arr) = self.into_field_and_arr();
617        FixedSizeListArray::try_new_with_length(field, list_size as i32, arr, None, 1)
618            .unwrap()
619    }
620
621    /// Build a single element [`FixedSizeListArray`] and wrap as [`ScalarValue::FixedSizeList`]
622    pub fn build_fixed_size_list_scalar(self, list_size: usize) -> ScalarValue {
623        ScalarValue::FixedSizeList(Arc::new(self.build_fixed_size_list_array(list_size)))
624    }
625
626    /// Build a single element [`ListViewArray`]
627    pub fn build_list_view_array(self) -> ListViewArray {
628        let (field, arr) = self.into_field_and_arr();
629        let offsets = ScalarBuffer::from(vec![0]);
630        let sizes = ScalarBuffer::from(vec![i32::try_from(arr.len()).expect(
631            "Trying to construct a ListView where element length exceeds i32::MAX",
632        )]);
633        ListViewArray::new(field, offsets, sizes, arr, None)
634    }
635
636    /// Build a single element [`ListViewArray`] and wrap as [`ScalarValue::ListView`]
637    pub fn build_list_view_scalar(self) -> ScalarValue {
638        ScalarValue::ListView(Arc::new(self.build_list_view_array()))
639    }
640
641    /// Build a single element [`LargeListViewArray`]
642    pub fn build_large_list_view_array(self) -> LargeListViewArray {
643        let (field, arr) = self.into_field_and_arr();
644        let offsets = ScalarBuffer::from(vec![0]);
645        let sizes = ScalarBuffer::from(vec![arr.len() as i64]);
646        LargeListViewArray::new(field, offsets, sizes, arr, None)
647    }
648
649    /// Build a single element [`LargeListViewArray`] and wrap as [`ScalarValue::LargeListView`]
650    pub fn build_large_list_view_scalar(self) -> ScalarValue {
651        ScalarValue::LargeListView(Arc::new(self.build_large_list_view_array()))
652    }
653
654    /// Helper function: convert this builder into a tuple of field and array
655    fn into_field_and_arr(self) -> (Arc<Field>, ArrayRef) {
656        let Self {
657            arr,
658            nullable,
659            field_name,
660        } = self;
661        let data_type = arr.data_type().to_owned();
662        let field = match field_name {
663            Some(name) => Field::new(name, data_type, nullable),
664            None => Field::new_list_field(data_type, nullable),
665        };
666        (Arc::new(field), arr)
667    }
668}
669
670/// Wrap arrays into a single element `ListArray`.
671///
672/// Example:
673/// ```
674/// use arrow::array::{Int32Array, ListArray, ArrayRef};
675/// use arrow::datatypes::{Int32Type, Field};
676/// use std::sync::Arc;
677///
678/// let arr1 = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
679/// let arr2 = Arc::new(Int32Array::from(vec![4, 5, 6])) as ArrayRef;
680///
681/// let list_arr = datafusion_common::utils::arrays_into_list_array([arr1, arr2]).unwrap();
682///
683/// let expected = ListArray::from_iter_primitive::<Int32Type, _, _>(
684///    vec![
685///     Some(vec![Some(1), Some(2), Some(3)]),
686///     Some(vec![Some(4), Some(5), Some(6)]),
687///    ]
688/// );
689///
690/// assert_eq!(list_arr, expected);
691/// ```
692pub fn arrays_into_list_array(
693    arr: impl IntoIterator<Item = ArrayRef>,
694) -> Result<ListArray> {
695    let arr = arr.into_iter().collect::<Vec<_>>();
696    assert_or_internal_err!(!arr.is_empty(), "Cannot wrap empty array into list array");
697
698    let lens = arr.iter().map(|x| x.len()).collect::<Vec<_>>();
699    // Assume data type is consistent
700    let data_type = arr[0].data_type().to_owned();
701    let values = arr.iter().map(|x| x.as_ref()).collect::<Vec<_>>();
702    Ok(ListArray::new(
703        Arc::new(Field::new_list_field(data_type, true)),
704        OffsetBuffer::from_lengths(lens),
705        arrow::compute::concat(values.as_slice())?,
706        None,
707    ))
708}
709
710/// Helper function to convert a ListArray into a vector of ArrayRefs.
711pub fn list_to_arrays<O: OffsetSizeTrait>(a: &ArrayRef) -> Vec<ArrayRef> {
712    a.as_list::<O>().iter().flatten().collect::<Vec<_>>()
713}
714
715/// Helper function to convert a FixedSizeListArray into a vector of ArrayRefs.
716pub fn fixed_size_list_to_arrays(a: &ArrayRef) -> Vec<ArrayRef> {
717    a.as_fixed_size_list().iter().flatten().collect::<Vec<_>>()
718}
719
720/// Get the base type of a data type.
721///
722/// Example
723/// ```
724/// use arrow::datatypes::{DataType, Field};
725/// use datafusion_common::utils::base_type;
726/// use std::sync::Arc;
727///
728/// let data_type =
729///     DataType::List(Arc::new(Field::new_list_field(DataType::Int32, true)));
730/// assert_eq!(base_type(&data_type), DataType::Int32);
731///
732/// let data_type = DataType::Int32;
733/// assert_eq!(base_type(&data_type), DataType::Int32);
734/// ```
735pub fn base_type(data_type: &DataType) -> DataType {
736    match data_type {
737        DataType::List(field)
738        | DataType::LargeList(field)
739        | DataType::ListView(field)
740        | DataType::LargeListView(field)
741        | DataType::FixedSizeList(field, _) => base_type(field.data_type()),
742        _ => data_type.to_owned(),
743    }
744}
745
746// TODO: Modify this to also allow specifying how listviews should be treated.
747//       For example if cast to List (default) or maintain as ListView (requires
748//       function to implement support for ListViews)
749//       https://github.com/apache/datafusion/issues/21777
750/// Information about how to coerce lists.
751#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
752pub enum ListCoercion {
753    /// [`DataType::FixedSizeList`] should be coerced to [`DataType::List`].
754    FixedSizedListToList,
755}
756
757/// A helper function to coerce base type in List.
758///
759/// Example
760/// ```
761/// use arrow::datatypes::{DataType, Field};
762/// use datafusion_common::utils::coerced_type_with_base_type_only;
763/// use std::sync::Arc;
764///
765/// let data_type = DataType::List(Arc::new(Field::new_list_field(DataType::Int32, true)));
766/// let base_type = DataType::Float64;
767/// let coerced_type = coerced_type_with_base_type_only(&data_type, &base_type, None);
768/// assert_eq!(coerced_type, DataType::List(Arc::new(Field::new_list_field(DataType::Float64, true))));
769/// ```
770pub fn coerced_type_with_base_type_only(
771    data_type: &DataType,
772    base_type: &DataType,
773    array_coercion: Option<&ListCoercion>,
774) -> DataType {
775    match (data_type, array_coercion) {
776        (DataType::List(field), _)
777        | (DataType::FixedSizeList(field, _), Some(ListCoercion::FixedSizedListToList)) =>
778        {
779            let field_type = coerced_type_with_base_type_only(
780                field.data_type(),
781                base_type,
782                array_coercion,
783            );
784
785            DataType::List(Arc::new(Field::new(
786                field.name(),
787                field_type,
788                field.is_nullable(),
789            )))
790        }
791        (DataType::FixedSizeList(field, len), _) => {
792            let field_type = coerced_type_with_base_type_only(
793                field.data_type(),
794                base_type,
795                array_coercion,
796            );
797
798            DataType::FixedSizeList(
799                Arc::new(Field::new(field.name(), field_type, field.is_nullable())),
800                *len,
801            )
802        }
803        (DataType::ListView(field), _) => {
804            let field_type = coerced_type_with_base_type_only(
805                field.data_type(),
806                base_type,
807                array_coercion,
808            );
809
810            DataType::ListView(Arc::new(Field::new(
811                field.name(),
812                field_type,
813                field.is_nullable(),
814            )))
815        }
816        (DataType::LargeList(field), _) => {
817            let field_type = coerced_type_with_base_type_only(
818                field.data_type(),
819                base_type,
820                array_coercion,
821            );
822
823            DataType::LargeList(Arc::new(Field::new(
824                field.name(),
825                field_type,
826                field.is_nullable(),
827            )))
828        }
829        (DataType::LargeListView(field), _) => {
830            let field_type = coerced_type_with_base_type_only(
831                field.data_type(),
832                base_type,
833                array_coercion,
834            );
835
836            DataType::LargeListView(Arc::new(Field::new(
837                field.name(),
838                field_type,
839                field.is_nullable(),
840            )))
841        }
842
843        _ => base_type.clone(),
844    }
845}
846
847/// Recursively coerce and `FixedSizeList` elements to `List`
848pub fn coerced_fixed_size_list_to_list(data_type: &DataType) -> DataType {
849    match data_type {
850        DataType::List(field) | DataType::FixedSizeList(field, _) => {
851            let field_type = coerced_fixed_size_list_to_list(field.data_type());
852
853            DataType::List(Arc::new(Field::new(
854                field.name(),
855                field_type,
856                field.is_nullable(),
857            )))
858        }
859        DataType::ListView(field) => {
860            let field_type = coerced_fixed_size_list_to_list(field.data_type());
861
862            DataType::ListView(Arc::new(Field::new(
863                field.name(),
864                field_type,
865                field.is_nullable(),
866            )))
867        }
868        DataType::LargeList(field) => {
869            let field_type = coerced_fixed_size_list_to_list(field.data_type());
870
871            DataType::LargeList(Arc::new(Field::new(
872                field.name(),
873                field_type,
874                field.is_nullable(),
875            )))
876        }
877        DataType::LargeListView(field) => {
878            let field_type = coerced_fixed_size_list_to_list(field.data_type());
879
880            DataType::LargeListView(Arc::new(Field::new(
881                field.name(),
882                field_type,
883                field.is_nullable(),
884            )))
885        }
886
887        _ => data_type.clone(),
888    }
889}
890
891/// Compute the number of dimensions in a list data type.
892pub fn list_ndims(data_type: &DataType) -> u64 {
893    match data_type {
894        DataType::List(field)
895        | DataType::LargeList(field)
896        | DataType::ListView(field)
897        | DataType::LargeListView(field)
898        | DataType::FixedSizeList(field, _) => 1 + list_ndims(field.data_type()),
899        _ => 0,
900    }
901}
902
903/// Adopted from strsim-rs for string similarity metrics
904pub mod datafusion_strsim {
905    // Source: https://github.com/dguo/strsim-rs/blob/master/src/lib.rs
906    // License: https://github.com/dguo/strsim-rs/blob/master/LICENSE
907    use std::cmp::min;
908    use std::str::Chars;
909
910    struct StringWrapper<'a>(&'a str);
911
912    impl<'b> IntoIterator for &StringWrapper<'b> {
913        type Item = char;
914        type IntoIter = Chars<'b>;
915
916        fn into_iter(self) -> Self::IntoIter {
917            self.0.chars()
918        }
919    }
920
921    /// Calculates the minimum number of insertions, deletions, and substitutions
922    /// required to change one sequence into the other, using a reusable cache buffer.
923    ///
924    /// This is the generic implementation that works with any iterator types.
925    /// The `cache` buffer will be resized as needed and reused across calls.
926    fn generic_levenshtein_with_buffer<'a, 'b, Iter1, Iter2, Elem1, Elem2>(
927        a: &'a Iter1,
928        b: &'b Iter2,
929        cache: &mut Vec<usize>,
930    ) -> usize
931    where
932        &'a Iter1: IntoIterator<Item = Elem1>,
933        &'b Iter2: IntoIterator<Item = Elem2>,
934        Elem1: PartialEq<Elem2>,
935    {
936        let b_len = b.into_iter().count();
937
938        if a.into_iter().next().is_none() {
939            return b_len;
940        }
941
942        // Resize cache to fit b_len elements
943        cache.clear();
944        cache.extend(1..=b_len);
945
946        let mut result = 0;
947
948        for (i, a_elem) in a.into_iter().enumerate() {
949            result = i + 1;
950            let mut distance_b = i;
951
952            for (j, b_elem) in b.into_iter().enumerate() {
953                let cost = if a_elem == b_elem { 0usize } else { 1usize };
954                let distance_a = distance_b + cost;
955                distance_b = cache[j];
956                result = min(result + 1, min(distance_a, distance_b + 1));
957                cache[j] = result;
958            }
959        }
960
961        result
962    }
963
964    /// Calculates the minimum number of insertions, deletions, and substitutions
965    /// required to change one sequence into the other.
966    fn generic_levenshtein<'a, 'b, Iter1, Iter2, Elem1, Elem2>(
967        a: &'a Iter1,
968        b: &'b Iter2,
969    ) -> usize
970    where
971        &'a Iter1: IntoIterator<Item = Elem1>,
972        &'b Iter2: IntoIterator<Item = Elem2>,
973        Elem1: PartialEq<Elem2>,
974    {
975        let mut cache = Vec::new();
976        generic_levenshtein_with_buffer(a, b, &mut cache)
977    }
978
979    /// Calculates the minimum number of insertions, deletions, and substitutions
980    /// required to change one string into the other.
981    ///
982    /// ```
983    /// use datafusion_common::utils::datafusion_strsim::levenshtein;
984    ///
985    /// assert_eq!(3, levenshtein("kitten", "sitting"));
986    /// ```
987    pub fn levenshtein(a: &str, b: &str) -> usize {
988        generic_levenshtein(&StringWrapper(a), &StringWrapper(b))
989    }
990
991    /// Calculates the Levenshtein distance using a reusable cache buffer.
992    /// This avoids allocating a new Vec for each call, improving performance
993    /// when computing many distances.
994    ///
995    /// The `cache` buffer will be resized as needed and reused across calls.
996    pub fn levenshtein_with_buffer(a: &str, b: &str, cache: &mut Vec<usize>) -> usize {
997        generic_levenshtein_with_buffer(&StringWrapper(a), &StringWrapper(b), cache)
998    }
999
1000    /// Calculates the normalized Levenshtein distance between two strings.
1001    /// The normalized distance is a value between 0.0 and 1.0, where 1.0 indicates
1002    /// that the strings are identical and 0.0 indicates no similarity.
1003    ///
1004    /// ```
1005    /// use datafusion_common::utils::datafusion_strsim::normalized_levenshtein;
1006    ///
1007    /// assert!((normalized_levenshtein("kitten", "sitting") - 0.57142).abs() < 0.00001);
1008    ///
1009    /// assert!(normalized_levenshtein("", "second").abs() < 0.00001);
1010    ///
1011    /// assert!((normalized_levenshtein("kitten", "sitten") - 0.833).abs() < 0.001);
1012    /// ```
1013    pub fn normalized_levenshtein(a: &str, b: &str) -> f64 {
1014        if a.is_empty() && b.is_empty() {
1015            return 1.0;
1016        }
1017        1.0 - (levenshtein(a, b) as f64)
1018            / (a.chars().count().max(b.chars().count()) as f64)
1019    }
1020}
1021
1022/// Merges collections `first` and `second`, removes duplicates and sorts the
1023/// result, returning it as a [`Vec`].
1024pub fn merge_and_order_indices<T: Borrow<usize>, S: Borrow<usize>>(
1025    first: impl IntoIterator<Item = T>,
1026    second: impl IntoIterator<Item = S>,
1027) -> Vec<usize> {
1028    let mut result: Vec<_> = first
1029        .into_iter()
1030        .map(|e| *e.borrow())
1031        .chain(second.into_iter().map(|e| *e.borrow()))
1032        .collect::<HashSet<_>>()
1033        .into_iter()
1034        .collect();
1035    result.sort();
1036    result
1037}
1038
1039/// Calculates the set difference between sequences `first` and `second`,
1040/// returning the result as a [`Vec`]. Preserves the ordering of `first`.
1041pub fn set_difference<T: Borrow<usize>, S: Borrow<usize>>(
1042    first: impl IntoIterator<Item = T>,
1043    second: impl IntoIterator<Item = S>,
1044) -> Vec<usize> {
1045    let set: HashSet<_> = second.into_iter().map(|e| *e.borrow()).collect();
1046    first
1047        .into_iter()
1048        .map(|e| *e.borrow())
1049        .filter(|e| !set.contains(e))
1050        .collect()
1051}
1052
1053/// Find indices of each element in `targets` inside `items`. If one of the
1054/// elements is absent in `items`, returns an error.
1055pub fn find_indices<T: PartialEq, S: Borrow<T>>(
1056    items: &[T],
1057    targets: impl IntoIterator<Item = S>,
1058) -> Result<Vec<usize>> {
1059    targets
1060        .into_iter()
1061        .map(|target| items.iter().position(|e| target.borrow().eq(e)))
1062        .collect::<Option<_>>()
1063        .ok_or_else(|| _exec_datafusion_err!("Target not found"))
1064}
1065
1066/// Transposes the given vector of vectors.
1067pub fn transpose<T>(original: Vec<Vec<T>>) -> Vec<Vec<T>> {
1068    match original.as_slice() {
1069        [] => vec![],
1070        [first, ..] => {
1071            let mut result = (0..first.len()).map(|_| vec![]).collect::<Vec<_>>();
1072            for row in original {
1073                for (item, transposed_row) in row.into_iter().zip(&mut result) {
1074                    transposed_row.push(item);
1075                }
1076            }
1077            result
1078        }
1079    }
1080}
1081
1082/// Computes the `skip` and `fetch` parameters of a single limit that would be
1083/// equivalent to two consecutive limits with the given `skip`/`fetch` parameters.
1084///
1085/// There are multiple cases to consider:
1086///
1087/// # Case 0: Parent and child are disjoint (`child_fetch <= skip`).
1088///
1089/// ```text
1090///   Before merging:
1091///                     |........skip........|---fetch-->|     Parent limit
1092///    |...child_skip...|---child_fetch-->|                    Child limit
1093/// ```
1094///
1095///   After merging:
1096/// ```text
1097///    |.........(child_skip + skip).........|
1098/// ```
1099///
1100/// # Case 1: Parent is beyond child's range (`skip < child_fetch <= skip + fetch`).
1101///
1102///   Before merging:
1103/// ```text
1104///                     |...skip...|------------fetch------------>|   Parent limit
1105///    |...child_skip...|-------------child_fetch------------>|       Child limit
1106/// ```
1107///
1108///   After merging:
1109/// ```text
1110///    |....(child_skip + skip)....|---(child_fetch - skip)-->|
1111/// ```
1112///
1113///  # Case 2: Parent is within child's range (`skip + fetch < child_fetch`).
1114///
1115///   Before merging:
1116/// ```text
1117///                     |...skip...|---fetch-->|                   Parent limit
1118///    |...child_skip...|-------------child_fetch------------>|    Child limit
1119/// ```
1120///
1121///   After merging:
1122/// ```text
1123///    |....(child_skip + skip)....|---fetch-->|
1124/// ```
1125pub fn combine_limit(
1126    parent_skip: usize,
1127    parent_fetch: Option<usize>,
1128    child_skip: usize,
1129    child_fetch: Option<usize>,
1130) -> (usize, Option<usize>) {
1131    let combined_skip = child_skip.saturating_add(parent_skip);
1132
1133    let combined_fetch = match (parent_fetch, child_fetch) {
1134        (Some(parent_fetch), Some(child_fetch)) => {
1135            Some(min(parent_fetch, child_fetch.saturating_sub(parent_skip)))
1136        }
1137        (Some(parent_fetch), None) => Some(parent_fetch),
1138        (None, Some(child_fetch)) => Some(child_fetch.saturating_sub(parent_skip)),
1139        (None, None) => None,
1140    };
1141
1142    (combined_skip, combined_fetch)
1143}
1144
1145/// Returns the estimated number of threads available for parallel execution.
1146///
1147/// This is a wrapper around `std::thread::available_parallelism`, providing a default value
1148/// of `1` if the system's parallelism cannot be determined.
1149///
1150/// The result is cached after the first call.
1151pub fn get_available_parallelism() -> usize {
1152    static PARALLELISM: LazyLock<usize> = LazyLock::new(|| {
1153        available_parallelism()
1154            .unwrap_or(NonZero::new(1).expect("literal value `1` shouldn't be zero"))
1155            .get()
1156    });
1157    *PARALLELISM
1158}
1159
1160/// Converts a collection of function arguments into a fixed-size array of length N
1161/// producing a reasonable error message in case of unexpected number of arguments.
1162///
1163/// # Example
1164/// ```
1165/// # use datafusion_common::Result;
1166/// # use datafusion_common::utils::take_function_args;
1167/// # use datafusion_common::ScalarValue;
1168/// fn my_function(args: &[ScalarValue]) -> Result<()> {
1169///     // function expects 2 args, so create a 2-element array
1170///     let [arg1, arg2] = take_function_args("my_function", args)?;
1171///     // ... do stuff..
1172///     Ok(())
1173/// }
1174///
1175/// // Calling the function with 1 argument produces an error:
1176/// let args = vec![ScalarValue::Int32(Some(10))];
1177/// let err = my_function(&args).unwrap_err();
1178/// assert_eq!(
1179///     err.to_string(),
1180///     "Execution error: my_function function requires 2 arguments, got 1"
1181/// );
1182/// // Calling the function with 2 arguments works great
1183/// let args = vec![ScalarValue::Int32(Some(10)), ScalarValue::Int32(Some(20))];
1184/// my_function(&args).unwrap();
1185/// ```
1186pub fn take_function_args<const N: usize, T>(
1187    function_name: &str,
1188    args: impl IntoIterator<Item = T>,
1189) -> Result<[T; N]> {
1190    let args = args.into_iter().collect::<Vec<_>>();
1191    args.try_into().map_err(|v: Vec<T>| {
1192        _exec_datafusion_err!(
1193            "{} function requires {} {}, got {}",
1194            function_name,
1195            N,
1196            if N == 1 { "argument" } else { "arguments" },
1197            v.len()
1198        )
1199    })
1200}
1201
1202/// Returns the inner values of a list, or an error otherwise
1203/// For [`ListArray`] and [`LargeListArray`], if it's sliced, it returns a
1204/// sliced array too. Therefore, too reconstruct a list using it,
1205/// you must adjust the offsets using [`adjust_offsets_for_slice`]
1206pub fn list_values(array: &dyn Array) -> Result<ArrayRef> {
1207    match array.data_type() {
1208        DataType::List(_) => Ok(sliced_list_values(array.as_list::<i32>())),
1209        DataType::LargeList(_) => Ok(sliced_list_values(array.as_list::<i64>())),
1210        DataType::FixedSizeList(_, _) => {
1211            Ok(Arc::clone(array.as_fixed_size_list().values()))
1212        }
1213        other => _exec_err!("expected list, got {other}"),
1214    }
1215}
1216
1217fn sliced_list_values<O: OffsetSizeTrait>(list: &GenericListArray<O>) -> ArrayRef {
1218    let values = list.values();
1219    let offsets = list.offsets();
1220
1221    if let (Some(first), Some(last)) = (offsets.first(), offsets.last()) {
1222        let first = first.as_usize();
1223        let last = last.as_usize();
1224
1225        if first != 0 || last != values.len() {
1226            return values.slice(first, last - first);
1227        }
1228    }
1229
1230    Arc::clone(values)
1231}
1232
1233/// If `list` is sliced, returns an adjusted offset buffer so that
1234/// it points to the sliced portion of the list values, and not the whole list values
1235pub fn adjust_offsets_for_slice<O: OffsetSizeTrait>(
1236    list: &GenericListArray<O>,
1237) -> OffsetBuffer<O> {
1238    let offsets = list.offsets();
1239
1240    offsets.clone().subtract(offsets[0])
1241}
1242
1243/// For lists and large lists, truncates the sublist of null values
1244/// Otherwise returns an error
1245pub fn remove_list_null_values(array: &ArrayRef) -> Result<ArrayRef> {
1246    // todo: handle list view and map
1247    match array.data_type() {
1248        DataType::List(_) => Ok(Arc::new(truncate_list_nulls(array.as_list::<i32>())?)),
1249        DataType::LargeList(_) => {
1250            Ok(Arc::new(truncate_list_nulls(array.as_list::<i64>())?))
1251        }
1252        dt => _exec_err!("expected List or LargeList, got {dt}"),
1253    }
1254}
1255
1256/// Create a new list array where all the nulls point to empty lists
1257fn truncate_list_nulls<O: OffsetSizeTrait>(
1258    list: &GenericListArray<O>,
1259) -> Result<GenericListArray<O>> {
1260    if let Some(nulls) = list.nulls()
1261        && nulls.null_count() > 0
1262    {
1263        let lengths = length(list)?;
1264        let zero: &dyn Datum = if lengths.data_type() == &DataType::Int32 {
1265            &Int32Array::new_scalar(0)
1266        } else {
1267            &Int64Array::new_scalar(0)
1268        };
1269
1270        let (mut valid_or_empty, _nulls) = eq(&lengths, zero)?.into_parts();
1271        valid_or_empty |= nulls.inner();
1272        let valid_or_empty = BooleanArray::from(valid_or_empty);
1273
1274        if valid_or_empty.has_false() {
1275            let array_data = list.values().to_data();
1276            let offsets = list.offsets();
1277            let capacity = offsets[offsets.len() - 1] - offsets[0];
1278            let mut mutable_array_data =
1279                MutableArrayData::new(vec![&array_data], false, capacity.as_usize());
1280
1281            let (valid_or_empty, _nulls) = valid_or_empty.into_parts();
1282
1283            for (start, end) in valid_or_empty.set_slices() {
1284                mutable_array_data.try_extend(
1285                    0,
1286                    offsets[start].as_usize(),
1287                    offsets[end].as_usize(),
1288                )?;
1289            }
1290
1291            let lengths = std::iter::zip(offsets.lengths(), nulls)
1292                .map(|(length, is_valid)| if is_valid { length } else { 0 });
1293
1294            let offsets = OffsetBuffer::from_lengths(lengths);
1295            let values = make_array(mutable_array_data.freeze());
1296
1297            let field = match list.data_type() {
1298                DataType::List(field) => field,
1299                DataType::LargeList(field) => field,
1300                _ => unreachable!(),
1301            };
1302
1303            return Ok(GenericListArray::try_new(
1304                Arc::clone(field),
1305                offsets,
1306                values,
1307                list.nulls().cloned(),
1308            )?);
1309        }
1310    }
1311    Ok(list.clone())
1312}
1313
1314/// If `array` is a list or a map, returns a new array of the same length as it's inner values
1315/// where each value is the 1-based index of the sublist it's contained. Example:
1316///
1317/// `[[1], [2, 3], [4, 5, 6]] =>  [1, 2, 2, 3, 3, 3]`
1318///
1319/// Otherwise returns an error
1320pub fn list_values_row_number(array: &dyn Array) -> Result<ArrayRef> {
1321    match array.data_type() {
1322        DataType::List(_) => Ok(Arc::new(variable_size_list_values_row_number::<
1323            Int32Type,
1324        >(array.as_list().offsets()))),
1325        DataType::LargeList(_) => Ok(Arc::new(variable_size_list_values_row_number::<
1326            Int64Type,
1327        >(array.as_list().offsets()))),
1328        DataType::ListView(_) => Ok(Arc::new(variable_size_list_values_row_number::<
1329            Int32Type,
1330        >(array.as_list_view().offsets()))),
1331        DataType::LargeListView(_) => {
1332            Ok(Arc::new(variable_size_list_values_row_number::<Int64Type>(
1333                array.as_list_view().offsets(),
1334            )))
1335        }
1336        DataType::FixedSizeList(_, _) => {
1337            let fixed_size_list = array.as_fixed_size_list();
1338
1339            Ok(Arc::new(fsl_values_row_number(
1340                fixed_size_list.value_length(),
1341                fixed_size_list.len(),
1342            )?))
1343        }
1344        DataType::Map(_, _) => Ok(Arc::new(variable_size_list_values_row_number::<
1345            Int32Type,
1346        >(array.as_map().offsets()))),
1347        other => _exec_err!("expected list, got {other}"),
1348    }
1349}
1350
1351/// [0, 2, 2, 5, 6] -> [0, 0, 2, 2, 2, 3]
1352fn variable_size_list_values_row_number<T: ArrowPrimitiveType>(
1353    offsets: &[T::Native],
1354) -> PrimitiveArray<T> {
1355    let mut rows_number = Vec::with_capacity(
1356        offsets[offsets.len() - 1].to_usize().unwrap() - offsets[0].to_usize().unwrap(),
1357    );
1358
1359    for (i, w) in offsets.windows(2).enumerate() {
1360        let len = w[1].as_usize() - w[0].as_usize();
1361        rows_number.extend(repeat_n(T::Native::usize_as(i), len));
1362    }
1363
1364    PrimitiveArray::new(rows_number.into(), None)
1365}
1366
1367/// (2, 3) -> [0, 0, 1, 1, 2, 2]
1368fn fsl_values_row_number(list_size: i32, array_len: usize) -> Result<Int32Array> {
1369    let list_size = list_size.to_usize().ok_or_else(|| {
1370        _exec_datafusion_err!("fsl_values_index: invalid list_size {list_size}")
1371    })?;
1372
1373    let mut rows_number = Vec::with_capacity(list_size * array_len);
1374
1375    for i in 0..array_len {
1376        rows_number.extend(repeat_n(i as i32, list_size));
1377    }
1378
1379    Ok(PrimitiveArray::new(rows_number.into(), None))
1380}
1381
1382/// Replace `-0.0` with `+0.0` in any `Float16`, `Float32`, or `Float64` array.
1383/// For non-float arrays returns the input unchanged. NaN payloads are
1384/// preserved.
1385///
1386/// Arrow's comparison kernels (`arrow::compute::kernels::cmp::eq` etc.) and
1387/// row-encoding (`arrow::row::RowConverter`) use IEEE 754 totalOrder
1388/// semantics, which treats `-0.0` and `+0.0` as distinct. SQL semantics
1389/// (PostgreSQL / IEEE 754 equality) require them to compare equal, so
1390/// callers normalize before invoking those kernels.
1391///
1392/// The common case - no `-0.0` present - is allocation-free: a single
1393/// read-only scan of the underlying buffer (auto-vectorizable to an
1394/// OR-reduction) decides whether to fall through to the rewriting path.
1395/// Only arrays that actually contain `-0.0` pay for a new buffer.
1396pub fn normalize_float_zero(array: &ArrayRef) -> ArrayRef {
1397    use arrow::array::{Float16Array, Float32Array, Float64Array};
1398    use arrow::datatypes::{Float16Type, Float32Type, Float64Type};
1399    // -0.0 has only the sign bit set; no other finite or NaN value shares
1400    // this bit pattern, so a strict-equality scan reliably gates the rewrite.
1401    const NEG_ZERO_F16_BITS: u16 = half::f16::NEG_ZERO.to_bits();
1402    const NEG_ZERO_F32_BITS: u32 = (-0.0_f32).to_bits();
1403    const NEG_ZERO_F64_BITS: u64 = (-0.0_f64).to_bits();
1404    match array.data_type() {
1405        DataType::Float32 => {
1406            let arr: &Float32Array = array.as_primitive::<Float32Type>();
1407            if !arr
1408                .values()
1409                .iter()
1410                .any(|v| v.to_bits() == NEG_ZERO_F32_BITS)
1411            {
1412                return Arc::clone(array);
1413            }
1414            let normalized: Float32Array =
1415                arr.unary(|v| if v.to_bits() << 1 == 0 { 0.0_f32 } else { v });
1416            Arc::new(normalized)
1417        }
1418        DataType::Float64 => {
1419            let arr: &Float64Array = array.as_primitive::<Float64Type>();
1420            if !arr
1421                .values()
1422                .iter()
1423                .any(|v| v.to_bits() == NEG_ZERO_F64_BITS)
1424            {
1425                return Arc::clone(array);
1426            }
1427            let normalized: Float64Array =
1428                arr.unary(|v| if v.to_bits() << 1 == 0 { 0.0_f64 } else { v });
1429            Arc::new(normalized)
1430        }
1431        DataType::Float16 => {
1432            let arr: &Float16Array = array.as_primitive::<Float16Type>();
1433            if !arr
1434                .values()
1435                .iter()
1436                .any(|v| v.to_bits() == NEG_ZERO_F16_BITS)
1437            {
1438                return Arc::clone(array);
1439            }
1440            let normalized: Float16Array = arr.unary(|v| {
1441                if v.to_bits() << 1 == 0 {
1442                    half::f16::from_bits(0)
1443                } else {
1444                    v
1445                }
1446            });
1447            Arc::new(normalized)
1448        }
1449        _ => Arc::clone(array),
1450    }
1451}
1452
1453/// Replace `-0.0` with `+0.0` in `Float16`, `Float32`, or `Float64` scalar
1454/// values. Other variants are returned unchanged. See [`normalize_float_zero`]
1455/// for context.
1456pub fn normalize_float_zero_scalar(scalar: ScalarValue) -> ScalarValue {
1457    match scalar {
1458        ScalarValue::Float32(Some(v)) if v.to_bits() << 1 == 0 => {
1459            ScalarValue::Float32(Some(0.0))
1460        }
1461        ScalarValue::Float64(Some(v)) if v.to_bits() << 1 == 0 => {
1462            ScalarValue::Float64(Some(0.0))
1463        }
1464        ScalarValue::Float16(Some(v)) if v.to_bits() << 1 == 0 => {
1465            ScalarValue::Float16(Some(half::f16::from_bits(0)))
1466        }
1467        other => other,
1468    }
1469}
1470
1471#[cfg(test)]
1472mod tests {
1473    use std::sync::Arc;
1474
1475    use super::*;
1476    use crate::ScalarValue::Null;
1477    use arrow::{
1478        array::{Float64Array, Int32Array},
1479        buffer::NullBuffer,
1480        datatypes::Int32Type,
1481    };
1482    #[cfg(feature = "sql")]
1483    use sqlparser::ast::Ident;
1484
1485    #[test]
1486    fn test_bisect_linear_left_and_right() -> Result<()> {
1487        let arrays: Vec<ArrayRef> = vec![
1488            Arc::new(Float64Array::from(vec![5.0, 7.0, 8.0, 9., 10.])),
1489            Arc::new(Float64Array::from(vec![2.0, 3.0, 3.0, 4.0, 5.0])),
1490            Arc::new(Float64Array::from(vec![5.0, 7.0, 8.0, 10., 11.0])),
1491            Arc::new(Float64Array::from(vec![15.0, 13.0, 8.0, 5., 0.0])),
1492        ];
1493        let search_tuple: Vec<ScalarValue> = vec![
1494            ScalarValue::Float64(Some(8.0)),
1495            ScalarValue::Float64(Some(3.0)),
1496            ScalarValue::Float64(Some(8.0)),
1497            ScalarValue::Float64(Some(8.0)),
1498        ];
1499        let ords = [
1500            SortOptions {
1501                descending: false,
1502                nulls_first: true,
1503            },
1504            SortOptions {
1505                descending: false,
1506                nulls_first: true,
1507            },
1508            SortOptions {
1509                descending: false,
1510                nulls_first: true,
1511            },
1512            SortOptions {
1513                descending: true,
1514                nulls_first: true,
1515            },
1516        ];
1517        let res = bisect::<true>(&arrays, &search_tuple, &ords)?;
1518        assert_eq!(res, 2);
1519        let res = bisect::<false>(&arrays, &search_tuple, &ords)?;
1520        assert_eq!(res, 3);
1521        let res = linear_search::<true>(&arrays, &search_tuple, &ords)?;
1522        assert_eq!(res, 2);
1523        let res = linear_search::<false>(&arrays, &search_tuple, &ords)?;
1524        assert_eq!(res, 3);
1525        Ok(())
1526    }
1527
1528    #[test]
1529    fn vector_ord() {
1530        assert!(vec![1, 0, 0, 0, 0, 0, 0, 1] < vec![1, 0, 0, 0, 0, 0, 0, 2]);
1531        assert!(vec![1, 0, 0, 0, 0, 0, 1, 1] > vec![1, 0, 0, 0, 0, 0, 0, 2]);
1532        assert!(
1533            vec![
1534                ScalarValue::Int32(Some(2)),
1535                Null,
1536                ScalarValue::Int32(Some(0)),
1537            ] < vec![
1538                ScalarValue::Int32(Some(2)),
1539                Null,
1540                ScalarValue::Int32(Some(1)),
1541            ]
1542        );
1543        assert!(
1544            vec![
1545                ScalarValue::Int32(Some(2)),
1546                ScalarValue::Int32(None),
1547                ScalarValue::Int32(Some(0)),
1548            ] < vec![
1549                ScalarValue::Int32(Some(2)),
1550                ScalarValue::Int32(None),
1551                ScalarValue::Int32(Some(1)),
1552            ]
1553        );
1554    }
1555
1556    #[test]
1557    fn ord_same_type() {
1558        assert!((ScalarValue::Int32(Some(2)) < ScalarValue::Int32(Some(3))));
1559    }
1560
1561    #[test]
1562    fn test_bisect_linear_left_and_right_diff_sort() -> Result<()> {
1563        // Descending, left
1564        let arrays: Vec<ArrayRef> =
1565            vec![Arc::new(Float64Array::from(vec![4.0, 3.0, 2.0, 1.0, 0.0]))];
1566        let search_tuple: Vec<ScalarValue> = vec![ScalarValue::Float64(Some(4.0))];
1567        let ords = [SortOptions {
1568            descending: true,
1569            nulls_first: true,
1570        }];
1571        let res = bisect::<true>(&arrays, &search_tuple, &ords)?;
1572        assert_eq!(res, 0);
1573        let res = linear_search::<true>(&arrays, &search_tuple, &ords)?;
1574        assert_eq!(res, 0);
1575
1576        // Descending, right
1577        let arrays: Vec<ArrayRef> =
1578            vec![Arc::new(Float64Array::from(vec![4.0, 3.0, 2.0, 1.0, 0.0]))];
1579        let search_tuple: Vec<ScalarValue> = vec![ScalarValue::Float64(Some(4.0))];
1580        let ords = [SortOptions {
1581            descending: true,
1582            nulls_first: true,
1583        }];
1584        let res = bisect::<false>(&arrays, &search_tuple, &ords)?;
1585        assert_eq!(res, 1);
1586        let res = linear_search::<false>(&arrays, &search_tuple, &ords)?;
1587        assert_eq!(res, 1);
1588
1589        // Ascending, left
1590        let arrays: Vec<ArrayRef> =
1591            vec![Arc::new(Float64Array::from(vec![5.0, 7.0, 8.0, 9., 10.]))];
1592        let search_tuple: Vec<ScalarValue> = vec![ScalarValue::Float64(Some(7.0))];
1593        let ords = [SortOptions {
1594            descending: false,
1595            nulls_first: true,
1596        }];
1597        let res = bisect::<true>(&arrays, &search_tuple, &ords)?;
1598        assert_eq!(res, 1);
1599        let res = linear_search::<true>(&arrays, &search_tuple, &ords)?;
1600        assert_eq!(res, 1);
1601
1602        // Ascending, right
1603        let arrays: Vec<ArrayRef> =
1604            vec![Arc::new(Float64Array::from(vec![5.0, 7.0, 8.0, 9., 10.]))];
1605        let search_tuple: Vec<ScalarValue> = vec![ScalarValue::Float64(Some(7.0))];
1606        let ords = [SortOptions {
1607            descending: false,
1608            nulls_first: true,
1609        }];
1610        let res = bisect::<false>(&arrays, &search_tuple, &ords)?;
1611        assert_eq!(res, 2);
1612        let res = linear_search::<false>(&arrays, &search_tuple, &ords)?;
1613        assert_eq!(res, 2);
1614
1615        let arrays: Vec<ArrayRef> = vec![
1616            Arc::new(Float64Array::from(vec![5.0, 7.0, 8.0, 8.0, 9., 10.])),
1617            Arc::new(Float64Array::from(vec![10.0, 9.0, 8.0, 7.5, 7., 6.])),
1618        ];
1619        let search_tuple: Vec<ScalarValue> = vec![
1620            ScalarValue::Float64(Some(8.0)),
1621            ScalarValue::Float64(Some(8.0)),
1622        ];
1623        let ords = [
1624            SortOptions {
1625                descending: false,
1626                nulls_first: true,
1627            },
1628            SortOptions {
1629                descending: true,
1630                nulls_first: true,
1631            },
1632        ];
1633        let res = bisect::<false>(&arrays, &search_tuple, &ords)?;
1634        assert_eq!(res, 3);
1635        let res = linear_search::<false>(&arrays, &search_tuple, &ords)?;
1636        assert_eq!(res, 3);
1637
1638        let res = bisect::<true>(&arrays, &search_tuple, &ords)?;
1639        assert_eq!(res, 2);
1640        let res = linear_search::<true>(&arrays, &search_tuple, &ords)?;
1641        assert_eq!(res, 2);
1642        Ok(())
1643    }
1644
1645    #[test]
1646    fn test_evaluate_partition_ranges() -> Result<()> {
1647        let arrays: Vec<ArrayRef> = vec![
1648            Arc::new(Float64Array::from(vec![1.0, 1.0, 1.0, 2.0, 2.0, 2.0])),
1649            Arc::new(Float64Array::from(vec![4.0, 4.0, 3.0, 2.0, 1.0, 1.0])),
1650        ];
1651        let n_row = arrays[0].len();
1652        let options: Vec<SortOptions> = vec![
1653            SortOptions {
1654                descending: false,
1655                nulls_first: false,
1656            },
1657            SortOptions {
1658                descending: true,
1659                nulls_first: false,
1660            },
1661        ];
1662        let sort_columns = arrays
1663            .into_iter()
1664            .zip(options)
1665            .map(|(values, options)| SortColumn {
1666                values,
1667                options: Some(options),
1668            })
1669            .collect::<Vec<_>>();
1670        let ranges = evaluate_partition_ranges(n_row, &sort_columns)?;
1671        assert_eq!(ranges.len(), 4);
1672        assert_eq!(ranges[0], Range { start: 0, end: 2 });
1673        assert_eq!(ranges[1], Range { start: 2, end: 3 });
1674        assert_eq!(ranges[2], Range { start: 3, end: 4 });
1675        assert_eq!(ranges[3], Range { start: 4, end: 6 });
1676        Ok(())
1677    }
1678
1679    #[cfg(feature = "sql")]
1680    #[test]
1681    fn test_quote_identifier() -> Result<()> {
1682        let cases = vec![
1683            ("foo", r#"foo"#),
1684            ("_foo", r#"_foo"#),
1685            ("foo_bar", r#"foo_bar"#),
1686            ("foo-bar", r#""foo-bar""#),
1687            // name itself has a period, needs to be quoted
1688            ("foo.bar", r#""foo.bar""#),
1689            ("Foo", r#""Foo""#),
1690            ("Foo.Bar", r#""Foo.Bar""#),
1691            // name starting with a number needs to be quoted
1692            ("test1", r#"test1"#),
1693            ("1test", r#""1test""#),
1694        ];
1695
1696        for (identifier, quoted_identifier) in cases {
1697            println!("input: \n{identifier}\nquoted_identifier:\n{quoted_identifier}");
1698
1699            assert_eq!(quote_identifier(identifier), quoted_identifier);
1700
1701            // When parsing the quoted identifier, it should be a
1702            // a single identifier without normalization, and not in multiple parts
1703            let quote_style = if quoted_identifier.starts_with('"') {
1704                Some('"')
1705            } else {
1706                None
1707            };
1708
1709            let expected_parsed = vec![Ident {
1710                value: identifier.to_string(),
1711                quote_style,
1712                span: sqlparser::tokenizer::Span::empty(),
1713            }];
1714
1715            assert_eq!(
1716                parse_identifiers(quoted_identifier).unwrap(),
1717                expected_parsed
1718            );
1719        }
1720
1721        Ok(())
1722    }
1723
1724    #[test]
1725    fn test_get_at_indices() -> Result<()> {
1726        let in_vec = vec![1, 2, 3, 4, 5, 6, 7];
1727        assert_eq!(get_at_indices(&in_vec, [0, 2])?, vec![1, 3]);
1728        assert_eq!(get_at_indices(&in_vec, [4, 2])?, vec![5, 3]);
1729        // 7 is outside the range
1730        assert!(get_at_indices(&in_vec, [7]).is_err());
1731        Ok(())
1732    }
1733
1734    #[test]
1735    fn test_longest_consecutive_prefix() {
1736        assert_eq!(longest_consecutive_prefix([0, 3, 4]), 1);
1737        assert_eq!(longest_consecutive_prefix([0, 1, 3, 4]), 2);
1738        assert_eq!(longest_consecutive_prefix([0, 1, 2, 3, 4]), 5);
1739        assert_eq!(longest_consecutive_prefix([1, 2, 3, 4]), 0);
1740    }
1741
1742    #[test]
1743    fn test_merge_and_order_indices() {
1744        assert_eq!(
1745            merge_and_order_indices([0, 3, 4], [1, 3, 5]),
1746            vec![0, 1, 3, 4, 5]
1747        );
1748        // Result should be ordered, even if inputs are not
1749        assert_eq!(
1750            merge_and_order_indices([3, 0, 4], [5, 1, 3]),
1751            vec![0, 1, 3, 4, 5]
1752        );
1753    }
1754
1755    #[test]
1756    fn test_set_difference() {
1757        assert_eq!(set_difference([0, 3, 4], [1, 2]), vec![0, 3, 4]);
1758        assert_eq!(set_difference([0, 3, 4], [1, 2, 4]), vec![0, 3]);
1759        // return value should have same ordering with the in1
1760        assert_eq!(set_difference([3, 4, 0], [1, 2, 4]), vec![3, 0]);
1761        assert_eq!(set_difference([0, 3, 4], [4, 1, 2]), vec![0, 3]);
1762        assert_eq!(set_difference([3, 4, 0], [4, 1, 2]), vec![3, 0]);
1763    }
1764
1765    #[test]
1766    fn test_find_indices() -> Result<()> {
1767        assert_eq!(find_indices(&[0, 3, 4], [0, 3, 4])?, vec![0, 1, 2]);
1768        assert_eq!(find_indices(&[0, 3, 4], [0, 4, 3])?, vec![0, 2, 1]);
1769        assert_eq!(find_indices(&[3, 0, 4], [0, 3])?, vec![1, 0]);
1770        assert!(find_indices(&[0, 3], [0, 3, 4]).is_err());
1771        assert!(find_indices(&[0, 3, 4], [0, 2]).is_err());
1772        Ok(())
1773    }
1774
1775    #[test]
1776    fn test_transpose() -> Result<()> {
1777        let in_data = vec![vec![1, 2, 3], vec![4, 5, 6]];
1778        let transposed = transpose(in_data);
1779        let expected = vec![vec![1, 4], vec![2, 5], vec![3, 6]];
1780        assert_eq!(expected, transposed);
1781        Ok(())
1782    }
1783
1784    #[test]
1785    fn test_sliced_list_values() {
1786        let data = vec![
1787            Some(vec![Some(0), Some(1), Some(2)]),
1788            None,
1789            Some(vec![Some(3), None, Some(5)]),
1790            Some(vec![Some(6), Some(7)]),
1791        ];
1792
1793        let list = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1794
1795        assert_eq!(
1796            sliced_list_values(&list).as_primitive(),
1797            &Int32Array::from(vec![
1798                Some(0),
1799                Some(1),
1800                Some(2),
1801                Some(3),
1802                None,
1803                Some(5),
1804                Some(6),
1805                Some(7)
1806            ])
1807        );
1808
1809        assert_eq!(
1810            sliced_list_values(&list.slice(0, 1)).as_primitive(),
1811            &Int32Array::from(vec![Some(0), Some(1), Some(2)])
1812        );
1813
1814        assert_eq!(
1815            sliced_list_values(&list.slice(2, 1)).as_primitive(),
1816            &Int32Array::from(vec![Some(3), None, Some(5)])
1817        );
1818
1819        assert_eq!(
1820            sliced_list_values(&list.slice(3, 1)).as_primitive(),
1821            &Int32Array::from(vec![Some(6), Some(7)])
1822        );
1823
1824        assert!(sliced_list_values(&list.slice(0, 0)).is_empty());
1825        assert!(sliced_list_values(&list.slice(1, 0)).is_empty());
1826        assert!(sliced_list_values(&list.slice(3, 0)).is_empty());
1827    }
1828
1829    #[test]
1830    fn test_adjust_offsets() {
1831        let data = vec![
1832            Some(vec![Some(0), Some(1), Some(2)]),
1833            None,
1834            Some(vec![Some(3), None, Some(5)]),
1835            Some(vec![Some(6), Some(7)]),
1836        ];
1837        let list = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1838
1839        assert_eq!(
1840            adjust_offsets_for_slice(&list),
1841            OffsetBuffer::from_lengths([3, 0, 3, 2])
1842        );
1843
1844        assert_eq!(
1845            adjust_offsets_for_slice(&list.slice(0, 1)),
1846            OffsetBuffer::from_lengths([3])
1847        );
1848
1849        assert_eq!(
1850            adjust_offsets_for_slice(&list.slice(1, 2)),
1851            OffsetBuffer::from_lengths([0, 3])
1852        );
1853
1854        assert_eq!(
1855            adjust_offsets_for_slice(&list.slice(1, 3)),
1856            OffsetBuffer::from_lengths([0, 3, 2])
1857        );
1858
1859        assert_eq!(
1860            adjust_offsets_for_slice(&list.slice(0, 0)),
1861            OffsetBuffer::from_lengths([])
1862        );
1863
1864        assert_eq!(
1865            adjust_offsets_for_slice(&list.slice(1, 0)),
1866            OffsetBuffer::from_lengths([])
1867        );
1868
1869        assert_eq!(
1870            adjust_offsets_for_slice(&list.slice(3, 0)),
1871            OffsetBuffer::from_lengths([])
1872        );
1873    }
1874
1875    fn create_i32_list(
1876        values: impl Into<Int32Array>,
1877        offsets: OffsetBuffer<i32>,
1878        nulls: Option<NullBuffer>,
1879    ) -> ListArray {
1880        let list_field = Arc::new(Field::new_list_field(DataType::Int32, true));
1881
1882        ListArray::new(list_field, offsets, Arc::new(values.into()), nulls)
1883    }
1884
1885    #[test]
1886    fn test_remove_list_null_values_list() {
1887        let list = Arc::new(create_i32_list(
1888            vec![100, 20, 10, 0, 0, 0, 0, 1, 50],
1889            OffsetBuffer::<i32>::from_lengths(vec![3, 4, 0, 2, 0]),
1890            Some(NullBuffer::from(vec![true, false, false, true, false])),
1891        )) as ArrayRef;
1892
1893        let res = remove_list_null_values(&list).unwrap();
1894        let res = res.as_list::<i32>();
1895
1896        let expected = Arc::new(create_i32_list(
1897            vec![100, 20, 10, 1, 50],
1898            OffsetBuffer::<i32>::from_lengths(vec![3, 0, 0, 2, 0]),
1899            Some(NullBuffer::from(vec![true, false, false, true, false])),
1900        )) as ArrayRef;
1901        let expected = expected.as_list::<i32>();
1902
1903        assert_eq!(res, expected);
1904        // check above skips inner value of nulls
1905        assert_eq!(res.values(), expected.values());
1906        assert_eq!(res.offsets(), expected.offsets());
1907    }
1908
1909    #[test]
1910    fn test_list_array_values_row_number() {
1911        assert_eq!(
1912            variable_size_list_values_row_number::<Int32Type>(
1913                &OffsetBuffer::from_lengths([1, 3, 0, 2,])
1914            ),
1915            Int32Array::from(vec![0, 1, 1, 1, 3, 3])
1916        );
1917
1918        assert_eq!(
1919            variable_size_list_values_row_number::<Int32Type>(
1920                &OffsetBuffer::from_lengths([])
1921            ),
1922            Int32Array::new_null(0)
1923        );
1924
1925        assert_eq!(
1926            variable_size_list_values_row_number::<Int32Type>(
1927                &OffsetBuffer::from_lengths([0])
1928            ),
1929            Int32Array::new_null(0)
1930        );
1931
1932        assert_eq!(
1933            variable_size_list_values_row_number::<Int32Type>(
1934                &OffsetBuffer::from_lengths([0, 0])
1935            ),
1936            Int32Array::new_null(0)
1937        );
1938
1939        assert_eq!(
1940            variable_size_list_values_row_number::<Int32Type>(
1941                &OffsetBuffer::from_lengths([1])
1942            ),
1943            Int32Array::from(vec![0])
1944        );
1945
1946        assert_eq!(
1947            variable_size_list_values_row_number::<Int32Type>(
1948                &OffsetBuffer::from_lengths([2])
1949            ),
1950            Int32Array::from(vec![0, 0])
1951        );
1952    }
1953
1954    #[test]
1955    fn test_fsl_values_row_number() {
1956        assert_eq!(
1957            fsl_values_row_number(2, 3).unwrap(),
1958            Int32Array::from(vec![0, 0, 1, 1, 2, 2])
1959        );
1960
1961        assert_eq!(
1962            fsl_values_row_number(1, 3).unwrap(),
1963            Int32Array::from(vec![0, 1, 2])
1964        );
1965
1966        assert_eq!(
1967            fsl_values_row_number(2, 1).unwrap(),
1968            Int32Array::from(vec![0, 0])
1969        );
1970
1971        assert_eq!(
1972            fsl_values_row_number(2, 0).unwrap(),
1973            Int32Array::new_null(0),
1974        );
1975
1976        assert_eq!(
1977            fsl_values_row_number(0, 2).unwrap(),
1978            Int32Array::new_null(0),
1979        );
1980
1981        assert_eq!(
1982            fsl_values_row_number(0, 0).unwrap(),
1983            Int32Array::new_null(0),
1984        );
1985
1986        fsl_values_row_number(-1, 2).unwrap_err();
1987        fsl_values_row_number(-1, 0).unwrap_err();
1988    }
1989}