Skip to main content

rudb_kernels/
lists.rs

1//! The list functions that look inside a list: searching it, deduplicating it, picking from it and
2//! reshaping it.
3//!
4//! `list_position`, `list_contains`, `list_has_any`, `list_has_all`, `list_distinct`,
5//! `list_unique`, `list_intersect`, `list_where`, `list_select`, `list_reverse`, `list_sort`,
6//! `list_reverse_sort`, `flatten` and `list_resize`. The binder has already cast every list to one
7//! element type and every argument to what it has to be, so nothing here converts a value, and each
8//! answer was read off the pin case by case.
9//!
10//! Three of them answer something other than null for a null argument and are called above the
11//! null rule. `list_position(l, NULL)` finds the first null element, since the search is `IS NOT
12//! DISTINCT FROM` and not `=`, `list_resize(l, NULL)` is the empty list, and so is
13//! `list_intersect(l, NULL)`. Everything else is null in and null out.
14//!
15//! Values are compared with [`order`], the one ordering every other operator uses, so a list of
16//! doubles deduplicates `-0.0` and `0.0` the way a `GROUP BY` does. The pin keeps the elements of
17//! `list_distinct` and `list_intersect` in the order of its hash table, which is not an order a
18//! caller can rely on and is not one rudb copies. Both keep the order of first appearance here,
19//! which is one of the orders the pin could have given.
20
21use std::cmp::Ordering;
22use std::collections::HashSet;
23
24use rudb_common::{Error, LogicalType, Result, Value};
25use rudb_vector::{Buffer, Data, Live, Validity, Vector, interleave};
26
27use crate::aggregate::{Accumulator, NOWHERE, finish_run, update_runs, update_scattered};
28use crate::compare::order;
29use crate::datetime;
30use crate::number::integral;
31
32/// What the pin says when the mask of `list_where` or the indexes of `list_select` hold a null.
33const NULL_PICK: &str = "NULLs are not allowed as list elements in the second input parameter.";
34
35/// The answer for a call that has to see its null arguments, or `None` for any other call.
36pub(crate) fn before_nulls(
37    name: &str,
38    args: &[Value],
39    returns: &LogicalType,
40) -> Option<Result<Value>> {
41    Some(match (name, args) {
42        ("list_position", [Value::Null, _]) => Ok(Value::Null),
43        ("list_position", [Value::List { values, .. }, needle]) => position(values, needle),
44        ("list_resize" | "list_intersect", [Value::Null, ..]) => Ok(Value::Null),
45        ("list_intersect", [Value::List { .. }, Value::Null]) => listed(Vec::new(), returns),
46        ("list_resize", [Value::List { values, .. }, size, filler @ ..]) => {
47            resize(values, size, filler.first().unwrap_or(&Value::Null), returns)
48        }
49        _ => return None,
50    })
51}
52
53/// The answer for a call none of whose arguments is null, or `None` for a name that is not here.
54pub(crate) fn value(name: &str, args: &[Value], returns: &LogicalType) -> Option<Result<Value>> {
55    let list = |values| listed(values, returns);
56    Some(match (name, args) {
57        ("list_contains", [Value::List { values, .. }, needle]) => {
58            found(values, needle).map(|at| Value::Boolean(at.is_some()))
59        }
60        ("list_has_any", [Value::List { values, .. }, Value::List { values: wanted, .. }]) => {
61            has_any(values, wanted).map(Value::Boolean)
62        }
63        ("list_has_all", [Value::List { values, .. }, Value::List { values: wanted, .. }]) => {
64            has_any_missing(values, wanted).map(|missing| Value::Boolean(!missing))
65        }
66        ("list_distinct", [Value::List { values, .. }]) => distinct(values).and_then(&list),
67        ("list_unique", [Value::List { values, .. }]) => {
68            distinct(values).map(|kept| Value::UBigInt(kept.len() as u64))
69        }
70        ("list_intersect", [Value::List { values, .. }, Value::List { values: other, .. }]) => {
71            intersect(values, other).and_then(&list)
72        }
73        ("list_where", [Value::List { values, .. }, Value::List { values: mask, .. }]) => {
74            masked(values, mask).and_then(&list)
75        }
76        ("list_select", [Value::List { values, .. }, Value::List { values: indexes, .. }]) => {
77            selected(values, indexes).and_then(&list)
78        }
79        ("list_sort", [Value::List { values, .. }, spelled @ ..]) => {
80            let order = spelled.first().map(spelled_order).transpose();
81            let nulls = spelled.get(1).map(spelled_nulls).transpose();
82            match (order, nulls) {
83                (Ok(order), Ok(nulls)) => {
84                    sort(values, order.unwrap_or(false), nulls.unwrap_or(false)).and_then(list)
85                }
86                (Err(error), _) | (_, Err(error)) => Err(error),
87            }
88        }
89        ("range" | "generate_series", _) => ranged(name == "generate_series", args).and_then(list),
90        ("list_grade_up", [Value::List { values, .. }, spelled @ ..]) => {
91            let order = spelled.first().map(spelled_order).transpose();
92            let nulls = spelled.get(1).map(spelled_nulls).transpose();
93            match (order, nulls) {
94                (Ok(order), Ok(nulls)) => {
95                    graded(values, order.unwrap_or(false), nulls.unwrap_or(false)).and_then(list)
96                }
97                (Err(error), _) | (_, Err(error)) => Err(error),
98            }
99        }
100        ("list_reverse_sort", [Value::List { values, .. }, spelled @ ..]) => {
101            match spelled.first().map(spelled_nulls).transpose() {
102                Ok(nulls) => sort(values, true, nulls.unwrap_or(false)).and_then(list),
103                Err(error) => Err(error),
104            }
105        }
106        ("list_reverse", [Value::List { values, .. }]) => {
107            list(values.iter().rev().cloned().collect())
108        }
109        ("flatten", [Value::List { values, .. }]) => {
110            let mut flat = Vec::new();
111            for inner in values {
112                if let Value::List { values: held, .. } = inner {
113                    flat.extend(held.iter().cloned());
114                }
115            }
116            list(flat)
117        }
118        _ => return None,
119    })
120}
121
122/// A list of the element type the call answers in.
123fn listed(values: Vec<Value>, returns: &LogicalType) -> Result<Value> {
124    let LogicalType::List(element) = returns else {
125        return Err(Error::internal(format!("a list function returning {returns}")));
126    };
127    Ok(Value::List { element: (**element).clone(), values })
128}
129
130/// `range` and `generate_series` as scalars: the series from the start toward the stop as a list.
131///
132/// `generate_series` takes the stop when a step lands on it and `range` stops short of it. One
133/// argument is the stop, with a start of zero and a step of one. A step of zero, or one that points
134/// away from the stop, is an empty list rather than an error, which is the pin's answer.
135fn ranged(inclusive: bool, args: &[Value]) -> Result<Vec<Value>> {
136    if let [start, stop, Value::Interval { months, days, micros }] = args {
137        return stepped(inclusive, start, stop, (*months, *days, *micros));
138    }
139    let whole = |value: &Value| {
140        integral(value)
141            .and_then(|held| i64::try_from(held).ok())
142            .ok_or_else(|| Error::internal(format!("a range over a {}", value.logical_type())))
143    };
144    let (start, stop, step) = match args {
145        [stop] => (0, whole(stop)?, 1),
146        [start, stop] => (whole(start)?, whole(stop)?, 1),
147        [start, stop, step] => (whole(start)?, whole(stop)?, whole(step)?),
148        _ => return Err(Error::internal(format!("a range over {} arguments", args.len()))),
149    };
150    let count = series_length(start, stop, step, inclusive)?;
151    // Every value is between the start and the stop, both of which are BIGINTs, so none of these
152    // can leave the type.
153    let mut at = start;
154    let mut values = Vec::with_capacity(count);
155    // row at a time: this is the scalar form of range for one constant call, which hands back a
156    // list value, and the vector form over columns writes its child directly without this loop.
157    for _ in 0..count {
158        values.push(Value::BigInt(at));
159        at = at.wrapping_add(step);
160    }
161    Ok(values)
162}
163
164/// How many values an integer series has, counted wide so the gap between the two ends of BIGINT
165/// does not overflow.
166fn series_length(start: i64, stop: i64, step: i64, inclusive: bool) -> Result<usize> {
167    if step == 0 || (start > stop && step > 0) || (start < stop && step < 0) {
168        return Ok(0);
169    }
170    let apart = stop.abs_diff(start);
171    let by = step.unsigned_abs();
172    // A step of one is nearly every series written, and it needs no division at all.
173    let (whole, over) =
174        if by == 1 { (apart, false) } else { (apart / by, !apart.is_multiple_of(by)) };
175    let count = u128::from(whole) + u128::from(inclusive || over);
176    usize::try_from(count).ok().filter(|&count| count <= MAX_SERIES).ok_or_else(too_long)
177}
178
179/// A series of moments, each one the last with the interval added, which is how the pin steps and
180/// why a step of a month from the thirty first lands where adding a month would.
181fn stepped(
182    inclusive: bool,
183    start: &Value,
184    stop: &Value,
185    interval: (i32, i32, i64),
186) -> Result<Vec<Value>> {
187    let moment = |value: &Value| match value {
188        Value::Timestamp(stamp) | Value::TimestampTz(stamp) => Ok(*stamp),
189        other => Err(Error::internal(format!("a range from a {}", other.logical_type()))),
190    };
191    let mut stamps = Vec::new();
192    step_stamps(inclusive, moment(start)?, moment(stop)?, interval, &mut stamps)?;
193    let zoned = matches!(start, Value::TimestampTz(_));
194    Ok(stamps
195        .into_iter()
196        .map(|stamp| if zoned { Value::TimestampTz(stamp) } else { Value::Timestamp(stamp) })
197        .collect())
198}
199
200/// Appends the series of moments from `start` toward `end` to `out` and says how many it added.
201///
202/// An interval that is neither forward nor backward is an empty series, and one that is both is
203/// refused, which are the pin's two answers.
204fn step_stamps(
205    inclusive: bool,
206    start: i64,
207    end: i64,
208    (months, days, micros): (i32, i32, i64),
209    out: &mut Vec<i64>,
210) -> Result<usize> {
211    let forward = months > 0 || days > 0 || micros > 0;
212    let backward = months < 0 || days < 0 || micros < 0;
213    if forward && backward {
214        return Err(Error::invalid_input(
215            "Interval with mix of negative/positive entries not supported",
216        ));
217    }
218    // The two infinities are the two ends of the `i64`, less one at the bottom as upstream has it.
219    if [start, end].iter().any(|&stamp| stamp == i64::MAX || stamp == -i64::MAX) {
220        return Err(Error::invalid_input("Interval infinite bounds not supported"));
221    }
222    let from = out.len();
223    if !forward && !backward {
224        return Ok(0);
225    }
226    // Without months every step is the same number of microseconds, so the series is counted and
227    // written the way an integer one is, and every moment in it is between the start and the end.
228    let whole = i128::from(days) * i128::from(datetime::MICROS_PER_DAY) + i128::from(micros);
229    if let (0, Ok(step)) = (months, i64::try_from(whole)) {
230        let count = series_length(start, end, step, inclusive)?;
231        let steps = i64::try_from(count).map_err(|_| too_long())?;
232        out.reserve(count);
233        out.extend((0..steps).map(|at| start.wrapping_add(at.wrapping_mul(step))));
234        return Ok(count);
235    }
236    let (months, days, micros) = (i64::from(months), i64::from(days), i128::from(micros));
237    let mut at = start;
238    loop {
239        let past = if forward { at > end } else { at < end };
240        if past || (at == end && !inclusive) {
241            return Ok(out.len() - from);
242        }
243        if out.len() - from == MAX_SERIES {
244            return Err(too_long());
245        }
246        let next = datetime::shifted_stamp(at, months, days, micros)?;
247        out.push(at);
248        at = next;
249    }
250}
251
252/// A series of moments as the table form of `range` hands it out, one position at a time.
253#[derive(Debug, Clone, PartialEq, Eq)]
254pub enum Stepping {
255    /// Every step the same number of microseconds, so a position is worked out and not kept.
256    Even {
257        /// The moment at position zero.
258        start: i64,
259        /// Microseconds between one moment and the next.
260        step: i64,
261        /// How many moments there are.
262        count: usize,
263    },
264    /// A step with months in it, walked on the calendar and kept.
265    Listed(Vec<i64>),
266}
267
268impl Stepping {
269    /// How many moments there are.
270    #[must_use]
271    pub fn len(&self) -> usize {
272        match self {
273            Self::Even { count, .. } => *count,
274            Self::Listed(stamps) => stamps.len(),
275        }
276    }
277
278    /// Whether there are none.
279    #[must_use]
280    pub fn is_empty(&self) -> bool {
281        self.len() == 0
282    }
283
284    /// The moment at a position, which is below [`Self::len`].
285    #[must_use]
286    pub fn at(&self, position: usize) -> i64 {
287        match self {
288            Self::Even { start, step, .. } => {
289                let steps = i64::try_from(position).unwrap_or(i64::MAX);
290                start.wrapping_add(steps.wrapping_mul(*step))
291            }
292            Self::Listed(stamps) => stamps[position],
293        }
294    }
295}
296
297/// The moments from `start` toward `end` by `interval`, for the table form of `range` and
298/// `generate_series`, which checks the interval itself because it words the refusals differently.
299///
300/// # Errors
301///
302/// A series past 2^32 moments, and a moment the calendar cannot reach.
303pub fn moment_steps(
304    inclusive: bool,
305    start: i64,
306    end: i64,
307    interval: (i32, i32, i64),
308) -> Result<Stepping> {
309    let (months, days, micros) = interval;
310    let whole = i128::from(days) * i128::from(datetime::MICROS_PER_DAY) + i128::from(micros);
311    if let (0, Ok(step)) = (months, i64::try_from(whole)) {
312        return Ok(Stepping::Even {
313            start,
314            step,
315            count: series_length(start, end, step, inclusive)?,
316        });
317    }
318    let mut stamps = Vec::new();
319    step_stamps(inclusive, start, end, interval, &mut stamps)?;
320    Ok(Stepping::Listed(stamps))
321}
322
323/// The longest list the pin builds for a series, which is the most entries a list can hold.
324const MAX_SERIES: usize = u32::MAX as usize;
325
326/// The pin's refusal of a series longer than [`MAX_SERIES`].
327fn too_long() -> Error {
328    Error::invalid_input("Lists larger than 2^32 elements are not supported")
329}
330
331/// Whether two values are the same value, with a null the same as another null.
332fn same(left: &Value, right: &Value) -> Result<bool> {
333    Ok(match (left.is_null(), right.is_null()) {
334        (true, true) => true,
335        (true, false) | (false, true) => false,
336        (false, false) => order(left, right)? == Ordering::Equal,
337    })
338}
339
340/// Where `needle` first is in `values`, nulls matching nulls.
341fn found(values: &[Value], needle: &Value) -> Result<Option<usize>> {
342    for (at, value) in values.iter().enumerate() {
343        if same(value, needle)? {
344            return Ok(Some(at));
345        }
346    }
347    Ok(None)
348}
349
350/// `list_position`, one based, or null when the value is not there.
351fn position(values: &[Value], needle: &Value) -> Result<Value> {
352    Ok(match found(values, needle)? {
353        Some(at) => Value::Integer(i32::try_from(at + 1).map_err(|_| {
354            Error::out_of_range(format!("a list position of {} does not fit in INTEGER", at + 1))
355        })?),
356        None => Value::Null,
357    })
358}
359
360/// The values that are not null, sorted, so that a lookup is a binary search.
361fn sorted(values: &[Value]) -> Result<Vec<&Value>> {
362    let mut held: Vec<&Value> = values.iter().filter(|value| !value.is_null()).collect();
363    let mut failed = None;
364    held.sort_by(|left, right| {
365        order(left, right).unwrap_or_else(|error| {
366            failed.get_or_insert(error);
367            Ordering::Equal
368        })
369    });
370    match failed {
371        Some(error) => Err(error),
372        None => Ok(held),
373    }
374}
375
376/// Whether `needle`, which is not null, is in `haystack`, which [`sorted`] made.
377fn contains(haystack: &[&Value], needle: &Value) -> Result<bool> {
378    let mut failed = None;
379    let hit = haystack
380        .binary_search_by(|probe| {
381            order(probe, needle).unwrap_or_else(|error| {
382                failed.get_or_insert(error);
383                Ordering::Equal
384            })
385        })
386        .is_ok();
387    match failed {
388        Some(error) => Err(error),
389        None => Ok(hit),
390    }
391}
392
393/// `list_has_any`: whether some value that is not null is in both lists.
394fn has_any(values: &[Value], wanted: &[Value]) -> Result<bool> {
395    let haystack = sorted(values)?;
396    for value in wanted.iter().filter(|value| !value.is_null()) {
397        if contains(&haystack, value)? {
398            return Ok(true);
399        }
400    }
401    Ok(false)
402}
403
404/// Whether some value of `wanted` that is not null is missing from `values`, which is `list_has_all`
405/// turned over. A null in `wanted` is not asked about, so `list_has_all([1], [NULL])` is true.
406fn has_any_missing(values: &[Value], wanted: &[Value]) -> Result<bool> {
407    let haystack = sorted(values)?;
408    for value in wanted.iter().filter(|value| !value.is_null()) {
409        if !contains(&haystack, value)? {
410            return Ok(true);
411        }
412    }
413    Ok(false)
414}
415
416/// The values that are not null, each once, in the order they first appear.
417fn distinct(values: &[Value]) -> Result<Vec<Value>> {
418    let mut at: Vec<usize> = (0..values.len()).filter(|&at| !values[at].is_null()).collect();
419    let mut failed = None;
420    // Sorted by value and then by position, so the first of each run of equal values is the one
421    // that appeared first.
422    at.sort_by(|&left, &right| match order(&values[left], &values[right]) {
423        Ok(Ordering::Equal) => left.cmp(&right),
424        Ok(ordering) => ordering,
425        Err(error) => {
426            failed.get_or_insert(error);
427            Ordering::Equal
428        }
429    });
430    if let Some(error) = failed {
431        return Err(error);
432    }
433    let mut kept = Vec::with_capacity(at.len());
434    for (index, &here) in at.iter().enumerate() {
435        if index == 0 || order(&values[at[index - 1]], &values[here])? != Ordering::Equal {
436            kept.push(here);
437        }
438    }
439    kept.sort_unstable();
440    Ok(kept.into_iter().map(|at| values[at].clone()).collect())
441}
442
443/// `list_intersect`: the values of the first list that are also in the second, each once.
444fn intersect(values: &[Value], other: &[Value]) -> Result<Vec<Value>> {
445    let haystack = sorted(other)?;
446    let mut kept = Vec::new();
447    for value in distinct(values)? {
448        if contains(&haystack, &value)? {
449            kept.push(value);
450        }
451    }
452    Ok(kept)
453}
454
455/// `list_where`: the values whose place in the mask is true. A mask longer than the list picks
456/// nulls past its end, so `list_where([1], [true, true])` is `[1, NULL]`.
457fn masked(values: &[Value], mask: &[Value]) -> Result<Vec<Value>> {
458    let mut kept = Vec::new();
459    for (at, flag) in mask.iter().enumerate() {
460        match flag {
461            Value::Boolean(true) => kept.push(values.get(at).cloned().unwrap_or(Value::Null)),
462            Value::Boolean(false) => {}
463            Value::Null => return Err(Error::invalid_input(NULL_PICK)),
464            other => {
465                return Err(Error::internal(format!(
466                    "list_where with a {} mask",
467                    other.logical_type()
468                )));
469            }
470        }
471    }
472    Ok(kept)
473}
474
475/// `list_select`: the values at the given one based places, and a null for a place that is not in
476/// the list. A negative place does not count from the end here, unlike a subscript.
477fn selected(values: &[Value], indexes: &[Value]) -> Result<Vec<Value>> {
478    let mut kept = Vec::with_capacity(indexes.len());
479    for index in indexes {
480        if index.is_null() {
481            return Err(Error::invalid_input(NULL_PICK));
482        }
483        let picked = index
484            .as_i64()
485            .and_then(|index| usize::try_from(index).ok())
486            .and_then(|index| index.checked_sub(1))
487            .and_then(|at| values.get(at));
488        kept.push(picked.cloned().unwrap_or(Value::Null));
489    }
490    Ok(kept)
491}
492
493/// `list_resize`: the list cut or padded to `size`, padding with `filler`. A null size is the empty
494/// list, which is the pin's answer and not a null one.
495fn resize(values: &[Value], size: &Value, filler: &Value, returns: &LogicalType) -> Result<Value> {
496    let size = match size {
497        Value::Null => 0,
498        Value::UBigInt(size) => usize::try_from(*size).map_err(|_| {
499            Error::out_of_range(format!("a list of {size} elements is too long to build"))
500        })?,
501        other => {
502            return Err(Error::internal(format!("list_resize to a {}", other.logical_type())));
503        }
504    };
505    let element = match returns {
506        LogicalType::List(element) => element,
507        _ => &LogicalType::Null,
508    };
509    let width = element.physical().size().max(1);
510    if (size as u128) * (width as u128) > MAX_VECTOR_BYTES {
511        return Err(Error::out_of_range(format!(
512            "Cannot resize vector to {size} rows: maximum allowed vector size is 128.0 GiB"
513        )));
514    }
515    let mut kept: Vec<Value> = values.iter().take(size).cloned().collect();
516    kept.resize(size, filler.clone());
517    listed(kept, returns)
518}
519
520/// The most bytes the pin lets one vector hold. A `list_resize` past it is refused before anything
521/// is allocated, so a size of a few quintillion is an error and not an abort.
522const MAX_VECTOR_BYTES: u128 = 1 << 37;
523
524/// Whether a sort order spelled out as a string is descending.
525fn spelled_order(spelled: &Value) -> Result<bool> {
526    let spelled = spelled.to_string().to_uppercase();
527    match spelled.as_str() {
528        "ASC" | "ASCENDING" | "DEFAULT" | "ORDER_DEFAULT" => Ok(false),
529        "DESC" | "DESCENDING" => Ok(true),
530        _ => Err(unrecognized(&spelled, "OrderType")),
531    }
532}
533
534/// Whether a null order spelled out as a string puts the nulls first.
535fn spelled_nulls(spelled: &Value) -> Result<bool> {
536    let spelled = spelled.to_string().to_uppercase();
537    match spelled.as_str() {
538        "NULLS FIRST" | "NULLS_FIRST" => Ok(true),
539        "NULLS LAST" | "NULLS_LAST" | "DEFAULT" | "ORDER_DEFAULT" => Ok(false),
540        _ => Err(unrecognized(&spelled, "OrderByNullType")),
541    }
542}
543
544/// The pin's refusal of a name that is not one of an enum's values. The pin follows it with a line
545/// of candidates picked by how close they are to what was written, which is left out here.
546fn unrecognized(spelled: &str, kind: &str) -> Error {
547    Error::not_implemented(format!(
548        "Enum value: unrecognized value \"{spelled}\" for enum \"{kind}\""
549    ))
550}
551
552/// `list_sort`: the values in order, with the nulls kept together at one end.
553fn sort(values: &[Value], descending: bool, nulls_first: bool) -> Result<Vec<Value>> {
554    Ok(grade(values, descending, nulls_first)?.into_iter().map(|at| values[at].clone()).collect())
555}
556
557/// `list_grade_up`: the one based place of each value in the order `list_sort` would put it.
558fn graded(values: &[Value], descending: bool, nulls_first: bool) -> Result<Vec<Value>> {
559    grade(values, descending, nulls_first)?
560        .into_iter()
561        .map(|at| {
562            Ok(Value::BigInt(
563                i64::try_from(at + 1).map_err(|error| Error::internal(error.to_string()))?,
564            ))
565        })
566        .collect()
567}
568
569/// The places of the values in sorted order, with the nulls kept together at one end.
570///
571/// The nulls go last unless asked otherwise whichever way the rest are sorted, which is the pin's
572/// default and not the reverse of an ascending sort. The sort is stable, so equal values keep the
573/// order they came in, which is what makes the grade of a list with repeats the pin's.
574fn grade(values: &[Value], descending: bool, nulls_first: bool) -> Result<Vec<usize>> {
575    let (mut held, nulls): (Vec<usize>, Vec<usize>) =
576        (0..values.len()).partition(|&at| !values[at].is_null());
577    let mut failed = None;
578    held.sort_by(|&left, &right| {
579        let ordering = order(&values[left], &values[right]).unwrap_or_else(|error| {
580            failed.get_or_insert(error);
581            Ordering::Equal
582        });
583        if descending { ordering.reverse() } else { ordering }
584    });
585    if let Some(error) = failed {
586        return Err(error);
587    }
588    Ok(if nulls_first { [nulls, held].concat() } else { [held, nulls].concat() })
589}
590
591/// A loop over whole vectors for the list calls that have one, or `None` for a call that goes
592/// through the row at a time path.
593///
594/// A list vector is entries over one child, so building a list, reversing one or searching one for
595/// a constant can be a gather or a scan of the child with no `Value` made for any row. These are
596/// the calls that were furthest behind the pin when measured, and each one here gives the same
597/// answer as its arm in [`value`], which the tests in the facade check row for row.
598pub(crate) fn vectorized<V: AsRef<Vector>>(
599    name: &str,
600    args: &[V],
601    returns: &LogicalType,
602    rows: usize,
603) -> Result<Option<Vector>> {
604    match (name, args) {
605        ("list_value", [_, ..]) => built(args, returns, rows),
606        ("range" | "generate_series", [_, ..]) => {
607            series(name == "generate_series", args, returns, rows)
608        }
609        ("list_aggr", [list, aggregate]) => aggregated(list.as_ref(), aggregate.as_ref(), returns),
610        ("list_reverse", [list]) => reversed(list.as_ref()),
611        ("length" | "array_length", [list]) => counted(list.as_ref()),
612        ("list_distinct", [list]) => deduplicated(false, list.as_ref()),
613        ("list_unique", [list]) => deduplicated(true, list.as_ref()),
614        ("list_contains" | "list_position", [list, needle]) => {
615            searched(name == "list_position", list.as_ref(), needle.as_ref())
616        }
617        ("list_sort" | "list_grade_up", [list, spelled @ ..]) => ordered(
618            list.as_ref(),
619            spelled.first().map(AsRef::as_ref),
620            spelled.get(1).map(AsRef::as_ref),
621            false,
622            name == "list_grade_up",
623        ),
624        ("list_reverse_sort", [list, spelled @ ..]) => {
625            ordered(list.as_ref(), None, spelled.first().map(AsRef::as_ref), true, false)
626        }
627        _ => Ok(None),
628    }
629}
630
631/// `list_value` over columns: every argument laid end to end and read back a row at a time.
632///
633/// Left to the row path when the element is nested, because laying a nested column is a row at a
634/// time there too, or when an argument is not already of the element type.
635fn built<V: AsRef<Vector>>(
636    args: &[V],
637    returns: &LogicalType,
638    rows: usize,
639) -> Result<Option<Vector>> {
640    let LogicalType::List(element) = returns else {
641        return Ok(None);
642    };
643    if nested_or_null(element) || args.iter().any(|arg| arg.as_ref().logical_type() != &**element) {
644        return Ok(None);
645    }
646    // flatten: the interleave copies every element into one child by position, and it reads flat
647    // values, so each argument is one copy either way.
648    let pieces = args.iter().map(|arg| arg.as_ref().flatten()).collect::<Result<Vec<_>>>()?;
649    let width = args.len();
650    let order: Vec<usize> =
651        (0..rows).flat_map(|row| (0..width).map(move |at| at * rows + row)).collect();
652    let child = interleave(element, &pieces, &order)?;
653    let count = entry(width)?;
654    let entries = (0..rows).map(|row| Ok((entry(row * width)?, count))).collect::<Result<_>>()?;
655    Vector::list(entries, child).map(Some)
656}
657
658/// `range` and `generate_series` over integer columns, with every row's series written straight
659/// into one child and no `Value` made for any element. A row with a null argument is a null list.
660fn series<V: AsRef<Vector>>(
661    inclusive: bool,
662    args: &[V],
663    returns: &LogicalType,
664    rows: usize,
665) -> Result<Option<Vector>> {
666    if let [start, stop, step] = args
667        && step.as_ref().logical_type() == &LogicalType::Interval
668    {
669        return timed(inclusive, [start.as_ref(), stop.as_ref(), step.as_ref()], returns, rows);
670    }
671    if args.iter().any(|arg| arg.as_ref().logical_type() != &LogicalType::BigInt) {
672        return Ok(None);
673    }
674    // flatten: the loop below reads each row's start, stop and step as plain i64 values, and the
675    // arguments are three scalars a row, small next to the series written for them.
676    let flat: Vec<Vector> = args.iter().map(|arg| arg.as_ref().flatten()).collect::<Result<_>>()?;
677    let mut columns = Vec::with_capacity(flat.len());
678    for vector in &flat {
679        let Some(Data::Int64(values)) = vector.data() else {
680            return Ok(None);
681        };
682        columns.push((values.as_slice(), vector.validity().live()));
683    }
684    // Every row is counted before anything is written, so the child is allocated once at its full
685    // length and never moved while it grows.
686    let mut runs = Vec::with_capacity(rows);
687    let mut live = vec![true; rows];
688    let mut total = 0_usize;
689    for (row, live) in live.iter_mut().enumerate() {
690        let mut held = [0_i64; 3];
691        for (at, (values, valid)) in columns.iter().enumerate() {
692            match values.get(row) {
693                Some(&value) if valid.at(row) => held[at] = value,
694                _ => *live = false,
695            }
696        }
697        let (start, stop, step) = match columns.len() {
698            1 => (0, held[0], 1),
699            2 => (held[0], held[1], 1),
700            _ => (held[0], held[1], held[2]),
701        };
702        let count = if *live { series_length(start, stop, step, inclusive)? } else { 0 };
703        runs.push((start, step, count));
704        total += count;
705    }
706    let mut entries = Vec::with_capacity(rows);
707    let mut child = Vec::with_capacity(total);
708    for &(start, step, count) in &runs {
709        entries.push((entry(child.len())?, entry(count)?));
710        // Every value taken is between the start and the stop, both BIGINTs, so neither the product
711        // nor the sum can leave the type for any of them.
712        let steps = i64::try_from(count).map_err(|_| too_long())?;
713        child.extend((0..steps).map(|at| start.wrapping_add(at.wrapping_mul(step))));
714    }
715    let child = Vector::flat(LogicalType::BigInt, Data::Int64(Buffer::from(child)))?;
716    let validity = Validity::from_iter(rows, |row| live[row]).normalize(rows);
717    Ok(Some(Vector::list(entries, child)?.with_validity(validity)))
718}
719
720/// `range` and `generate_series` over moments and an interval, the same way as [`series`] and
721/// with each step taken on the raw microseconds.
722fn timed(
723    inclusive: bool,
724    args: [&Vector; 3],
725    returns: &LogicalType,
726    rows: usize,
727) -> Result<Option<Vector>> {
728    let LogicalType::List(element) = returns else {
729        return Ok(None);
730    };
731    if args[..2].iter().any(|arg| arg.logical_type() != &**element) {
732        return Ok(None);
733    }
734    let [start, stop, step] = args.map(Vector::flatten);
735    let (start, stop, step) = (start?, stop?, step?);
736    let (Some(Data::Int64(starts)), Some(Data::Int64(stops)), Some(Data::Interval(steps))) =
737        (start.data(), stop.data(), step.data())
738    else {
739        return Ok(None);
740    };
741    let (starts, stops, steps) = (starts.as_slice(), stops.as_slice(), steps.as_slice());
742    let lives = [start.validity().live(), stop.validity().live(), step.validity().live()];
743    let mut entries = Vec::with_capacity(rows);
744    let mut child = Vec::new();
745    let mut live = vec![true; rows];
746    for row in 0..rows {
747        let at = entry(child.len())?;
748        let held = (starts.get(row), stops.get(row), steps.get(row));
749        let (Some(&from), Some(&to), Some(&interval)) = held else {
750            return Ok(None);
751        };
752        if lives.iter().any(|live| !live.at(row)) {
753            entries.push((at, 0));
754            live[row] = false;
755            continue;
756        }
757        let count = step_stamps(inclusive, from, to, interval, &mut child)?;
758        entries.push((at, entry(count)?));
759    }
760    let child = Vector::flat((**element).clone(), Data::Int64(Buffer::from(child)))?;
761    let validity = Validity::from_iter(rows, |row| live[row]).normalize(rows);
762    Ok(Some(Vector::list(entries, child)?.with_validity(validity)))
763}
764
765/// `length` of a list column, which is every entry's length with the column's nulls.
766fn counted(list: &Vector) -> Result<Option<Vector>> {
767    let Some((entries, _)) = list.list_parts() else {
768        return Ok(None);
769    };
770    if !matches!(list.logical_type(), LogicalType::List(_)) {
771        return Ok(None);
772    }
773    let lengths: Vec<i64> = entries.iter().map(|&(_, len)| i64::from(len)).collect();
774    let answer = Vector::flat(LogicalType::BigInt, Data::Int64(Buffer::from(lengths)))?;
775    Ok(Some(answer.with_validity(list.validity().clone())))
776}
777
778/// `list_aggr` over a column, as a grouped aggregate whose groups are the lists.
779///
780/// Every element of the child belongs to the row whose list holds it, so the child is the input and
781/// the rows are the slots, and the same one pass folds a `GROUP BY` uses do the rest. The elements
782/// of one list are walked in order, which keeps a floating point total adding the way the row path
783/// adds it. A null list folds nothing and is null. Left to the row path when two lists share an
784/// element of the child, since a row of the input can only go to one slot, and when the call has
785/// arguments after the aggregate's name.
786fn aggregated(list: &Vector, aggregate: &Vector, returns: &LogicalType) -> Result<Option<Vector>> {
787    let (Some((entries, child)), Some(Value::Varchar(aggregate))) =
788        (list.list_parts(), aggregate.constant_value())
789    else {
790        return Ok(None);
791    };
792    let live = list.validity().live();
793    let mut slots = vec![NOWHERE; child.len()];
794    for (row, &(start, len)) in entries.iter().enumerate() {
795        if !live.at(row) {
796            continue;
797        }
798        let (start, len) = (start as usize, len as usize);
799        let Some(held) = slots.get_mut(start..start + len) else {
800            return Err(Error::internal("a list entry past the end of its child"));
801        };
802        if held.iter().any(|&slot| slot != NOWHERE) {
803            return Ok(None);
804        }
805        held.fill(row);
806    }
807    let rows = entries.len();
808    let mut states = vec![Accumulator::new(aggregate, returns)?; rows];
809    let mut runs: Vec<(usize, usize)> = Vec::new();
810    for (at, &slot) in slots.iter().enumerate() {
811        match runs.last_mut() {
812            Some((held, end)) if *held == slot => *end = at + 1,
813            _ => runs.push((slot, at + 1)),
814        }
815    }
816    if !update_runs(&mut states, &runs, 1, 0, Some(child), child.len())? {
817        update_scattered(&mut states, &slots, 1, 0, Some(child), child.len())?;
818    }
819    let every: Vec<usize> = (0..rows).collect();
820    let answer = match finish_run(&states, &every, 1, 0, returns)? {
821        Some(answer) => answer,
822        None => {
823            let values = states.iter().map(Accumulator::finish).collect::<Result<Vec<_>>>()?;
824            Vector::from_values(returns.clone(), &values)?
825        }
826    };
827    let validity = answer.validity().and(list.validity(), rows);
828    Ok(Some(answer.with_validity(validity)))
829}
830
831/// `list_reverse` over a column: one gather of the child with every row's run turned round.
832fn reversed(list: &Vector) -> Result<Option<Vector>> {
833    let Some((entries, child)) = list.list_parts() else {
834        return Ok(None);
835    };
836    if !matches!(list.logical_type(), LogicalType::List(_)) {
837        return Ok(None);
838    }
839    let live = list.validity().live();
840    let mut indices = Vec::with_capacity(child.len());
841    let mut placed = Vec::with_capacity(entries.len());
842    for (row, &(start, len)) in entries.iter().enumerate() {
843        let at = entry(indices.len())?;
844        if live.at(row) {
845            indices.extend((start..start + len).rev());
846            placed.push((at, len));
847        } else {
848            placed.push((at, 0));
849        }
850    }
851    let child = child.gather(&indices)?;
852    Ok(Some(Vector::list(placed, child)?.with_validity(list.validity().clone())))
853}
854
855/// `list_contains` and `list_position` over an integer column with a constant needle, as one scan
856/// of the child.
857///
858/// A null needle is left to the row path, since `list_position` finds a null element with it and
859/// `list_contains` is null, and so is anything that is not a plain integer, where equality is not
860/// the same thing as equal bits.
861fn searched(position: bool, list: &Vector, needle: &Vector) -> Result<Option<Vector>> {
862    let (Some((entries, child)), Some(wanted)) = (list.list_parts(), needle.constant_value())
863    else {
864        return Ok(None);
865    };
866    let plain = plain(child.logical_type());
867    let Some(wanted) =
868        integral(wanted).filter(|_| plain && needle.logical_type() == child.logical_type())
869    else {
870        return Ok(None);
871    };
872    let elements = child.validity().live();
873    macro_rules! scan {
874        ($($variant:ident),+) => {
875            match child.data() {
876                $(Some(Data::$variant(values)) => {
877                    first_places(entries, values.as_slice(), elements, wanted)
878                })+
879                _ => return Ok(None),
880            }
881        };
882    }
883    let found = scan!(Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64);
884    let rows = list.validity().live();
885    if position {
886        let validity = Validity::from_iter(entries.len(), |row| rows.at(row) && found[row] != 0);
887        let data =
888            Data::Int32(Buffer::from(found.iter().map(|&place| place as i32).collect::<Vec<_>>()));
889        let answer = Vector::flat(LogicalType::Integer, data)?;
890        return Ok(Some(answer.with_validity(validity.normalize(entries.len()))));
891    }
892    let data = Data::Bool(Buffer::from(found.iter().map(|&place| place != 0).collect::<Vec<_>>()));
893    let answer = Vector::flat(LogicalType::Boolean, data)?;
894    Ok(Some(answer.with_validity(list.validity().clone())))
895}
896
897/// `list_sort`, `list_reverse_sort` and `list_grade_up` over an integer column: each row's run of
898/// the child sorted as indices, and the child gathered once in that order. A grade answers with the
899/// places themselves and gathers nothing.
900///
901/// The order and null order are constants, which the binder insists on, so they are read once for
902/// the whole vector. A null one is left to the row path, where it makes every row null. So is a
903/// vector with no row that is not null, because the row path never reads the order for those and
904/// so never refuses a bad one.
905fn ordered(
906    list: &Vector,
907    order: Option<&Vector>,
908    nulls: Option<&Vector>,
909    reverse: bool,
910    grade: bool,
911) -> Result<Option<Vector>> {
912    let Some((entries, child)) = list.list_parts() else {
913        return Ok(None);
914    };
915    if !plain(child.logical_type()) || list.validity().count_valid(list.len()) == 0 {
916        return Ok(None);
917    }
918    let spelled = |arg: Option<&Vector>| match arg.map(Vector::constant_value) {
919        None => Some(None),
920        Some(Some(value @ Value::Varchar(_))) => Some(Some(value.clone())),
921        Some(_) => None,
922    };
923    let (Some(order), Some(nulls)) = (spelled(order), spelled(nulls)) else {
924        return Ok(None);
925    };
926    let descending = reverse || order.as_ref().map(spelled_order).transpose()?.unwrap_or(false);
927    let nulls_first = nulls.as_ref().map(spelled_nulls).transpose()?.unwrap_or(false);
928    let rows = list.validity().live();
929    let elements = child.validity().live();
930    macro_rules! permute {
931        ($($variant:ident),+) => {
932            match child.data() {
933                $(Some(Data::$variant(values)) => {
934                    let values = values.as_slice();
935                    permutation(entries, rows, elements, nulls_first, |left, right| {
936                        let ordering = values[left as usize].cmp(&values[right as usize]);
937                        if descending { ordering.reverse() } else { ordering }
938                    })?
939                })+
940                _ => return Ok(None),
941            }
942        };
943    }
944    let (placed, indices) = permute!(Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64);
945    let child = if grade {
946        // A grade is each index less the start of its row's run, counted from one.
947        let mut places = Vec::with_capacity(indices.len());
948        for (&(at, len), &(start, _)) in placed.iter().zip(entries) {
949            let run = &indices[at as usize..(at + len) as usize];
950            places.extend(run.iter().map(|&index| i64::from(index - start) + 1));
951        }
952        Vector::flat(LogicalType::BigInt, Data::Int64(Buffer::from(places)))?
953    } else {
954        child.gather(&indices)?
955    };
956    Ok(Some(Vector::list(placed, child)?.with_validity(list.validity().clone())))
957}
958
959/// `list_distinct` and `list_unique` over an integer column, as one pass over each row's run that
960/// keeps the first appearance of every value that is not null.
961fn deduplicated(unique: bool, list: &Vector) -> Result<Option<Vector>> {
962    let Some((entries, child)) = list.list_parts() else {
963        return Ok(None);
964    };
965    if !plain(child.logical_type()) {
966        return Ok(None);
967    }
968    let rows = list.validity().live();
969    let elements = child.validity().live();
970    macro_rules! keep {
971        ($($variant:ident),+) => {
972            match child.data() {
973                $(Some(Data::$variant(values)) => {
974                    let values = values.as_slice();
975                    firsts(entries, rows, elements, |at| i128::from(values[at as usize]))?
976                })+
977                _ => return Ok(None),
978            }
979        };
980    }
981    let (placed, indices) = keep!(Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64);
982    if unique {
983        let counts: Vec<u64> = placed.iter().map(|&(_, len)| u64::from(len)).collect();
984        let answer = Vector::flat(LogicalType::UBigInt, Data::UInt64(Buffer::from(counts)))?;
985        return Ok(Some(answer.with_validity(list.validity().clone())));
986    }
987    let child = child.gather(&indices)?;
988    Ok(Some(Vector::list(placed, child)?.with_validity(list.validity().clone())))
989}
990
991/// The new entries and the child indices that keep the first element of every `key` in each row's
992/// run and drop the nulls, which is what [`distinct`] does with values.
993///
994/// A short run is checked against what it has kept so far, which for the lists people write is a
995/// handful of comparisons and no allocation. A long one goes through a set.
996fn firsts(
997    entries: &[(u32, u32)],
998    rows: Live<'_>,
999    elements: Live<'_>,
1000    key: impl Fn(u32) -> i128,
1001) -> Result<Permuted> {
1002    const SHORT: u32 = 32;
1003    let mut indices = Vec::new();
1004    let mut placed = Vec::with_capacity(entries.len());
1005    let mut kept: Vec<i128> = Vec::new();
1006    let mut seen: HashSet<i128> = HashSet::new();
1007    for (row, &(start, len)) in entries.iter().enumerate() {
1008        let at = entry(indices.len())?;
1009        if !rows.at(row) {
1010            placed.push((at, 0));
1011            continue;
1012        }
1013        let from = indices.len();
1014        kept.clear();
1015        seen.clear();
1016        for index in start..start + len {
1017            if !elements.at(index as usize) {
1018                continue;
1019            }
1020            let value = key(index);
1021            let fresh = if len <= SHORT {
1022                let fresh = !kept.contains(&value);
1023                if fresh {
1024                    kept.push(value);
1025                }
1026                fresh
1027            } else {
1028                seen.insert(value)
1029            };
1030            if fresh {
1031                indices.push(index);
1032            }
1033        }
1034        placed.push((at, entry(indices.len() - from)?));
1035    }
1036    Ok((placed, indices))
1037}
1038
1039/// A list column rearranged but not yet gathered: its new entries, and the child index each new
1040/// element is read from.
1041type Permuted = (Vec<(u32, u32)>, Vec<u32>);
1042
1043/// The new entries and the child indices in order, for sorting every row's run with `compare`.
1044///
1045/// The nulls in a run are set aside, the rest are sorted stably, and the nulls go back in at the
1046/// front or the back, which is what [`sort`] does with values.
1047fn permutation(
1048    entries: &[(u32, u32)],
1049    rows: Live<'_>,
1050    elements: Live<'_>,
1051    nulls_first: bool,
1052    compare: impl Fn(u32, u32) -> Ordering,
1053) -> Result<Permuted> {
1054    let mut indices = Vec::new();
1055    let mut placed = Vec::with_capacity(entries.len());
1056    let mut nulls = Vec::new();
1057    for (row, &(start, len)) in entries.iter().enumerate() {
1058        let at = entry(indices.len())?;
1059        if !rows.at(row) {
1060            placed.push((at, 0));
1061            continue;
1062        }
1063        nulls.clear();
1064        let from = indices.len();
1065        for index in start..start + len {
1066            if elements.at(index as usize) {
1067                indices.push(index);
1068            } else {
1069                nulls.push(index);
1070            }
1071        }
1072        indices[from..].sort_by(|&left, &right| compare(left, right));
1073        if nulls_first {
1074            indices.splice(from..from, nulls.iter().copied());
1075        } else {
1076            indices.extend_from_slice(&nulls);
1077        }
1078        placed.push((at, len));
1079    }
1080    Ok((placed, indices))
1081}
1082
1083/// Whether equal values of `ty` are equal bits, which is what lets a search or a sort compare the
1084/// child's native values instead of going through [`order`].
1085fn plain(ty: &LogicalType) -> bool {
1086    matches!(
1087        ty,
1088        LogicalType::TinyInt
1089            | LogicalType::SmallInt
1090            | LogicalType::Integer
1091            | LogicalType::BigInt
1092            | LogicalType::UTinyInt
1093            | LogicalType::USmallInt
1094            | LogicalType::UInteger
1095            | LogicalType::UBigInt
1096    )
1097}
1098
1099/// The one based place in each row's run of the first element equal to `wanted` that is not null,
1100/// or 0 for none.
1101///
1102/// The needle is narrowed to the child's own type once, so the scan compares native values and a
1103/// child with no nulls is a plain search of each run. A needle that does not fit the type is in no
1104/// run at all.
1105fn first_places<T: Copy + PartialEq + TryFrom<i128>>(
1106    entries: &[(u32, u32)],
1107    values: &[T],
1108    elements: Live<'_>,
1109    wanted: i128,
1110) -> Vec<u32> {
1111    let Ok(wanted) = T::try_from(wanted) else {
1112        return vec![0; entries.len()];
1113    };
1114    let place = |at: Option<usize>| at.map_or(0, |at| at as u32 + 1);
1115    entries
1116        .iter()
1117        .map(|&(start, len)| {
1118            let start = start as usize;
1119            let run = &values[start..start + len as usize];
1120            match elements {
1121                Live::All => place(run.iter().position(|&value| value == wanted)),
1122                _ => place(
1123                    run.iter()
1124                        .enumerate()
1125                        .position(|(at, &value)| value == wanted && elements.at(start + at)),
1126                ),
1127            }
1128        })
1129        .collect()
1130}
1131
1132/// Whether a list of `element` has to be laid a row at a time.
1133fn nested_or_null(element: &LogicalType) -> bool {
1134    matches!(
1135        element,
1136        LogicalType::Null
1137            | LogicalType::List(_)
1138            | LogicalType::Array(..)
1139            | LogicalType::Struct(_)
1140            | LogicalType::Map(..)
1141            | LogicalType::Union(_)
1142    )
1143}
1144
1145/// A child offset as a list entry holds it.
1146fn entry(offset: usize) -> Result<u32> {
1147    u32::try_from(offset)
1148        .map_err(|_| Error::out_of_range(format!("a list child of {offset} elements")))
1149}