Skip to main content

rudb_vector/
vector.rs

1//! The vector itself.
2//!
3//! `spec/07-execution.md` section 7.1 calls this the widest interface in the system, says every
4//! operator depends on it, and says changing it after twenty operators exist is expensive. So it
5//! is written before the first operator rather than after the fifth.
6//!
7//! A vector is a type, a length of at most [`VECTOR_SIZE`], a physical form, a validity
8//! representation and some data. The four forms are the ones in `spec/04-architecture.md` section
9//! 4.3: flat, constant, sequence and dictionary. Encoded, the fifth, is the M3 work and it arrives
10//! with the specialization contract rather than before it.
11//!
12//! **What is not here yet.** Buffers are owned. Section 7.1 says a vector borrowed from a buffer
13//! managed page carries a pin, and there is no buffer manager until M2, so there is nothing to pin
14//! and pretending otherwise would be an interface built against an imaginary caller. Nested types
15//! are not stored yet either, for the same reason: a `LIST(STRUCT(...))` is offsets plus child
16//! column chunks, and child column chunks are storage.
17
18use rudb_common::{Error, LogicalType, Result, Value};
19
20use crate::buffer::Buffer;
21use crate::string::{StringColumn, StringView};
22use crate::validity::Validity;
23
24/// How many values are in a full vector.
25///
26/// 1024 rather than DuckDB's 2048, per `spec/04-architecture.md` section 4.3. It is the FastLanes
27/// unit, it makes a validity mask exactly 16 `u64` words, and it keeps a vector of 16 byte string
28/// views at 16 KiB, which is the size at which several of these fit in L1 together rather than
29/// evicting each other.
30pub const VECTOR_SIZE: usize = 1024;
31
32/// Which physical form a vector is in.
33///
34/// An operator asks this once per vector and then takes the path it wants, which is the one branch
35/// per vector that the whole design is willing to spend.
36///
37/// Not exhaustive, and that is a decision rather than an oversight. `Encoded` is the fifth form
38/// and it arrives at layer three with the specialization contract. If this enum were exhaustive,
39/// the day it lands is the day every kernel in the workspace stops compiling, and the pressure at
40/// that moment would be to add an arm to each of them in a hurry rather than to think about what
41/// each one should do with an encoded vector. A required fallback arm means each kernel already
42/// has a correct answer for a form it has never seen, and specializing it is then a change that
43/// can be made one kernel at a time with a benchmark next to it.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45#[non_exhaustive]
46pub enum Form {
47    /// One value per position.
48    Flat,
49    /// One value, repeated.
50    Constant,
51    /// A start and a step, computed rather than stored.
52    Sequence,
53    /// Codes into a smaller vector of distinct values.
54    Dictionary,
55}
56
57/// The values of a flat vector, one Rust vector per physical type.
58///
59/// The variants are physical rather than logical, which is what lets `DATE` and `INTEGER` share
60/// storage and share a kernel. What a run of `i32` means is the vector's logical type's business.
61#[derive(Debug, Clone, PartialEq)]
62#[non_exhaustive]
63pub enum Data {
64    /// No values, for the type of an untyped `NULL`.
65    Empty,
66    /// One byte per value.
67    Bool(Buffer<bool>),
68    /// 8 bit signed.
69    Int8(Buffer<i8>),
70    /// 16 bit signed.
71    Int16(Buffer<i16>),
72    /// 32 bit signed.
73    Int32(Buffer<i32>),
74    /// 64 bit signed.
75    Int64(Buffer<i64>),
76    /// 128 bit signed.
77    Int128(Buffer<i128>),
78    /// 8 bit unsigned.
79    UInt8(Buffer<u8>),
80    /// 16 bit unsigned.
81    UInt16(Buffer<u16>),
82    /// 32 bit unsigned.
83    UInt32(Buffer<u32>),
84    /// 64 bit unsigned.
85    UInt64(Buffer<u64>),
86    /// 128 bit unsigned.
87    UInt128(Buffer<u128>),
88    /// IEEE 754 binary32.
89    Float32(Buffer<f32>),
90    /// IEEE 754 binary64.
91    Float64(Buffer<f64>),
92    /// The months, days and microseconds triple.
93    Interval(Buffer<(i32, i32, i64)>),
94    /// Strings, as 16 byte views plus the arena the long ones live in.
95    Varlen(StringColumn),
96}
97
98impl Data {
99    /// How many values are stored.
100    ///
101    /// The match below has no wildcard arm, and that is what makes this function the check that
102    /// keeps [`for_each_layout`](crate::for_each_layout) honest. A variant added to this enum
103    /// without being added to the `all` group fails to compile here, which is a line in a build log
104    /// rather than a layout quietly missing from six kernels.
105    #[must_use]
106    pub fn len(&self) -> usize {
107        macro_rules! lengths {
108            ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
109                match self {
110                    Self::Empty => 0,
111                    $(Self::$variant(values) => values.len(),)+
112                }
113            };
114        }
115        crate::for_each_layout!(all, lengths)
116    }
117
118    /// Whether there are no values.
119    #[must_use]
120    pub fn is_empty(&self) -> bool {
121        self.len() == 0
122    }
123
124    /// An integer at `index`, widened, for any of the signed integer layouts.
125    ///
126    /// Used by the decimal path, which needs the unscaled value out of whichever width the width
127    /// and scale picked, and by anything else that would otherwise repeat the same five arms.
128    #[must_use]
129    pub fn signed_at(&self, index: usize) -> Option<i128> {
130        macro_rules! widened {
131            ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
132                match self {
133                    $(Self::$variant(v) => v.get(index).map(|&x| i128::from(x)),)+
134                    _ => None,
135                }
136            };
137        }
138        crate::for_each_layout!(signed, widened)
139    }
140
141    /// An unsigned integer at `index`, widened.
142    #[must_use]
143    pub fn unsigned_at(&self, index: usize) -> Option<u128> {
144        macro_rules! widened {
145            ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
146                match self {
147                    $(Self::$variant(v) => v.get(index).map(|&x| u128::from(x)),)+
148                    _ => None,
149                }
150            };
151        }
152        crate::for_each_layout!(unsigned, widened)
153    }
154
155    /// The string at `index`, for a `Varlen`.
156    #[must_use]
157    pub fn str_at(&self, index: usize) -> Option<&str> {
158        match self {
159            Self::Varlen(column) => column.get(index),
160            _ => None,
161        }
162    }
163}
164
165/// A type, a length, a validity representation and some data.
166#[derive(Debug, Clone, PartialEq)]
167pub struct Vector {
168    ty: LogicalType,
169    len: usize,
170    validity: Validity,
171    body: Body,
172}
173
174/// What the vector holds, which is what its form is decided by.
175#[derive(Debug, Clone, PartialEq)]
176enum Body {
177    Flat(Data),
178    Constant(Box<Value>),
179    Sequence { start: i64, step: i64 },
180    Dictionary { codes: Vec<u32>, values: Box<Vector> },
181}
182
183impl Vector {
184    /// A flat vector of `data`, all valid.
185    ///
186    /// # Errors
187    ///
188    /// If the data's physical layout is not the one the type calls for. That check is here rather
189    /// than left to the caller because a vector whose type and layout disagree is a wrong answer
190    /// waiting to be read out, and it costs one comparison at construction to prevent.
191    pub fn flat(ty: LogicalType, data: Data) -> Result<Self> {
192        let len = data.len();
193        if !matches!(data, Data::Empty) && layout_of(&data) != ty.physical() {
194            return Err(Error::internal(format!(
195                "a {ty} vector cannot hold {:?} data",
196                layout_of(&data)
197            )));
198        }
199        Ok(Self { ty, len, validity: Validity::AllValid, body: Body::Flat(data) })
200    }
201
202    /// A flat vector built from single values, with the nulls among them turning into validity.
203    ///
204    /// The slow way in, and the only way in that anything outside this crate has. It is what an
205    /// `INSERT`, a `VALUES` clause and a test build a column with, all of which arrive holding
206    /// values rather than a run of `i32`. Nothing on a scan path calls it: a scan produces a run of
207    /// data directly and hands it to [`Self::flat`].
208    ///
209    /// # Errors
210    ///
211    /// If a value is not one the type can hold, or if the type is one that cannot be stored flat
212    /// yet, which today means the nested types.
213    pub fn from_values(ty: LogicalType, values: &[Value]) -> Result<Self> {
214        let mut data = empty_data_for(&ty)?;
215        for value in values {
216            push_value(&mut data, value)?;
217        }
218        let validity = Validity::from_iter(values.len(), |index| !values[index].is_null());
219        Ok(Self { ty, len: values.len(), validity, body: Body::Flat(data) })
220    }
221
222    /// A vector of `len` copies of one value.
223    ///
224    /// Costs one value regardless of the length, which is what makes a literal in a predicate free
225    /// and what makes a projection of a constant free.
226    #[must_use]
227    pub fn constant(ty: LogicalType, value: Value, len: usize) -> Self {
228        let validity = if value.is_null() { Validity::AllInvalid } else { Validity::AllValid };
229        Self { ty, len, validity, body: Body::Constant(Box::new(value)) }
230    }
231
232    /// A vector of `len` values starting at `start` and stepping by `step`.
233    ///
234    /// This is what a row identifier column is, and it costs sixteen bytes rather than eight
235    /// kilobytes. A scan that produces row ids for a later fetch produces one of these.
236    #[must_use]
237    pub fn sequence(start: i64, step: i64, len: usize) -> Self {
238        Self {
239            ty: LogicalType::BigInt,
240            len,
241            validity: Validity::AllValid,
242            body: Body::Sequence { start, step },
243        }
244    }
245
246    /// A vector of codes into a smaller vector of distinct values.
247    ///
248    /// The form the whole M3 thesis rests on. A dictionary vector handed to a group by is an
249    /// integer column, and an aggregate over one is an aggregate over integers no matter what the
250    /// logical type says.
251    ///
252    /// A dictionary over a dictionary is composed into one level here rather than left as two, so
253    /// the form has a depth of one always and a kernel that reads [`Self::dictionary_parts`] is
254    /// reading the values rather than another layer of codes. Two filters over the same chunk build
255    /// the second case and four conjuncts pushed down separately build four of it.
256    ///
257    /// The cost of leaving them stacked turned out to be a cliff rather than a slope. Every loop in
258    /// `rudb-kernels` reaches for the values behind the codes with [`Self::data`], a dictionary
259    /// pointing at a dictionary has no data to hand back, so the second level does not make the
260    /// kernels slower, it turns them off and drops the work onto the row at a time path that exists
261    /// to be correct rather than fast. Measured on server3 over a chunk of two numeric columns and a
262    /// consumer of two vectorized passes, one level reads at 3.5 nanoseconds a row and two levels at
263    /// 104, and the third and fourth levels cost almost nothing more because the first one had
264    /// already given up everything there was to give. Composing is one pass over the outer codes,
265    /// which the range check above is already making.
266    ///
267    /// The one dictionary that is not composed past is one carrying a validity of its own. A
268    /// dictionary is built all valid and only [`Self::with_validity`] can change that, so such a
269    /// vector is saying that its nulls are at this level rather than in the values it points at, and
270    /// composing past it would drop them.
271    ///
272    /// # Errors
273    ///
274    /// If any code is past the end of the value vector.
275    pub fn dictionary(codes: Vec<u32>, values: Vector) -> Result<Self> {
276        if let Some(&bad) = codes.iter().find(|&&code| code as usize >= values.len()) {
277            return Err(Error::internal(format!(
278                "dictionary code {bad} is past the end of a {} value dictionary",
279                values.len()
280            )));
281        }
282        let (codes, values) = compose(codes, values);
283        Ok(Self {
284            ty: values.ty.clone(),
285            len: codes.len(),
286            validity: Validity::AllValid,
287            body: Body::Dictionary { codes, values: Box::new(values) },
288        })
289    }
290
291    /// The same vector with a different validity.
292    #[must_use]
293    pub fn with_validity(mut self, validity: Validity) -> Self {
294        self.validity = validity;
295        self
296    }
297
298    /// What kind of values these are.
299    #[must_use]
300    pub fn logical_type(&self) -> &LogicalType {
301        &self.ty
302    }
303
304    /// How many values there are.
305    #[must_use]
306    pub fn len(&self) -> usize {
307        self.len
308    }
309
310    /// Whether there are no values.
311    #[must_use]
312    pub fn is_empty(&self) -> bool {
313        self.len == 0
314    }
315
316    /// Which of the values are not null.
317    #[must_use]
318    pub fn validity(&self) -> &Validity {
319        &self.validity
320    }
321
322    /// Which physical form this vector is in.
323    #[must_use]
324    pub fn form(&self) -> Form {
325        match self.body {
326            Body::Flat(_) => Form::Flat,
327            Body::Constant(_) => Form::Constant,
328            Body::Sequence { .. } => Form::Sequence,
329            Body::Dictionary { .. } => Form::Dictionary,
330        }
331    }
332
333    /// The data, for a flat vector, and `None` for any other form.
334    ///
335    /// A kernel that wants a slice asks for it and takes the flat path if it gets one. A kernel
336    /// that can do better on a constant or a dictionary checks [`Self::form`] first.
337    #[must_use]
338    pub fn data(&self) -> Option<&Data> {
339        match &self.body {
340            Body::Flat(data) => Some(data),
341            _ => None,
342        }
343    }
344
345    /// The one value, for a constant vector, and `None` for any other form.
346    ///
347    /// A kernel comparing a column against a literal wants the literal once rather than 1024
348    /// times, and [`Self::value_at`] on a constant clones it on every call because it has to be
349    /// able to hand back a `Value` for any form. This is the accessor that lets the specialized
350    /// path hoist the clone out of the loop.
351    #[must_use]
352    pub fn constant_value(&self) -> Option<&Value> {
353        match &self.body {
354            Body::Constant(value) => Some(value.as_ref()),
355            _ => None,
356        }
357    }
358
359    /// The codes and the values, for a dictionary vector, and `None` for any other form.
360    ///
361    /// The reason a kernel needs this rather than reading the dictionary through
362    /// [`Self::value_at`] is the entire argument for the form existing. A filter against a
363    /// dictionary column of 1024 rows and 40 distinct values is 40 comparisons and 1024 lookups,
364    /// not 1024 comparisons, and there is no way to write that loop without seeing the codes.
365    ///
366    /// Note what the validity of the returned vector means. A dictionary keeps its nulls in the
367    /// vector it points at, and the dictionary's own validity says nothing about them, so a caller
368    /// deciding whether row `i` is null has to ask the value vector about `codes[i]` rather than
369    /// asking this vector about `i`. [`Self::flatten`] has the same note on it for the same
370    /// reason, because getting this wrong is a null that survives being selected and comes out as
371    /// a zero.
372    #[must_use]
373    pub fn dictionary_parts(&self) -> Option<(&[u32], &Self)> {
374        match &self.body {
375            Body::Dictionary { codes, values } => Some((codes, values.as_ref())),
376            _ => None,
377        }
378    }
379
380    /// The start and the step, for a sequence vector, and `None` for any other form.
381    #[must_use]
382    pub fn sequence_parts(&self) -> Option<(i64, i64)> {
383        match self.body {
384            Body::Sequence { start, step } => Some((start, step)),
385            _ => None,
386        }
387    }
388
389    /// The value at `index`, as a single value.
390    ///
391    /// This is the slow path on purpose. It is what a result set is read out with and what a test
392    /// asserts on, and an operator that calls it per row is an operator that has already lost the
393    /// argument the vector interface exists to win.
394    #[must_use]
395    pub fn value_at(&self, index: usize) -> Value {
396        if index >= self.len || !self.validity.is_valid(index) {
397            return Value::Null;
398        }
399        match &self.body {
400            Body::Constant(value) => value.as_ref().clone(),
401            Body::Sequence { start, step } => Value::BigInt(start + step * index as i64),
402            Body::Dictionary { codes, values } => match codes.get(index) {
403                Some(&code) => values.value_at(code as usize),
404                None => Value::Null,
405            },
406            Body::Flat(data) => value_from(&self.ty, data, index),
407        }
408    }
409
410    /// Every value in order, as single values.
411    pub fn iter(&self) -> impl Iterator<Item = Value> + '_ {
412        (0..self.len).map(|index| self.value_at(index))
413    }
414
415    /// A contiguous run of the values, in the form they are already in.
416    ///
417    /// This is the cut [`Self::gather`] cannot do. A gather walks a dictionary to its leaf and
418    /// copies, so gathering a piece of a dictionary encoded column hands back a flat one, and a
419    /// caller that only wanted the first thousand rows of a page has silently paid for a copy and
420    /// thrown the dictionary away. A group by over a dictionary encoded column is the case that
421    /// cares, and it is most of ClickBench.
422    ///
423    /// So each form is cut as itself. A dictionary keeps its dictionary and slices its codes, a
424    /// sequence stays arithmetic with its start moved along, a constant stays a shorter constant,
425    /// and a flat body is the one that genuinely has to copy its range.
426    ///
427    /// The dictionary is still cloned, because `Buffer` owns its values, so slicing a dictionary
428    /// vector copies the dictionary once. That is the same cost `Page::into_vector` in
429    /// `rudb-parquet` documents and it goes away with the same change: the buffer manager is what
430    /// can hand out a run inside a pinned page, and it is the only thing that can.
431    ///
432    /// # Errors
433    ///
434    /// If the range runs past the end of the vector, or if the type has no flat layout and the
435    /// body is one that has to be copied.
436    pub fn slice(&self, at: usize, len: usize) -> Result<Self> {
437        let end = at.checked_add(len).ok_or_else(|| Error::internal("a slice that wraps"))?;
438        if end > self.len {
439            return Err(Error::internal(format!("rows {at} to {end} of a vector of {}", self.len)));
440        }
441        if at == 0 && len == self.len {
442            return Ok(self.clone());
443        }
444        let validity = Validity::from_iter(len, |row| self.validity.is_valid(at + row));
445        let body = match &self.body {
446            Body::Constant(value) => Body::Constant(value.clone()),
447            Body::Sequence { start, step } => {
448                Body::Sequence { start: start + step * at as i64, step: *step }
449            }
450            Body::Dictionary { codes, values } => Body::Dictionary {
451                codes: codes[at..end].to_vec(),
452                values: Box::new(values.as_ref().clone()),
453            },
454            // The one form with nowhere to point, so its range is copied out. A gather is the
455            // right tool here and does no more than this would: a flat body has no dictionary
456            // under it for the gather to flatten.
457            Body::Flat(_) => {
458                let indices: Vec<u32> =
459                    (at..end).map(|row| u32::try_from(row).unwrap_or(u32::MAX)).collect();
460                return self.gather(&indices);
461            }
462        };
463        Ok(Self { ty: self.ty.clone(), len, validity, body })
464    }
465
466    /// The same values in flat form.
467    ///
468    /// Flattening a vector that is already flat is free. Flattening any other form costs a copy,
469    /// which is exactly why the other forms exist and why nothing on the hot path should call
470    /// this. It is here for the operators that genuinely cannot do better and for the tests that
471    /// check the other forms against it.
472    ///
473    /// # Errors
474    ///
475    /// If the type is one this crate cannot store flat yet, which today means the nested types.
476    pub fn flatten(&self) -> Result<Self> {
477        if let Body::Flat(_) = self.body {
478            return Ok(self.clone());
479        }
480        self.copied((0..self.len).collect(), false)
481    }
482
483    /// The values at the given positions, copied, in a form that does not point back at this vector.
484    ///
485    /// This is the copying counterpart to [`Self::dictionary`], and the two are the two halves of
486    /// the decision `spec/07-execution.md` section 7.1 describes. Which half is right is measured
487    /// rather than argued, and [`Chunk::compact`](crate::Chunk::compact) is where the measurement
488    /// is written down.
489    ///
490    /// A dictionary chain is walked to its leaf first and the codes composed on the way down, so the
491    /// copy runs once over the data rather than once per level, and a position that is null at any
492    /// level comes out null here. The copy is a typed loop per physical layout rather than a `Value`
493    /// per row, which is the whole point of it and is what [`Self::flatten`] now goes through too.
494    ///
495    /// # Errors
496    ///
497    /// If the type has no flat layout, which today means the nested types.
498    pub fn gather(&self, indices: &[u32]) -> Result<Self> {
499        self.copied(indices.iter().map(|&index| index as usize).collect(), true)
500    }
501
502    /// The copy both [`Self::gather`] and [`Self::flatten`] are.
503    ///
504    /// `constants_stay` is the one thing the two want differently. A gather of a constant is a
505    /// shorter constant and copying it out would be a thousand writes of the same value for nothing,
506    /// but flattening promises flat form to a caller that is about to read the data slice, so for
507    /// that one the constant has to be written out.
508    fn copied(&self, at: Vec<usize>, constants_stay: bool) -> Result<Self> {
509        let rows = at.len();
510        let (at, leaf) = self.resolve(at);
511        let live: Vec<bool> = at.iter().map(|&index| index != NOWHERE).collect();
512        let validity = Validity::from_run(&live);
513        let body = match &leaf.body {
514            // Every position holds the same value, so the only thing the gather can change is the
515            // length and which positions are null. A gather with no null in it is still a constant.
516            Body::Constant(value) => {
517                if constants_stay && matches!(validity, Validity::AllValid) {
518                    return Ok(Self::constant(self.ty.clone(), value.as_ref().clone(), rows));
519                }
520                let mut data = empty_data_for(&self.ty)?;
521                for &index in &at {
522                    push_value(&mut data, if index == NOWHERE { &Value::Null } else { value })?;
523                }
524                Body::Flat(data)
525            }
526            // A sequence is arithmetic rather than storage, so the gather is the arithmetic done at
527            // the positions asked for, and a null writes the zero every other layout writes.
528            Body::Sequence { start, step } => Body::Flat(Data::Int64(
529                at.iter()
530                    .map(|&index| if index == NOWHERE { 0 } else { start + step * index as i64 })
531                    .collect(),
532            )),
533            // A flat body with no values is the untyped null, so every position asked for is null
534            // whatever was asked for. Going through the copy would build a run of no values and
535            // call it `rows` long, which is a vector whose length and data disagree.
536            Body::Flat(Data::Empty) => {
537                return Ok(Self::constant(self.ty.clone(), Value::Null, rows));
538            }
539            Body::Flat(data) => Body::Flat(copy_of(data, &at)),
540            // Unreachable, because `resolve` stops at the first body that is not a dictionary.
541            Body::Dictionary { .. } => {
542                return Err(Error::internal("a dictionary survived being resolved"));
543            }
544        };
545        Ok(Self { ty: self.ty.clone(), len: rows, validity, body })
546    }
547
548    /// Where each wanted position lives in the first body that is not a dictionary, and that body.
549    ///
550    /// A position that is null anywhere on the way down, or past the end of anything on the way
551    /// down, comes back as [`NOWHERE`]. That single sentinel is what keeps the copy loop from
552    /// carrying a validity mask alongside the positions it is already walking.
553    fn resolve(&self, mut at: Vec<usize>) -> (Vec<usize>, &Self) {
554        let mut source = self;
555        loop {
556            for slot in &mut at {
557                if *slot >= source.len || !source.validity.is_valid(*slot) {
558                    *slot = NOWHERE;
559                }
560            }
561            let Body::Dictionary { codes, values } = &source.body else {
562                return (at, source);
563            };
564            for slot in &mut at {
565                *slot = match codes.get(*slot) {
566                    Some(&code) => code as usize,
567                    None => NOWHERE,
568                };
569            }
570            source = values.as_ref();
571        }
572    }
573}
574
575/// So that a kernel can take its operands as either a list of vectors or a list of references.
576///
577/// A caller that built a `Vec<Vector>` and a caller whose operands are already somewhere else, in a
578/// chunk or in an evaluator's scratch, want the same kernel. Without this the second kind has to
579/// clone every operand into a `Vec` to satisfy the signature, and a clone of a vector is a copy of
580/// the whole column, so the type would be charging real memory traffic for nothing.
581impl AsRef<Vector> for Vector {
582    fn as_ref(&self) -> &Vector {
583        self
584    }
585}
586
587/// One level of dictionary out of however many levels were handed to [`Vector::dictionary`].
588///
589/// Every dictionary in the system is built through that constructor and every one of them comes
590/// through here first, so the invariant this maintains is that the vector a dictionary points at is
591/// never itself a dictionary that could have been composed away. That makes the work a single `if`
592/// rather than a loop: the inner vector was already composed when it was built, so composing the
593/// outer codes through it leaves the result no deeper than the inner vector already was.
594///
595/// The codes are indexed rather than fetched with `get`, because the caller has already walked the
596/// whole outer array to check that every code is in range and the inner array is exactly as long as
597/// the vector those codes were checked against.
598fn compose(codes: Vec<u32>, values: Vector) -> (Vec<u32>, Vector) {
599    // A dictionary carrying a validity of its own is one whose nulls live at this level rather than
600    // in the values, which is the one thing composition cannot carry down with it.
601    if !matches!(values.validity, Validity::AllValid) {
602        return (codes, values);
603    }
604    let Vector { ty, len, validity, body } = values;
605    match body {
606        Body::Dictionary { codes: inner, values: leaf } => {
607            debug_assert!(
608                !matches!(leaf.body, Body::Dictionary { .. })
609                    || !matches!(leaf.validity, Validity::AllValid),
610                "a dictionary was stacked on a dictionary without going through the constructor"
611            );
612            (codes.iter().map(|&code| inner[code as usize]).collect(), *leaf)
613        }
614        body => (codes, Vector { ty, len, validity, body }),
615    }
616}
617
618/// The position of a value that is not anywhere, because it is null or out of range.
619///
620/// `usize::MAX` rather than an `Option<usize>`, because the copy loop's bounds check rejects it for
621/// free and an `Option` would put a second branch next to the one already there.
622const NOWHERE: usize = usize::MAX;
623
624/// A run of data copied at the given positions, with a zero wherever the position is [`NOWHERE`].
625///
626/// A zero and not a skip, because every layout here is a parallel array to a validity mask and a
627/// short one would put every value after the first null at the wrong index. It is the same rule
628/// [`push_value`] follows for a null.
629fn copy_of(data: &Data, at: &[usize]) -> Data {
630    macro_rules! copied {
631        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
632            match data {
633                Data::Empty => Data::Empty,
634                $(Data::$variant(values) => {
635                    let mut out = Buffer::with_capacity(at.len());
636                    for &index in at {
637                        // One bounds check rather than a null test and a bounds check, because
638                        // `NOWHERE` is past the end of every slice there can be.
639                        out.push(values.get(index).copied().unwrap_or($zero));
640                    }
641                    Data::$variant(out)
642                })+
643                // The one layout where a gather is a copy of bytes rather than a copy of fixed
644                // width slots, and the reason compaction is a decision rather than a default on a
645                // string column.
646                Data::Varlen(values) => {
647                    let mut out = StringColumn::with_capacity(at.len());
648                    // The bytes are known before any of them are copied, because a view carries its
649                    // length and the wanted positions are already in hand, so the arena is one
650                    // allocation rather than a run of doublings that each copy what the last one
651                    // copied.
652                    let views = values.views();
653                    out.reserve_bytes(
654                        at.iter()
655                            .filter_map(|&index| views.get(index))
656                            .filter(|view| !view.is_inline())
657                            .map(StringView::len)
658                            .sum(),
659                    );
660                    for &index in at {
661                        out.push(values.get(index).unwrap_or(""));
662                    }
663                    Data::Varlen(out)
664                }
665            }
666        };
667    }
668    crate::for_each_layout!(fixed, copied)
669}
670
671/// The physical layout a run of data is in, for the check that it matches its type.
672///
673/// The two enums name their variants the same way on purpose, so this is one generated arm rather
674/// than sixteen chances to pair the wrong two up.
675fn layout_of(data: &Data) -> rudb_common::PhysicalType {
676    use rudb_common::PhysicalType as P;
677    macro_rules! layouts {
678        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
679            match data {
680                Data::Empty => P::Empty,
681                $(Data::$variant(_) => P::$variant,)+
682            }
683        };
684    }
685    crate::for_each_layout!(all, layouts)
686}
687
688/// One value out of a run of data, given what the run means.
689///
690/// The match is on the logical type rather than on the data, because the data cannot tell a `DATE`
691/// from an `INTEGER` and that is the whole reason the two are kept apart.
692fn value_from(ty: &LogicalType, data: &Data, index: usize) -> Value {
693    let signed = || data.signed_at(index);
694    let unsigned = || data.unsigned_at(index);
695    let value = match ty {
696        LogicalType::Boolean => match data {
697            Data::Bool(v) => v.get(index).map(|&x| Value::Boolean(x)),
698            _ => None,
699        },
700        LogicalType::TinyInt => signed().and_then(|x| i8::try_from(x).ok()).map(Value::TinyInt),
701        LogicalType::SmallInt => signed().and_then(|x| i16::try_from(x).ok()).map(Value::SmallInt),
702        LogicalType::Integer => signed().and_then(|x| i32::try_from(x).ok()).map(Value::Integer),
703        LogicalType::BigInt => signed().and_then(|x| i64::try_from(x).ok()).map(Value::BigInt),
704        LogicalType::HugeInt => signed().map(Value::HugeInt),
705        LogicalType::UTinyInt => unsigned().and_then(|x| u8::try_from(x).ok()).map(Value::UTinyInt),
706        LogicalType::USmallInt => {
707            unsigned().and_then(|x| u16::try_from(x).ok()).map(Value::USmallInt)
708        }
709        LogicalType::UInteger => {
710            unsigned().and_then(|x| u32::try_from(x).ok()).map(Value::UInteger)
711        }
712        LogicalType::UBigInt => unsigned().and_then(|x| u64::try_from(x).ok()).map(Value::UBigInt),
713        LogicalType::UHugeInt => unsigned().map(Value::UHugeInt),
714        LogicalType::Float => match data {
715            Data::Float32(v) => v.get(index).map(|&x| Value::Float(x)),
716            _ => None,
717        },
718        LogicalType::Double => match data {
719            Data::Float64(v) => v.get(index).map(|&x| Value::Double(x)),
720            _ => None,
721        },
722        LogicalType::Decimal { width, scale } => {
723            signed().map(|unscaled| Value::Decimal { unscaled, width: *width, scale: *scale })
724        }
725        LogicalType::Varchar => data.str_at(index).map(|s| Value::Varchar(s.to_string())),
726        LogicalType::Blob | LogicalType::Bit => {
727            data.str_at(index).map(|s| Value::Blob(s.as_bytes().to_vec()))
728        }
729        LogicalType::Date => signed().and_then(|x| i32::try_from(x).ok()).map(Value::Date),
730        LogicalType::Time | LogicalType::TimeTz => {
731            signed().and_then(|x| i64::try_from(x).ok()).map(Value::Time)
732        }
733        LogicalType::Timestamp
734        | LogicalType::TimestampS
735        | LogicalType::TimestampMs
736        | LogicalType::TimestampNs
737        | LogicalType::TimestampTz => {
738            signed().and_then(|x| i64::try_from(x).ok()).map(Value::Timestamp)
739        }
740        LogicalType::Interval => match data {
741            Data::Interval(v) => {
742                v.get(index).map(|&(months, days, micros)| Value::Interval { months, days, micros })
743            }
744            _ => None,
745        },
746        _ => None,
747    };
748    value.unwrap_or(Value::Null)
749}
750
751/// An empty run of data of the right layout for a type.
752fn empty_data_for(ty: &LogicalType) -> Result<Data> {
753    use rudb_common::PhysicalType as P;
754    macro_rules! empties {
755        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
756            match ty.physical() {
757                P::Empty => Data::Empty,
758                $(P::$variant => Data::$variant(Buffer::new()),)+
759                P::Varlen => Data::Varlen(StringColumn::new()),
760                other => {
761                    return Err(Error::not_implemented(format!(
762                        "a flat vector of {other:?} data, which arrives with the storage layer"
763                    )));
764                }
765            }
766        };
767    }
768    Ok(crate::for_each_layout!(fixed, empties))
769}
770
771/// Appends one value to a run of data, or a zero of the right shape when it is null.
772///
773/// The zero matters. A null still occupies a position, the validity mask is what says it is null,
774/// and a run of data with a hole in it would put every value after the hole in the wrong place.
775fn push_value(data: &mut Data, value: &Value) -> Result<()> {
776    macro_rules! push {
777        ($vec:expr, $variant:path, $zero:expr) => {
778            match value {
779                Value::Null => $vec.push($zero),
780                $variant(x) => $vec.push(*x),
781                other => {
782                    return Err(Error::internal(format!(
783                        "{other:?} does not belong in this vector"
784                    )));
785                }
786            }
787        };
788    }
789    // A decimal is stored as its unscaled integer in whatever width its precision needs, which
790    // `LogicalType::physical` decides and which is why the same `Value::Decimal` is at home in four
791    // different runs. The narrowing cannot fail for a value the binder produced, because the width
792    // that chose the run is the width in the value, but it is checked rather than assumed because
793    // an unchecked cast here would silently store a different number.
794    macro_rules! decimal {
795        ($vec:expr, $ty:ty, $unscaled:expr) => {
796            match <$ty>::try_from(*$unscaled) {
797                Ok(x) => $vec.push(x),
798                Err(_) => {
799                    return Err(Error::internal(format!(
800                        "an unscaled decimal of {} does not fit the run its precision chose",
801                        $unscaled
802                    )));
803                }
804            }
805        };
806    }
807    match data {
808        Data::Empty => {}
809        Data::Bool(v) => push!(v, Value::Boolean, false),
810        Data::Int8(v) => push!(v, Value::TinyInt, 0),
811        Data::Int16(v) => match value {
812            Value::Null => v.push(0),
813            Value::SmallInt(x) => v.push(*x),
814            Value::Decimal { unscaled, .. } => decimal!(v, i16, unscaled),
815            other => return Err(Error::internal(format!("{other:?} is not a 16 bit value"))),
816        },
817        Data::Int32(v) => match value {
818            Value::Null => v.push(0),
819            Value::Integer(x) | Value::Date(x) => v.push(*x),
820            Value::Decimal { unscaled, .. } => decimal!(v, i32, unscaled),
821            other => return Err(Error::internal(format!("{other:?} is not a 32 bit value"))),
822        },
823        Data::Int64(v) => match value {
824            Value::Null => v.push(0),
825            Value::BigInt(x) | Value::Time(x) | Value::Timestamp(x) => v.push(*x),
826            Value::Decimal { unscaled, .. } => decimal!(v, i64, unscaled),
827            other => return Err(Error::internal(format!("{other:?} is not a 64 bit value"))),
828        },
829        Data::Int128(v) => match value {
830            Value::Null => v.push(0),
831            Value::HugeInt(x) => v.push(*x),
832            Value::Decimal { unscaled, .. } => v.push(*unscaled),
833            other => return Err(Error::internal(format!("{other:?} is not a 128 bit value"))),
834        },
835        Data::UInt8(v) => push!(v, Value::UTinyInt, 0),
836        Data::UInt16(v) => push!(v, Value::USmallInt, 0),
837        Data::UInt32(v) => push!(v, Value::UInteger, 0),
838        Data::UInt64(v) => push!(v, Value::UBigInt, 0),
839        Data::UInt128(v) => push!(v, Value::UHugeInt, 0),
840        Data::Float32(v) => push!(v, Value::Float, 0.0),
841        Data::Float64(v) => push!(v, Value::Double, 0.0),
842        Data::Interval(v) => match value {
843            Value::Null => v.push((0, 0, 0)),
844            Value::Interval { months, days, micros } => v.push((*months, *days, *micros)),
845            other => return Err(Error::internal(format!("{other:?} is not an interval"))),
846        },
847        Data::Varlen(column) => match value {
848            Value::Null => {
849                column.push("");
850            }
851            Value::Varchar(text) => {
852                column.push(text);
853            }
854            // A blob is bytes and this column is text, so the only blobs that survive a round trip
855            // here are the ones that happen to be valid UTF-8. Real blob storage is a byte column
856            // and it arrives with the storage layer at M2 rather than being faked now.
857            Value::Blob(bytes) => match std::str::from_utf8(bytes) {
858                Ok(text) => {
859                    column.push(text);
860                }
861                Err(_) => {
862                    return Err(Error::not_implemented(
863                        "a blob that is not valid UTF-8, which needs the byte column from M2",
864                    ));
865                }
866            },
867            other => return Err(Error::internal(format!("{other:?} is not a string"))),
868        },
869    }
870    Ok(())
871}
872
873#[cfg(test)]
874mod tests {
875    use rudb_common::{LogicalType, Value};
876
877    use super::{Data, Form, VECTOR_SIZE, Vector};
878    use crate::string::StringColumn;
879    use crate::validity::Validity;
880
881    fn integers(values: &[i32]) -> Vector {
882        Vector::flat(LogicalType::Integer, Data::Int32(values.to_vec().into())).unwrap()
883    }
884
885    #[test]
886    fn slicing_a_dictionary_keeps_it_a_dictionary_where_gathering_would_not() {
887        let values = Vector::from_values(
888            LogicalType::Varchar,
889            &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
890        )
891        .unwrap();
892        let vector = Vector::dictionary(vec![0, 1, 1, 0, 1], values).unwrap();
893
894        let piece = vector.slice(1, 3).unwrap();
895        assert_eq!(piece.form(), Form::Dictionary, "the form is the whole point");
896        assert_eq!(piece.len(), 3);
897        assert_eq!(
898            piece.iter().collect::<Vec<_>>(),
899            [
900                Value::Varchar("blue".into()),
901                Value::Varchar("blue".into()),
902                Value::Varchar("red".into())
903            ]
904        );
905        assert_eq!(vector.gather(&[1, 2, 3]).unwrap().form(), Form::Flat, "which a gather loses");
906    }
907
908    #[test]
909    fn a_slice_carries_the_nulls_that_were_in_its_range_and_not_the_others() {
910        let vector =
911            integers(&[1, 2, 3, 4]).with_validity(Validity::from_run(&[false, true, false, true]));
912        let piece = vector.slice(1, 2).unwrap();
913        assert!(piece.validity().is_valid(0));
914        assert!(!piece.validity().is_valid(1));
915        assert_eq!(piece.value_at(1), Value::Null);
916    }
917
918    #[test]
919    fn slicing_a_sequence_moves_its_start_rather_than_writing_the_values_out() {
920        let vector = Vector::sequence(100, 5, 10);
921        let piece = vector.slice(3, 4).unwrap();
922        assert_eq!(piece.form(), Form::Sequence);
923        assert_eq!(
924            piece.iter().collect::<Vec<_>>(),
925            [Value::BigInt(115), Value::BigInt(120), Value::BigInt(125), Value::BigInt(130)]
926        );
927    }
928
929    #[test]
930    fn slicing_a_constant_is_a_shorter_constant() {
931        let vector = Vector::constant(LogicalType::Integer, Value::Integer(9), 8);
932        let piece = vector.slice(2, 3).unwrap();
933        assert_eq!(piece.form(), Form::Constant);
934        assert_eq!(piece.len(), 3);
935        assert_eq!(piece.value_at(2), Value::Integer(9));
936    }
937
938    #[test]
939    fn slicing_the_whole_vector_hands_it_back_as_it_was() {
940        let vector = integers(&[1, 2, 3]);
941        assert_eq!(
942            vector.slice(0, 3).unwrap().iter().collect::<Vec<_>>(),
943            [Value::Integer(1), Value::Integer(2), Value::Integer(3)]
944        );
945    }
946
947    #[test]
948    fn a_slice_past_the_end_is_an_error_rather_than_a_short_vector() {
949        let error = integers(&[1, 2, 3]).slice(2, 2).unwrap_err();
950        assert!(error.to_string().contains("of a vector of 3"), "{error}");
951    }
952
953    #[test]
954    fn the_vector_size_is_the_one_the_design_is_built_around() {
955        // 1024 and not DuckDB's 2048. A validity mask is 16 u64 words and a vector of string views
956        // is 16 KiB, both of which are consequences of this number rather than coincidences.
957        assert_eq!(VECTOR_SIZE, 1024);
958        assert_eq!(VECTOR_SIZE / 64, 16);
959    }
960
961    #[test]
962    fn a_flat_vector_reads_back_what_was_put_in_it() {
963        let vector = integers(&[1, 2, 3]);
964        assert_eq!(vector.form(), Form::Flat);
965        assert_eq!(vector.len(), 3);
966        assert_eq!(vector.value_at(1), Value::Integer(2));
967        assert_eq!(
968            vector.iter().collect::<Vec<_>>(),
969            vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)]
970        );
971    }
972
973    #[test]
974    fn a_vector_built_from_values_reads_the_same_values_back() {
975        let vector = Vector::from_values(
976            LogicalType::Varchar,
977            &[
978                Value::Varchar("a".to_string()),
979                Value::Null,
980                Value::Varchar("a string too long to sit inside a view".to_string()),
981            ],
982        )
983        .expect("strings and a null");
984        assert_eq!(vector.len(), 3);
985        assert_eq!(vector.value_at(0), Value::Varchar("a".to_string()));
986        assert_eq!(vector.value_at(1), Value::Null);
987        assert_eq!(
988            vector.value_at(2),
989            Value::Varchar("a string too long to sit inside a view".to_string())
990        );
991    }
992
993    /// A null still occupies a position. If it did not then every value after it would read back
994    /// one place to the left, which is the kind of bug that looks like a storage bug for a week.
995    #[test]
996    fn a_null_in_the_middle_does_not_move_the_values_after_it() {
997        let vector = Vector::from_values(
998            LogicalType::Integer,
999            &[Value::Integer(1), Value::Null, Value::Integer(3)],
1000        )
1001        .expect("integers and a null");
1002        assert_eq!(vector.value_at(2), Value::Integer(3));
1003        assert!(vector.validity().has_nulls(3), "the middle one is null");
1004    }
1005
1006    #[test]
1007    fn a_value_the_type_cannot_hold_is_refused() {
1008        let wrong = Vector::from_values(LogicalType::Integer, &[Value::Varchar("x".to_string())]);
1009        assert!(wrong.is_err(), "a string is not an integer");
1010    }
1011
1012    #[test]
1013    fn a_type_that_does_not_match_its_layout_is_refused_at_construction() {
1014        // One comparison here against a wrong answer read out three layers later.
1015        let wrong = Vector::flat(LogicalType::Varchar, Data::Int32(vec![1].into()));
1016        assert!(wrong.is_err());
1017        let right = Vector::flat(LogicalType::Date, Data::Int32(vec![1].into()));
1018        assert!(right.is_ok(), "a date is stored in an i32 and that has to be allowed");
1019    }
1020
1021    #[test]
1022    fn a_constant_vector_costs_one_value_whatever_its_length() {
1023        let vector = Vector::constant(LogicalType::Integer, Value::Integer(7), VECTOR_SIZE);
1024        assert_eq!(vector.form(), Form::Constant);
1025        assert_eq!(vector.len(), VECTOR_SIZE);
1026        assert_eq!(vector.value_at(0), Value::Integer(7));
1027        assert_eq!(vector.value_at(VECTOR_SIZE - 1), Value::Integer(7));
1028        assert_eq!(vector.value_at(VECTOR_SIZE), Value::Null, "past the end is null, not a panic");
1029    }
1030
1031    #[test]
1032    fn a_constant_null_is_all_invalid_without_being_told() {
1033        let vector = Vector::constant(LogicalType::Integer, Value::Null, 8);
1034        assert_eq!(vector.validity(), &Validity::AllInvalid);
1035        assert_eq!(vector.value_at(3), Value::Null);
1036    }
1037
1038    #[test]
1039    fn a_sequence_vector_is_sixteen_bytes_of_row_identifiers() {
1040        let vector = Vector::sequence(100, 1, VECTOR_SIZE);
1041        assert_eq!(vector.form(), Form::Sequence);
1042        assert_eq!(vector.value_at(0), Value::BigInt(100));
1043        assert_eq!(vector.value_at(923), Value::BigInt(1023));
1044        let stepped = Vector::sequence(0, 5, 4);
1045        assert_eq!(
1046            stepped.iter().collect::<Vec<_>>(),
1047            vec![Value::BigInt(0), Value::BigInt(5), Value::BigInt(10), Value::BigInt(15)]
1048        );
1049    }
1050
1051    #[test]
1052    fn a_dictionary_vector_reads_through_its_codes() {
1053        let mut column = StringColumn::new();
1054        column.push("red");
1055        column.push("green");
1056        let values = Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap();
1057        let vector = Vector::dictionary(vec![0, 1, 1, 0], values).unwrap();
1058        assert_eq!(vector.form(), Form::Dictionary);
1059        assert_eq!(vector.logical_type(), &LogicalType::Varchar);
1060        assert_eq!(vector.value_at(2), Value::Varchar("green".into()));
1061        assert_eq!(vector.len(), 4);
1062    }
1063
1064    #[test]
1065    fn a_dictionary_code_past_the_end_is_refused() {
1066        // The alternative is a silent read of the wrong value, which is the failure mode the
1067        // entire M3 design has to be careful about.
1068        let values = integers(&[1, 2]);
1069        assert!(Vector::dictionary(vec![0, 2], values).is_err());
1070    }
1071
1072    #[test]
1073    fn every_form_flattens_to_the_same_values_it_reads_out() {
1074        // This is the shape of the equivalence testing in spec/16-testing.md section 16.2, in
1075        // miniature and long before there is an encoded kernel to point it at. A form that reads
1076        // out one way and flattens another is the exact bug that testing exists to catch.
1077        let mut column = StringColumn::new();
1078        column.push("alpha");
1079        column.push("beta");
1080        let dictionary = Vector::dictionary(
1081            vec![1, 0, 1],
1082            Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap(),
1083        )
1084        .unwrap();
1085        let cases = [
1086            Vector::constant(LogicalType::Integer, Value::Integer(3), 5),
1087            Vector::sequence(7, -2, 5),
1088            dictionary,
1089        ];
1090        for vector in cases {
1091            let flat = vector.flatten().unwrap();
1092            assert_eq!(flat.form(), Form::Flat);
1093            assert_eq!(flat.len(), vector.len());
1094            for index in 0..vector.len() {
1095                assert_eq!(flat.value_at(index), vector.value_at(index), "at {index}");
1096            }
1097        }
1098    }
1099
1100    #[test]
1101    fn a_null_still_occupies_a_position_after_flattening() {
1102        // The reason push_value writes a zero for a null rather than skipping it. A run of data
1103        // with a hole in it puts every value after the hole in the wrong place, and the validity
1104        // mask is what says the position is null.
1105        let vector = Vector::sequence(0, 1, 4).with_validity(Validity::from_iter(4, |i| i != 1));
1106        let flat = vector.flatten().unwrap();
1107        assert_eq!(flat.value_at(0), Value::BigInt(0));
1108        assert_eq!(flat.value_at(1), Value::Null);
1109        assert_eq!(flat.value_at(2), Value::BigInt(2));
1110        assert_eq!(flat.value_at(3), Value::BigInt(3));
1111    }
1112
1113    /// A dictionary holds its nulls in the vector it points at, so its own validity is all valid
1114    /// and reading that instead of the values turns a null into whatever zero means for the type.
1115    /// A filter over a nullable column produces exactly this vector, so the bug reaches a result
1116    /// set as `LEFT JOIN` padding that comes back as zeros.
1117    #[test]
1118    fn a_null_behind_a_dictionary_survives_flattening() {
1119        let values =
1120            Vector::from_values(LogicalType::Integer, &[Value::Integer(3), Value::Null]).unwrap();
1121        let dictionary = Vector::dictionary(vec![1, 0, 1], values).unwrap();
1122        let flat = dictionary.flatten().unwrap();
1123        assert_eq!(flat.value_at(0), Value::Null);
1124        assert_eq!(flat.value_at(1), Value::Integer(3));
1125        assert_eq!(flat.value_at(2), Value::Null);
1126    }
1127
1128    /// The property that makes `gather` usable at all: it has to be the same function as reading the
1129    /// wanted positions one at a time, over every form, or compaction changes answers.
1130    #[test]
1131    fn gathering_reads_what_reading_one_position_at_a_time_reads() {
1132        let mut column = StringColumn::new();
1133        column.push("alpha");
1134        column.push("beta");
1135        column.push("gamma");
1136        let cases = [
1137            integers(&[10, 20, 30, 40]),
1138            integers(&[10, 20, 30, 40]).with_validity(Validity::from_iter(4, |i| i != 2)),
1139            Vector::constant(LogicalType::Integer, Value::Integer(9), 4),
1140            Vector::sequence(100, -7, 4),
1141            Vector::sequence(100, -7, 4).with_validity(Validity::from_iter(4, |i| i % 2 == 0)),
1142            Vector::dictionary(
1143                vec![2, 0, 1, 2],
1144                Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap(),
1145            )
1146            .unwrap(),
1147            Vector::dictionary(
1148                vec![1, 0, 1, 0],
1149                Vector::from_values(LogicalType::Integer, &[Value::Integer(5), Value::Null])
1150                    .unwrap(),
1151            )
1152            .unwrap(),
1153        ];
1154        let wanted = [3_u32, 0, 2, 2, 1];
1155        for vector in cases {
1156            let gathered = vector.gather(&wanted).unwrap();
1157            assert_eq!(gathered.len(), wanted.len());
1158            assert_eq!(gathered.logical_type(), vector.logical_type());
1159            for (slot, &index) in wanted.iter().enumerate() {
1160                assert_eq!(
1161                    gathered.value_at(slot),
1162                    vector.value_at(index as usize),
1163                    "slot {slot} of {:?}",
1164                    vector.form()
1165                );
1166            }
1167        }
1168    }
1169
1170    /// A gather past the end is not an error, because the selection that produced the indices is
1171    /// checked by its caller and the one thing that must not happen here is a read of the wrong
1172    /// value. An index nothing answers is null, which is what an outer join pad needs anyway.
1173    #[test]
1174    fn gathering_a_position_that_is_not_there_is_a_null_and_not_a_wrong_value() {
1175        let vector = integers(&[1, 2, 3]);
1176        let gathered = vector.gather(&[2, 9]).unwrap();
1177        assert_eq!(gathered.value_at(0), Value::Integer(3));
1178        assert_eq!(gathered.value_at(1), Value::Null);
1179    }
1180
1181    /// The vector with nothing in it at all, which is what an untyped `NULL` is stored as. Every
1182    /// position asked for is past its end, so the answer is nulls and the length has to be the
1183    /// length that was asked for rather than the length that was there.
1184    #[test]
1185    fn gathering_from_a_vector_of_no_values_is_that_many_nulls() {
1186        let vector = Vector::flat(LogicalType::Null, Data::Empty).unwrap();
1187        let gathered = vector.gather(&[0, 1, 2]).unwrap();
1188        assert_eq!(gathered.len(), 3);
1189        assert_eq!(gathered.value_at(0), Value::Null);
1190        assert_eq!(gathered.value_at(2), Value::Null);
1191    }
1192
1193    /// Every position holds the same value, so a gather with no hole in it has nothing to copy and
1194    /// the result is the constant again rather than a run of a thousand copies of it.
1195    #[test]
1196    fn gathering_a_constant_stays_a_constant() {
1197        let vector = Vector::constant(LogicalType::Integer, Value::Integer(4), 100);
1198        let gathered = vector.gather(&[7, 7, 99]).unwrap();
1199        assert_eq!(gathered.form(), Form::Constant);
1200        assert_eq!(gathered.len(), 3);
1201        assert_eq!(gathered.value_at(2), Value::Integer(4));
1202    }
1203
1204    /// A dictionary over a dictionary is what a second filter over an already filtered chunk builds,
1205    /// and the gather has to walk to the bottom of that chain rather than one step down it. The
1206    /// constructor composes the ordinary chain away, so the one built here is the kind it cannot,
1207    /// which is a level holding nulls of its own.
1208    #[test]
1209    fn gathering_walks_a_dictionary_over_a_dictionary_to_the_values() {
1210        let inner = Vector::dictionary(vec![2, 1, 0], integers(&[7, 8, 9]))
1211            .unwrap()
1212            .with_validity(Validity::from_iter(3, |index| index != 2));
1213        let outer = Vector::dictionary(vec![1, 2], inner).unwrap();
1214        let gathered = outer.gather(&[0, 1]).unwrap();
1215        assert_eq!(gathered.form(), Form::Flat);
1216        assert_eq!(gathered.value_at(0), Value::Integer(8));
1217        assert_eq!(gathered.value_at(1), Value::Null);
1218    }
1219
1220    /// Two filters over one chunk build a dictionary over a dictionary, four conjuncts pushed down
1221    /// separately build four levels of it, and every level is a dependent load on every later read
1222    /// of every row plus a code array that cannot be freed. Composing at construction is one pass
1223    /// over the codes the range check was walking anyway.
1224    #[test]
1225    fn a_dictionary_over_a_dictionary_is_composed_into_one_level() {
1226        let inner = Vector::dictionary(vec![2, 1, 0], integers(&[7, 8, 9])).unwrap();
1227        let outer = Vector::dictionary(vec![1, 2], inner).unwrap();
1228        let (codes, values) = outer.dictionary_parts().unwrap();
1229        assert_eq!(codes, [1, 0]);
1230        assert_eq!(values.form(), Form::Flat);
1231        assert_eq!(outer.value_at(0), Value::Integer(8));
1232        assert_eq!(outer.value_at(1), Value::Integer(7));
1233    }
1234
1235    /// The invariant stated as the thing it is there for, which is that the depth does not grow with
1236    /// the number of filters. Four levels stacked one at a time are one level at the end of it.
1237    #[test]
1238    fn stacking_dictionaries_does_not_make_them_deeper() {
1239        let mut vector = integers(&[10, 20, 30, 40]);
1240        for _ in 0..4 {
1241            vector = Vector::dictionary(vec![3, 2, 1, 0], vector).unwrap();
1242        }
1243        let (codes, values) = vector.dictionary_parts().unwrap();
1244        assert_eq!(values.form(), Form::Flat);
1245        assert_eq!(codes, [0, 1, 2, 3]);
1246        assert_eq!(
1247            vector.iter().collect::<Vec<_>>(),
1248            integers(&[10, 20, 30, 40]).iter().collect::<Vec<_>>()
1249        );
1250    }
1251
1252    /// Composing has to carry the nulls down with it. The values hold them, the codes point at them,
1253    /// and a composed code that lands on a null position is still a null.
1254    #[test]
1255    fn composing_a_dictionary_keeps_the_nulls_its_values_hold() {
1256        let values =
1257            Vector::from_values(LogicalType::Integer, &[Value::Integer(3), Value::Null]).unwrap();
1258        let inner = Vector::dictionary(vec![1, 0, 1], values).unwrap();
1259        let outer = Vector::dictionary(vec![0, 1], inner).unwrap();
1260        assert_eq!(outer.dictionary_parts().unwrap().1.form(), Form::Flat);
1261        assert_eq!(outer.value_at(0), Value::Null);
1262        assert_eq!(outer.value_at(1), Value::Integer(3));
1263    }
1264
1265    /// The one level composition cannot go past. A dictionary that was given a validity of its own is
1266    /// saying its nulls are at that level rather than in the values, and pointing the outer codes
1267    /// straight at the values would read through the holes instead of stopping at them.
1268    #[test]
1269    fn a_dictionary_holding_its_own_nulls_is_not_composed_past() {
1270        let inner = Vector::dictionary(vec![0, 1, 2], integers(&[1, 2, 3]))
1271            .unwrap()
1272            .with_validity(Validity::from_iter(3, |index| index != 1));
1273        let outer = Vector::dictionary(vec![1, 2, 0], inner).unwrap();
1274        assert_eq!(outer.dictionary_parts().unwrap().1.form(), Form::Dictionary);
1275        assert_eq!(outer.value_at(0), Value::Null);
1276        assert_eq!(outer.value_at(1), Value::Integer(3));
1277        assert_eq!(outer.value_at(2), Value::Integer(1));
1278    }
1279
1280    #[test]
1281    fn flattening_a_flat_vector_is_the_same_vector() {
1282        let vector = integers(&[1, 2, 3]);
1283        assert_eq!(vector.flatten().unwrap(), vector);
1284    }
1285
1286    #[test]
1287    fn a_decimal_reads_its_width_and_scale_from_the_type_and_not_the_data() {
1288        let ty = LogicalType::decimal(9, 2).unwrap();
1289        let vector = Vector::flat(ty, Data::Int32(vec![1234].into())).unwrap();
1290        assert_eq!(vector.value_at(0), Value::Decimal { unscaled: 1234, width: 9, scale: 2 });
1291        assert_eq!(vector.value_at(0).to_string(), "12.34");
1292    }
1293
1294    #[test]
1295    fn a_decimal_writes_into_whichever_of_the_four_runs_its_precision_chose() {
1296        // The read path worked at every width and the write path only accepted the 128 bit run, so
1297        // `SELECT 2.5` produced a value nothing could store. All four widths round trip now.
1298        for (width, scale, unscaled) in
1299            [(4u8, 1u8, 25i128), (9, 2, 1234), (18, 3, 123_456), (38, 4, 1_234_567)]
1300        {
1301            let ty = LogicalType::decimal(width, scale).unwrap();
1302            let value = Value::Decimal { unscaled, width, scale };
1303            let vector = Vector::from_values(ty, &[value.clone(), Value::Null]).unwrap();
1304            assert_eq!(vector.value_at(0), value, "a decimal of width {width}");
1305            assert_eq!(vector.value_at(1), Value::Null, "a null decimal of width {width}");
1306        }
1307    }
1308
1309    #[test]
1310    fn a_decimal_too_wide_for_the_run_its_type_chose_is_an_error_and_not_a_wrong_number() {
1311        // Only reachable by hand, since a value's width is what picked the run. Truncating here
1312        // would store a different number and say nothing about it.
1313        let ty = LogicalType::decimal(4, 1).unwrap();
1314        let value = Value::Decimal { unscaled: 1_000_000, width: 4, scale: 1 };
1315        let error = Vector::from_values(ty, &[value]).unwrap_err();
1316        assert!(error.to_string().contains("does not fit"), "{error}");
1317    }
1318}