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. Four of the forms are the ones in `spec/04-architecture.md`
9//! section 4.3: flat, constant, sequence and dictionary. Run length, bit packed and string view come
10//! after them, one at a time with the kernels that read them rather than all at once ahead of
11//! anything that can use them.
12//!
13//! Dictionary and run length are the pair worth understanding together, because they answer
14//! different questions about the same column. A dictionary says which distinct values there are, so
15//! it wins on low cardinality however the rows are ordered. Run length says where the values stop,
16//! so it wins on a clustered column however many distinct values it has. A column can want either
17//! one without wanting the other, and `hits` has columns of both kinds.
18//!
19//! String view is the odd one out, because it is not about making a column smaller. It is about who
20//! owns the bytes: the views are the vector's and the arena is shared, so cutting a chunk out of a
21//! page of strings moves sixteen bytes a row and copies none of the payload. Every other form here
22//! trades a little work per row for less memory, and that one trades nothing at all.
23//!
24//! **What is not here yet.** Buffers are owned. Section 7.1 says a vector borrowed from a buffer
25//! managed page carries a pin, and there is no buffer manager until M2, so there is nothing to pin
26//! and pretending otherwise would be an interface built against an imaginary caller. Nested types
27//! are not stored yet either, for the same reason: a `LIST(STRUCT(...))` is offsets plus child
28//! column chunks, and child column chunks are storage.
29
30use std::borrow::Cow;
31use std::sync::Arc;
32
33use rudb_common::{Cause, Error, LogicalType, Result, Value, slow};
34
35use crate::buffer::Buffer;
36use crate::fsst::SymbolTable;
37use crate::string::{StringColumn, StringView};
38use crate::validity::Validity;
39
40/// How many values are in a full vector.
41///
42/// 1024 rather than DuckDB's 2048, per `spec/04-architecture.md` section 4.3. It is the FastLanes
43/// unit, it makes a validity mask exactly 16 `u64` words, and it keeps a vector of 16 byte string
44/// views at 16 KiB, which is the size at which several of these fit in L1 together rather than
45/// evicting each other.
46pub const VECTOR_SIZE: usize = 1024;
47
48/// Which physical form a vector is in.
49///
50/// An operator asks this once per vector and then takes the path it wants, which is the one branch
51/// per vector that the whole design is willing to spend.
52///
53/// Not exhaustive, and that is a decision rather than an oversight. `Encoded` is the fifth form
54/// and it arrives at layer three with the specialization contract. If this enum were exhaustive,
55/// the day it lands is the day every kernel in the workspace stops compiling, and the pressure at
56/// that moment would be to add an arm to each of them in a hurry rather than to think about what
57/// each one should do with an encoded vector. A required fallback arm means each kernel already
58/// has a correct answer for a form it has never seen, and specializing it is then a change that
59/// can be made one kernel at a time with a benchmark next to it.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61#[non_exhaustive]
62pub enum Form {
63    /// One value per position.
64    Flat,
65    /// One value, repeated.
66    Constant,
67    /// A start and a step, computed rather than stored.
68    Sequence,
69    /// Codes into a smaller vector of distinct values.
70    Dictionary,
71    /// Integers stored in as many bits as the range of the column needs, offset from a base.
72    ///
73    /// The form a narrow integer column is in. A ClickBench `ResolutionWidth` is a `SMALLINT` whose
74    /// values live between 0 and 2560, which is twelve bits, so the column is three quarters of the
75    /// size it was and the pages behind it are three quarters of the reads. What it costs is a shift
76    /// and a mask per value, which is why this is worth it at storage and at rest and is not a form
77    /// anything should be building in the middle of a pipeline.
78    BitPacked,
79    /// Sixteen byte views over an arena the vector shares rather than owns.
80    ///
81    /// The form a varchar column is in once more than one vector is looking at the same page. A flat
82    /// varchar vector owns its arena, so cutting a chunk out of it copies every byte of every long
83    /// string in the range, and on ClickBench that is most of what reading `URL` costs. Sharing the
84    /// arena makes the cut the views and nothing else, the way a dictionary cut is the codes and
85    /// nothing else.
86    StringView,
87    /// Strings compressed against one symbol table, each row on its own.
88    ///
89    /// The form a text column is in at rest. FSST is about half the bytes on the ClickBench `URL`
90    /// and `Title` columns, and unlike a block compressor it keeps random access, so reading row
91    /// four million does not decompress the four million before it. What it costs is a decompression
92    /// per row read, which is why an equality filter over it is worth writing in code space: the
93    /// literal compresses once and the rows never decompress at all.
94    Fsst,
95    /// One value per run, with the row each run ends at.
96    ///
97    /// The form a clustered column is in. `hits` is written in time order, so `EventDate` is a few
98    /// hundred runs over a hundred million rows, and a sum over it is a few hundred multiplications
99    /// rather than a hundred million additions. Dictionary says which distinct values there are and
100    /// this says where they stop, and a column can want either one without wanting the other.
101    Rle,
102}
103
104/// The values of a flat vector, one Rust vector per physical type.
105///
106/// The variants are physical rather than logical, which is what lets `DATE` and `INTEGER` share
107/// storage and share a kernel. What a run of `i32` means is the vector's logical type's business.
108#[derive(Debug, Clone, PartialEq)]
109#[non_exhaustive]
110pub enum Data {
111    /// No values, for the type of an untyped `NULL`.
112    Empty,
113    /// One byte per value.
114    Bool(Buffer<bool>),
115    /// 8 bit signed.
116    Int8(Buffer<i8>),
117    /// 16 bit signed.
118    Int16(Buffer<i16>),
119    /// 32 bit signed.
120    Int32(Buffer<i32>),
121    /// 64 bit signed.
122    Int64(Buffer<i64>),
123    /// 128 bit signed.
124    Int128(Buffer<i128>),
125    /// 8 bit unsigned.
126    UInt8(Buffer<u8>),
127    /// 16 bit unsigned.
128    UInt16(Buffer<u16>),
129    /// 32 bit unsigned.
130    UInt32(Buffer<u32>),
131    /// 64 bit unsigned.
132    UInt64(Buffer<u64>),
133    /// 128 bit unsigned.
134    UInt128(Buffer<u128>),
135    /// IEEE 754 binary32.
136    Float32(Buffer<f32>),
137    /// IEEE 754 binary64.
138    Float64(Buffer<f64>),
139    /// The months, days and microseconds triple.
140    Interval(Buffer<(i32, i32, i64)>),
141    /// Strings, as 16 byte views plus the arena the long ones live in.
142    Varlen(StringColumn),
143}
144
145impl Data {
146    /// How many values are stored.
147    ///
148    /// The match below has no wildcard arm, and that is what makes this function the check that
149    /// keeps [`for_each_layout`](crate::for_each_layout) honest. A variant added to this enum
150    /// without being added to the `all` group fails to compile here, which is a line in a build log
151    /// rather than a layout quietly missing from six kernels.
152    #[must_use]
153    pub fn len(&self) -> usize {
154        macro_rules! lengths {
155            ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
156                match self {
157                    Self::Empty => 0,
158                    $(Self::$variant(values) => values.len(),)+
159                }
160            };
161        }
162        crate::for_each_layout!(all, lengths)
163    }
164
165    /// Whether there are no values.
166    #[must_use]
167    pub fn is_empty(&self) -> bool {
168        self.len() == 0
169    }
170
171    /// How many bytes of memory these values are holding.
172    ///
173    /// One arm per layout through the same macro as [`Data::len`], for the same reason: a layout
174    /// added without a size here is a layout the memory limit would charge nothing for, and a
175    /// buffer that is free is a buffer that can be grown until the process dies.
176    #[must_use]
177    pub fn footprint(&self) -> usize {
178        macro_rules! sizes {
179            ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
180                match self {
181                    Self::Empty => 0,
182                    $(Self::$variant(values) => values.footprint(),)+
183                }
184            };
185        }
186        crate::for_each_layout!(all, sizes)
187    }
188
189    /// An integer at `index`, widened, for any of the signed integer layouts.
190    ///
191    /// Used by the decimal path, which needs the unscaled value out of whichever width the width
192    /// and scale picked, and by anything else that would otherwise repeat the same five arms.
193    #[must_use]
194    pub fn signed_at(&self, index: usize) -> Option<i128> {
195        macro_rules! widened {
196            ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
197                match self {
198                    $(Self::$variant(v) => v.get(index).map(|&x| i128::from(x)),)+
199                    _ => None,
200                }
201            };
202        }
203        crate::for_each_layout!(signed, widened)
204    }
205
206    /// An unsigned integer at `index`, widened.
207    #[must_use]
208    pub fn unsigned_at(&self, index: usize) -> Option<u128> {
209        macro_rules! widened {
210            ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
211                match self {
212                    $(Self::$variant(v) => v.get(index).map(|&x| u128::from(x)),)+
213                    _ => None,
214                }
215            };
216        }
217        crate::for_each_layout!(unsigned, widened)
218    }
219
220    /// The string at `index`, for a `Varlen`.
221    #[must_use]
222    pub fn str_at(&self, index: usize) -> Option<&str> {
223        match self {
224            Self::Varlen(column) => column.get(index),
225            _ => None,
226        }
227    }
228
229    /// The bytes at `index`, for a `Varlen`, whatever they are.
230    ///
231    /// What a `BLOB` reads through, since the bytes of one are not required to be text and
232    /// [`Self::str_at`] answers `None` for the ones that are not.
233    #[must_use]
234    pub fn bytes_at(&self, index: usize) -> Option<&[u8]> {
235        match self {
236            Self::Varlen(column) => column.bytes(index),
237            _ => None,
238        }
239    }
240}
241
242/// A type, a length, a validity representation and some data.
243#[derive(Debug, Clone, PartialEq)]
244pub struct Vector {
245    ty: LogicalType,
246    len: usize,
247    validity: Validity,
248    body: Body,
249}
250
251/// What the vector holds, which is what its form is decided by.
252#[derive(Debug, Clone, PartialEq)]
253enum Body {
254    Flat(Data),
255    Constant(Box<Value>),
256    Sequence {
257        start: i64,
258        step: i64,
259    },
260    /// The values are behind an `Arc` rather than a `Box` because slicing shares them.
261    ///
262    /// A dictionary vector is cut once per chunk and the dictionary itself is the same dictionary
263    /// every time, so a `Box` meant a copy of every value in it per cut. On the ClickBench columns
264    /// that are dictionary encoded the dictionary is larger than the chunk of codes pointing into
265    /// it, and copying it was ten percent of the cycles of reading the file.
266    ///
267    /// Nothing here mutates a dictionary in place, so sharing one is only ever a read, and the one
268    /// place that wants an owned copy of the values is [`compose`], which asks for one.
269    Dictionary {
270        codes: Vec<u32>,
271        values: Arc<Vector>,
272    },
273    /// Integer codes of `width` bits each, packed end to end, each one an offset from `base`.
274    ///
275    /// Row `r` is the `width` bits starting at bit `(offset + r) * width`, read little end first, so
276    /// a code that straddles a word boundary has its low bits in the earlier word. `offset` is what
277    /// lets a cut of a packed column be free: the bits are not byte aligned, so a slice either
278    /// repacks or remembers where it starts, and remembering is one addition per read.
279    ///
280    /// The words are behind an `Arc` for the reason the dictionary's values are. A page is packed
281    /// once and cut into chunk sized pieces, and copying the words per cut would undo most of what
282    /// the packing saved.
283    Packed {
284        words: Arc<Vec<u64>>,
285        width: u32,
286        base: i128,
287        offset: usize,
288    },
289    /// The views of a string column, over an arena that other vectors are reading at the same time.
290    ///
291    /// The views are owned because a cut is a different run of views, and the arena is shared
292    /// because a cut is the same bytes. That split is the whole form: sixteen bytes a row move and
293    /// the payload does not, however many cuts a page is taken in.
294    ///
295    /// A row's bytes are found the same way [`StringColumn`] finds them, through
296    /// [`StringView::bytes_in`], so a short string never reads the arena at all and the two ways of
297    /// holding strings cannot answer a row differently.
298    Views {
299        views: Vec<StringView>,
300        arena: Arc<Buffer<u8>>,
301    },
302    /// The FSST codes of every row, end to end, with one symbol table over all of them.
303    ///
304    /// A span rather than a run of offsets, because a gather keeps this form and a gather puts the
305    /// rows in an order the codes are not in. Eight bytes a row either way, and the span is the one
306    /// that survives being permuted.
307    ///
308    /// The codes and the table are shared for the reason a dictionary's values are: one table is
309    /// trained per page and every chunk cut out of it points at the same one. A table is sixty five
310    /// thousand hash slots, so a table per chunk would cost more than the compression saves.
311    Coded {
312        codes: Arc<Vec<u8>>,
313        spans: Vec<(u32, u32)>,
314        table: Arc<SymbolTable>,
315    },
316    /// One value per run, with the row each run ends at, exclusive and increasing.
317    ///
318    /// Ends rather than lengths, because every reader of this wants to know which run holds a row
319    /// and ends answer that with a binary search while lengths answer it with a running total. The
320    /// two are the same information and only one of them is the one that gets asked for.
321    ///
322    /// The values are behind an `Arc` for the reason the dictionary's are: a page is cut into chunk
323    /// sized pieces and the values are the same values every time.
324    Runs {
325        ends: Vec<u32>,
326        values: Arc<Vector>,
327    },
328}
329
330impl Vector {
331    /// A flat vector of `data`, all valid.
332    ///
333    /// # Errors
334    ///
335    /// If the data's physical layout is not the one the type calls for. That check is here rather
336    /// than left to the caller because a vector whose type and layout disagree is a wrong answer
337    /// waiting to be read out, and it costs one comparison at construction to prevent.
338    pub fn flat(ty: LogicalType, data: Data) -> Result<Self> {
339        let len = data.len();
340        if !matches!(data, Data::Empty) && layout_of(&data) != ty.physical() {
341            return Err(Error::internal(format!(
342                "a {ty} vector cannot hold {:?} data",
343                layout_of(&data)
344            )));
345        }
346        Ok(Self { ty, len, validity: Validity::AllValid, body: Body::Flat(data) })
347    }
348
349    /// A flat vector built from single values, with the nulls among them turning into validity.
350    ///
351    /// The slow way in, and the only way in that anything outside this crate has. It is what an
352    /// `INSERT`, a `VALUES` clause and a test build a column with, all of which arrive holding
353    /// values rather than a run of `i32`. Nothing on a scan path calls it: a scan produces a run of
354    /// data directly and hands it to [`Self::flat`].
355    ///
356    /// # Errors
357    ///
358    /// If a value is not one the type can hold, or if the type is one that cannot be stored flat
359    /// yet, which today means the nested types.
360    pub fn from_values(ty: LogicalType, values: &[Value]) -> Result<Self> {
361        let mut data = empty_data_for(&ty)?;
362        for value in values {
363            push_value(&mut data, value)?;
364        }
365        let validity = Validity::from_iter(values.len(), |index| !values[index].is_null());
366        Ok(Self { ty, len: values.len(), validity, body: Body::Flat(data) })
367    }
368
369    /// A vector of `len` copies of one value.
370    ///
371    /// Costs one value regardless of the length, which is what makes a literal in a predicate free
372    /// and what makes a projection of a constant free.
373    #[must_use]
374    pub fn constant(ty: LogicalType, value: Value, len: usize) -> Self {
375        let validity = if value.is_null() { Validity::AllInvalid } else { Validity::AllValid };
376        Self { ty, len, validity, body: Body::Constant(Box::new(value)) }
377    }
378
379    /// A vector of `len` values starting at `start` and stepping by `step`.
380    ///
381    /// This is what a row identifier column is, and it costs sixteen bytes rather than eight
382    /// kilobytes. A scan that produces row ids for a later fetch produces one of these.
383    #[must_use]
384    pub fn sequence(start: i64, step: i64, len: usize) -> Self {
385        Self {
386            ty: LogicalType::BigInt,
387            len,
388            validity: Validity::AllValid,
389            body: Body::Sequence { start, step },
390        }
391    }
392
393    /// A vector of codes into a smaller vector of distinct values.
394    ///
395    /// The form the whole M3 thesis rests on. A dictionary vector handed to a group by is an
396    /// integer column, and an aggregate over one is an aggregate over integers no matter what the
397    /// logical type says.
398    ///
399    /// A dictionary over a dictionary is composed into one level here rather than left as two, so
400    /// the form has a depth of one always and a kernel that reads [`Self::dictionary_parts`] is
401    /// reading the values rather than another layer of codes. Two filters over the same chunk build
402    /// the second case and four conjuncts pushed down separately build four of it.
403    ///
404    /// The cost of leaving them stacked turned out to be a cliff rather than a slope. Every loop in
405    /// `rudb-kernels` reaches for the values behind the codes with [`Self::data`], a dictionary
406    /// pointing at a dictionary has no data to hand back, so the second level does not make the
407    /// kernels slower, it turns them off and drops the work onto the row at a time path that exists
408    /// to be correct rather than fast. Measured on server3 over a chunk of two numeric columns and a
409    /// consumer of two vectorized passes, one level reads at 3.5 nanoseconds a row and two levels at
410    /// 104, and the third and fourth levels cost almost nothing more because the first one had
411    /// already given up everything there was to give. Composing is one pass over the outer codes,
412    /// which the range check above is already making.
413    ///
414    /// The one dictionary that is not composed past is one carrying a validity of its own. A
415    /// dictionary is built all valid and only [`Self::with_validity`] can change that, so such a
416    /// vector is saying that its nulls are at this level rather than in the values it points at, and
417    /// composing past it would drop them.
418    ///
419    /// # Errors
420    ///
421    /// If any code is past the end of the value vector.
422    pub fn dictionary(codes: Vec<u32>, values: Vector) -> Result<Self> {
423        Self::dictionary_over(codes, Arc::new(values))
424    }
425
426    /// The same, over a set of values somebody else is holding too.
427    ///
428    /// The body holds its values in an `Arc` either way, so a caller that already has one has
429    /// nothing to hand over but a pointer. The caller this is for is a Parquet chunk: one dictionary
430    /// page serves every data page of the chunk, and going through [`Self::dictionary`] meant
431    /// copying the whole dictionary into each page's vector on the way to putting it in an `Arc`
432    /// that then had a single holder. On a ClickBench scan that copy was sixteen percent of the
433    /// instructions the query ran.
434    ///
435    /// Composing a dictionary over a dictionary still needs the values by value, so that case takes
436    /// them out of the handle and copies if anybody else is still reading them. Nothing that shares
437    /// a dictionary builds a stacked one, so the two paths do not meet in practice.
438    ///
439    /// The range check takes the highest code rather than stopping at the first bad one. Stopping
440    /// early sounds cheaper and is not, because a loop that can exit anywhere cannot be vectorized
441    /// and a running maximum can, and the only run that would have exited early is the one about to
442    /// fail the query anyway. Every other run reads the whole of `codes` either way. It was 5.2
443    /// percent of a ClickBench scan as a `find`.
444    ///
445    /// # Errors
446    ///
447    /// If any code is past the end of the value vector.
448    pub fn dictionary_over(codes: Vec<u32>, values: Arc<Vector>) -> Result<Self> {
449        let highest = codes.iter().copied().fold(0, u32::max);
450        if !codes.is_empty() && highest as usize >= values.len() {
451            return Err(Error::internal(format!(
452                "dictionary code {highest} is past the end of a {} value dictionary",
453                values.len()
454            )));
455        }
456        let stacked = matches!(values.validity, Validity::AllValid)
457            && matches!(values.body, Body::Dictionary { .. });
458        let (codes, values) = if stacked {
459            let (codes, values) = compose(codes, Arc::unwrap_or_clone(values));
460            (codes, Arc::new(values))
461        } else {
462            (codes, values)
463        };
464        Ok(Self {
465            ty: values.ty.clone(),
466            len: codes.len(),
467            validity: Validity::AllValid,
468            body: Body::Dictionary { codes, values },
469        })
470    }
471
472    /// A vector of runs, one value each, with the row each run ends at.
473    ///
474    /// `ends` is exclusive and strictly increasing, so run `i` covers the rows from `ends[i - 1]` to
475    /// `ends[i]` and run zero starts at nothing. The length of the vector is the last end.
476    ///
477    /// The depth is one, the same way a dictionary's is, and for a sharper reason. Every kernel that
478    /// wants runs wants the value of a run without another search, and a run length vector over a
479    /// run length vector turns one search into two and then into three. Rather than compose, this
480    /// refuses: nothing in the engine builds a stacked one, because [`Self::run_encoded`] only ever
481    /// reads a flat body, so a stacked one is a caller doing something by hand and the useful answer
482    /// is to say so rather than to quietly do a pass of work they did not ask for.
483    ///
484    /// A run over a dictionary is fine and is not that case. The two forms answer different
485    /// questions and a column that is both clustered and low cardinality genuinely wants both.
486    ///
487    /// # Errors
488    ///
489    /// If there is not exactly one value per run, if the ends do not increase, or if the values are
490    /// themselves run length encoded.
491    pub fn runs(ends: Vec<u32>, values: Vector) -> Result<Self> {
492        if matches!(values.body, Body::Runs { .. }) {
493            return Err(Error::internal("runs of runs, which is two searches to read one row"));
494        }
495        if ends.len() != values.len() {
496            return Err(Error::internal(format!(
497                "{} runs and {} values to put in them",
498                ends.len(),
499                values.len()
500            )));
501        }
502        if ends.windows(2).any(|pair| pair[0] >= pair[1]) || ends.first() == Some(&0) {
503            return Err(Error::internal("run ends that do not increase"));
504        }
505        let len = ends.last().copied().unwrap_or(0) as usize;
506        Ok(Self {
507            ty: values.ty.clone(),
508            len,
509            validity: Validity::AllValid,
510            body: Body::Runs { ends, values: Arc::new(values) },
511        })
512    }
513
514    /// The same values as runs, when there are few enough runs for that to be smaller.
515    ///
516    /// Costs one pass over the column to find out, which is why this is a call somebody makes rather
517    /// than something a constructor does. The decision is the same arithmetic every time: a row in
518    /// flat form costs one value, a run costs one value plus the four bytes of its end, so runs are
519    /// smaller once there are fewer than about half as many runs as rows, and the narrower the
520    /// column the more runs it takes. `RUNS_PAY_AT` is that ratio, written down rather than spelt
521    /// into an `if`, because it is the number a sweep will want to move.
522    ///
523    /// Only a flat body is looked at. A constant and a sequence are already one value and two
524    /// numbers, so there is nothing to win, and a dictionary that is also clustered is a real case
525    /// that wants its codes run length encoded rather than its values, which is a different function
526    /// and not this one.
527    ///
528    /// Two adjacent nulls are one run. Two adjacent equal values with a null between them are three,
529    /// because the null is a value of the column as far as anything reading it is concerned.
530    ///
531    /// # Errors
532    ///
533    /// If the type has no flat layout, which today means the nested types.
534    pub fn run_encoded(&self) -> Result<Self> {
535        let Body::Flat(data) = &self.body else {
536            return Ok(self.clone());
537        };
538        let ends = boundaries(data, &self.validity, self.len);
539        if ends.len().saturating_mul(RUNS_PAY_AT) >= self.len {
540            return Ok(self.clone());
541        }
542        let starts: Vec<u32> =
543            std::iter::once(0).chain(ends.iter().copied()).take(ends.len()).collect();
544        Self::runs(ends, self.gather(&starts)?)
545    }
546
547    /// A vector of `len` integers packed `width` bits each, every one an offset from `base`.
548    ///
549    /// The way in for a reader that already has the packed bits, which is what a column file holds
550    /// and what a network frame carries. Nothing unpacks on the way in, so a scan of a packed column
551    /// hands the bits straight to the chunk and the cost of the form is paid by whoever reads a
552    /// value rather than by the scan.
553    ///
554    /// The range check is on the two ends rather than on every code, which is the whole check. A
555    /// code is between zero and `2^width - 1` by construction, so if `base` and `base + 2^width - 1`
556    /// both fit the column's layout then every value does, and that is two comparisons instead of
557    /// one per row.
558    ///
559    /// # Errors
560    ///
561    /// If the type is not one of the integer layouts, if the width is not between one and
562    /// [`PACKED_WIDTH_MAX`], if there are not enough words for the length, or if either end of the
563    /// range would not fit the type.
564    pub fn packed(
565        ty: LogicalType,
566        words: Vec<u64>,
567        width: u32,
568        base: i128,
569        len: usize,
570    ) -> Result<Self> {
571        let Some((low, high)) = layout_range(&ty) else {
572            return Err(Error::internal(format!("a {ty} vector has no integer layout to pack")));
573        };
574        if width == 0 || width > PACKED_WIDTH_MAX {
575            return Err(Error::internal(format!(
576                "a packed width of {width}, which is outside 1 to {PACKED_WIDTH_MAX}"
577            )));
578        }
579        let needed = words_for(len, width);
580        if words.len() < needed {
581            return Err(Error::internal(format!(
582                "{} words for {len} values of {width} bits, which needs {needed}",
583                words.len()
584            )));
585        }
586        let top = base + i128::from(u64::MAX >> (64 - width));
587        if base < low || top > high {
588            return Err(Error::internal(format!(
589                "packed values from {base} to {top}, which a {ty} cannot hold"
590            )));
591        }
592        Ok(Self {
593            ty,
594            len,
595            validity: Validity::AllValid,
596            body: Body::Packed { words: Arc::new(words), width, base, offset: 0 },
597        })
598    }
599
600    /// The same values bit packed, when the range of the column makes that smaller.
601    ///
602    /// Costs one pass to find the range and one to write the bits, which is why this is a call
603    /// somebody makes rather than something a constructor does. It is the counterpart of
604    /// [`Self::run_encoded`] and the decision has the same shape: a row flat costs the width of its
605    /// layout, a row packed costs the bits the column's range needs, and the form is worth having
606    /// only when the second is a good deal smaller than the first. [`PACKING_PAYS_AT`] is that
607    /// ratio, written down rather than spelt into an `if`, because it is the number a sweep will
608    /// want to move.
609    ///
610    /// Only a flat integer body is looked at. A constant and a sequence are already smaller than any
611    /// packing of them, a dictionary's codes are the thing that would want packing rather than its
612    /// values, and a float has no range to pack into since the bits of an `f64` are not an integer
613    /// that arithmetic on the column agrees with.
614    ///
615    /// The range is taken over every slot including the null ones, which hold a zero. A column of
616    /// large values with one null in it therefore packs a range that reaches down to zero and comes
617    /// out wider than it needed to be. The alternative is a pass that consults the validity per slot
618    /// to find the range and a second rule for what to write into a null slot, and this form exists
619    /// to make reads cheap rather than to squeeze the last bit out of a sparse column.
620    ///
621    /// A column whose values are all the same packs to nothing at all, and rather than invent a zero
622    /// bit code this declines and leaves it to [`Self::run_encoded`], which turns that column into
623    /// one run and is smaller than any packing of it.
624    ///
625    /// # Errors
626    ///
627    /// If the packed bits and the length disagree, which would be a bug here rather than a caller
628    /// doing something wrong.
629    pub fn bit_packed(&self) -> Result<Self> {
630        let Body::Flat(data) = &self.body else {
631            return Ok(self.clone());
632        };
633        let Some((low, high)) = span_of(data, self.len) else {
634            return Ok(self.clone());
635        };
636        let Some(range) = high.checked_sub(low).and_then(|range| u64::try_from(range).ok()) else {
637            return Ok(self.clone());
638        };
639        let width = u64::BITS - range.leading_zeros();
640        if width == 0 || width > PACKED_WIDTH_MAX {
641            return Ok(self.clone());
642        }
643        if words_for(self.len, width) * size_of::<u64>() * PACKING_PAYS_AT > data.footprint() {
644            return Ok(self.clone());
645        }
646        let words = pack(data, self.len, low, width);
647        let packed = Self::packed(self.ty.clone(), words, width, low, self.len)?;
648        Ok(packed.with_validity(self.validity.clone()))
649    }
650
651    /// A vector of string views over an arena somebody else is holding too.
652    ///
653    /// The way in for a scan that has a page of strings and wants several chunks over it. Each chunk
654    /// gets its own run of views and they all share the one arena, so the bytes are read where the
655    /// page put them and nothing copies them.
656    ///
657    /// Every view is checked against the arena here rather than when a row is read. That is a pass
658    /// over the views at construction, which is the same pass the caller just did to build them, and
659    /// what it buys is that a row of this form cannot resolve to bytes that are not there. The check
660    /// is on the offsets and not on the bytes, so it says nothing about whether the payload is text,
661    /// which is the same promise a `BLOB` column makes.
662    ///
663    /// # Errors
664    ///
665    /// If the type is not one stored as views, or if a view points past the end of the arena.
666    pub fn string_views(
667        ty: LogicalType,
668        views: Vec<StringView>,
669        arena: Arc<Buffer<u8>>,
670    ) -> Result<Self> {
671        if ty.physical() != rudb_common::PhysicalType::Varlen {
672            return Err(Error::internal(format!("a {ty} vector cannot hold string views")));
673        }
674        if views.iter().any(|view| view.bytes_in(&arena).is_none()) {
675            return Err(Error::internal("a string view points past the end of its arena"));
676        }
677        let len = views.len();
678        Ok(Self { ty, len, validity: Validity::AllValid, body: Body::Views { views, arena } })
679    }
680
681    /// The same strings, in a form where a cut of them does not copy the bytes.
682    ///
683    /// The counterpart of [`Self::run_encoded`] and [`Self::bit_packed`] for a string column, and
684    /// the only one of the three that takes `self` by value. It has to: what it does is move the
685    /// arena into an `Arc` so nothing copies it again, and a version taking `&self` would start by
686    /// copying the arena once to have one to move.
687    ///
688    /// Anything that is not a flat string column comes back as it was, which includes a column that
689    /// is already in this form.
690    ///
691    /// # Errors
692    ///
693    /// Nothing here fails today. The result is a `Result` because the check inside
694    /// [`Self::string_views`] is worth running on the views this builds rather than trusting that
695    /// this function built them right.
696    pub fn shared_text(self) -> Result<Self> {
697        let Body::Flat(Data::Varlen(column)) = self.body else {
698            return Ok(self);
699        };
700        let (views, arena) = column.into_parts();
701        let shared = Self::string_views(self.ty, views, Arc::new(arena))?;
702        Ok(shared.with_validity(self.validity))
703    }
704
705    /// A vector of FSST codes against a table somebody else trained.
706    ///
707    /// The way in for a reader that has a page of compressed strings and the table that goes with
708    /// it. The codes are not copied and the table is not retrained, so laying several chunks over
709    /// one page costs the spans and nothing else.
710    ///
711    /// # Errors
712    ///
713    /// If the type is not one stored as text, or if a span runs past the end of the codes.
714    pub fn coded(
715        ty: LogicalType,
716        codes: Arc<Vec<u8>>,
717        spans: Vec<(u32, u32)>,
718        table: Arc<SymbolTable>,
719    ) -> Result<Self> {
720        if ty.physical() != rudb_common::PhysicalType::Varlen {
721            return Err(Error::internal(format!("a {ty} vector cannot hold FSST codes")));
722        }
723        let end = u32::try_from(codes.len()).unwrap_or(u32::MAX);
724        if spans.iter().any(|&(from, to)| from > to || to > end) {
725            return Err(Error::internal("an FSST span runs past the end of the codes"));
726        }
727        let len = spans.len();
728        Ok(Self {
729            ty,
730            len,
731            validity: Validity::AllValid,
732            body: Body::Coded { codes, spans, table },
733        })
734    }
735
736    /// The same strings, compressed against a table trained on them.
737    ///
738    /// The counterpart of [`Self::run_encoded`] and [`Self::bit_packed`] for a text column, and it
739    /// takes `self` by value for the reason [`Self::shared_text`] does.
740    ///
741    /// The table is trained on every row rather than on a sample. A vector is at most 1024 rows, so
742    /// the sample would be most of the column anyway, and the systematic sampling
743    /// `spec/06-compression.md` section 6.3 asks for is a decision about a page and belongs to
744    /// whoever is holding one.
745    ///
746    /// It declines unless the codes are at most half the bytes the strings are. FSST gets about that
747    /// on text and rather less on anything already short or already random, and below that the
748    /// decompression per row read is not bought back. A column it declines on comes back as it was.
749    ///
750    /// # Errors
751    ///
752    /// Nothing here fails today. The result is a `Result` because the checks inside [`Self::coded`]
753    /// are worth running on what this builds rather than trusting that this built it right.
754    pub fn compressed(self) -> Result<Self> {
755        let Body::Flat(Data::Varlen(column)) = &self.body else {
756            return Ok(self);
757        };
758        let rows: Vec<&[u8]> = (0..self.len).filter_map(|row| column.bytes(row)).collect();
759        if rows.len() != self.len {
760            return Ok(self);
761        }
762        let plain: usize = rows.iter().map(|row| row.len()).sum();
763        let table = SymbolTable::train(&rows);
764        let mut codes = Vec::with_capacity(plain);
765        let mut spans = Vec::with_capacity(self.len);
766        for row in &rows {
767            let from = u32::try_from(codes.len()).unwrap_or(u32::MAX);
768            table.compress(row, &mut codes);
769            spans.push((from, u32::try_from(codes.len()).unwrap_or(u32::MAX)));
770        }
771        if codes.len() * FSST_PAYS_AT > plain {
772            return Ok(self);
773        }
774        let coded = Self::coded(self.ty.clone(), Arc::new(codes), spans, Arc::new(table))?;
775        Ok(coded.with_validity(self.validity.clone()))
776    }
777
778    /// The same vector with a different validity.
779    #[must_use]
780    pub fn with_validity(mut self, validity: Validity) -> Self {
781        self.validity = validity;
782        self
783    }
784
785    /// What kind of values these are.
786    #[must_use]
787    pub fn logical_type(&self) -> &LogicalType {
788        &self.ty
789    }
790
791    /// How many values there are.
792    #[must_use]
793    pub fn len(&self) -> usize {
794        self.len
795    }
796
797    /// Whether there are no values.
798    #[must_use]
799    pub fn is_empty(&self) -> bool {
800        self.len == 0
801    }
802
803    /// How many bytes of memory this vector is holding.
804    ///
805    /// What the memory limit charges for it. A constant and a sequence hold one value and two
806    /// numbers however long they are, which is the point of both forms, so the number here is the
807    /// form's cost and not the column's width times its length.
808    ///
809    /// A dictionary counts its values in full, and two vectors sharing one dictionary each report
810    /// all of it. That over counts, deliberately: working out that two operators are looking at the
811    /// same `Arc` means threading identity through the accounting, and a limit that over counts
812    /// refuses a query that would have fit while a limit that under counts lets one through that
813    /// does not. The first is a worse answer to give and the second is a worse thing to be.
814    #[must_use]
815    pub fn footprint(&self) -> usize {
816        let body = match &self.body {
817            Body::Flat(data) => data.footprint(),
818            Body::Constant(value) => value.footprint(),
819            Body::Sequence { .. } => 0,
820            Body::Dictionary { codes, values } => {
821                codes.capacity() * size_of::<u32>() + values.footprint()
822            }
823            Body::Packed { words, .. } => words.capacity() * size_of::<u64>(),
824            // The arena counts in full in every vector sharing it, for the reason a shared
825            // dictionary does: over counting refuses a query that would have fit and under counting
826            // admits one that does not, and the first is the better way to be wrong.
827            Body::Views { views, arena } => {
828                views.capacity() * size_of::<StringView>() + arena.footprint()
829            }
830            // The table counts in full in every vector sharing it, the way a shared arena and a
831            // shared dictionary do. It is the largest of the three and the most shared of them, so
832            // this is the one place the over counting is worth saying out loud: a page of a hundred
833            // chunks reports its table a hundred times.
834            Body::Coded { codes, spans, table } => {
835                codes.capacity() + spans.capacity() * size_of::<(u32, u32)>() + table.footprint()
836            }
837            Body::Runs { ends, values } => ends.capacity() * size_of::<u32>() + values.footprint(),
838        };
839        size_of::<Self>() + self.validity.footprint() + body
840    }
841
842    /// Which of the values are not null, at this level and no deeper.
843    ///
844    /// This is not the same question as [`Self::is_null_at`] and the difference has already cost
845    /// one wrong answer. A dictionary and a run length vector keep their nulls in the values they
846    /// point at rather than in a mask of their own, so both are built with every row marked present
847    /// here and a row whose value is null reads as valid. A caller that wants to know whether a row
848    /// is null wants the other one. A caller that wants the mask of a flat column, to copy it or to
849    /// count it, wants this one.
850    #[must_use]
851    pub fn validity(&self) -> &Validity {
852        &self.validity
853    }
854
855    /// Whether the row at `index` is null, in whichever form the vector is in.
856    ///
857    /// Reads through a dictionary or a run to the value it stands for, which is where those two
858    /// forms keep their nulls, and answers from the mask for every other form. A row past the end
859    /// is null, the same answer [`Self::value_at`] gives it.
860    #[must_use]
861    pub fn is_null_at(&self, index: usize) -> bool {
862        if index >= self.len || !self.validity.is_valid(index) {
863            return true;
864        }
865        match &self.body {
866            Body::Dictionary { codes, values } => match codes.get(index) {
867                Some(&code) => values.is_null_at(code as usize),
868                None => true,
869            },
870            Body::Runs { ends, values } => match run_holding(ends, index) {
871                Some(run) => values.is_null_at(run),
872                None => true,
873            },
874            _ => false,
875        }
876    }
877
878    /// Which physical form this vector is in.
879    #[must_use]
880    pub fn form(&self) -> Form {
881        match self.body {
882            Body::Flat(_) => Form::Flat,
883            Body::Constant(_) => Form::Constant,
884            Body::Sequence { .. } => Form::Sequence,
885            Body::Dictionary { .. } => Form::Dictionary,
886            Body::Packed { .. } => Form::BitPacked,
887            Body::Views { .. } => Form::StringView,
888            Body::Coded { .. } => Form::Fsst,
889            Body::Runs { .. } => Form::Rle,
890        }
891    }
892
893    /// The data, for a flat vector, and `None` for any other form.
894    ///
895    /// A kernel that wants a slice asks for it and takes the flat path if it gets one. A kernel
896    /// that can do better on a constant or a dictionary checks [`Self::form`] first.
897    #[must_use]
898    pub fn data(&self) -> Option<&Data> {
899        match &self.body {
900            Body::Flat(data) => Some(data),
901            _ => None,
902        }
903    }
904
905    /// The one value, for a constant vector, and `None` for any other form.
906    ///
907    /// A kernel comparing a column against a literal wants the literal once rather than 1024
908    /// times, and [`Self::value_at`] on a constant clones it on every call because it has to be
909    /// able to hand back a `Value` for any form. This is the accessor that lets the specialized
910    /// path hoist the clone out of the loop.
911    #[must_use]
912    pub fn constant_value(&self) -> Option<&Value> {
913        match &self.body {
914            Body::Constant(value) => Some(value.as_ref()),
915            _ => None,
916        }
917    }
918
919    /// The codes and the values, for a dictionary vector, and `None` for any other form.
920    ///
921    /// The reason a kernel needs this rather than reading the dictionary through
922    /// [`Self::value_at`] is the entire argument for the form existing. A filter against a
923    /// dictionary column of 1024 rows and 40 distinct values is 40 comparisons and 1024 lookups,
924    /// not 1024 comparisons, and there is no way to write that loop without seeing the codes.
925    ///
926    /// Note what the validity of the returned vector means. A dictionary keeps its nulls in the
927    /// vector it points at, and the dictionary's own validity says nothing about them, so a caller
928    /// deciding whether row `i` is null has to ask the value vector about `codes[i]` rather than
929    /// asking this vector about `i`. [`Self::flatten`] has the same note on it for the same
930    /// reason, because getting this wrong is a null that survives being selected and comes out as
931    /// a zero.
932    #[must_use]
933    pub fn dictionary_parts(&self) -> Option<(&[u32], &Self)> {
934        match &self.body {
935            Body::Dictionary { codes, values } => Some((codes, values.as_ref())),
936            _ => None,
937        }
938    }
939
940    /// The run ends and the run values, for a run length vector, and `None` for any other form.
941    ///
942    /// The ends are exclusive and increasing, and there is exactly one value per run, so a kernel
943    /// that wants to walk this walks the pairs and never asks which run a row is in. That is the
944    /// whole argument for the form: an aggregate over a clustered column is one multiply per run
945    /// instead of one add per row, and there is no way to write that loop without seeing the ends.
946    ///
947    /// The nulls are in the values, the way a dictionary's are, so a caller deciding whether row `i`
948    /// is null asks the value vector about the run rather than asking this vector about `i`.
949    #[must_use]
950    pub fn run_parts(&self) -> Option<(&[u32], &Self)> {
951        match &self.body {
952            Body::Runs { ends, values } => Some((ends, values.as_ref())),
953            _ => None,
954        }
955    }
956
957    /// Where each row's value is, for the two forms that keep their values somewhere else.
958    ///
959    /// A dictionary and a run length vector are the same shape seen from a kernel: a run of
960    /// positions and a vector to read them out of. The difference is that a dictionary stores the
961    /// positions and a run length vector works them out, and a kernel writing `values[at[row]]` does
962    /// not care which. So every specialization written against [`Self::dictionary_parts`] covers
963    /// both forms by asking this instead, and the day a third form with an indirection arrives it
964    /// covers that one too without any of those kernels being reopened.
965    ///
966    /// The run length side costs an allocation of one position per row and a pass to fill it, which
967    /// is the same four bytes a row a dictionary was already carrying and is paid once per kernel
968    /// call rather than once per row. That is the price of this being one accessor rather than a
969    /// second arm in eighteen kernels, and it is not the last word: a kernel that wants a run at a
970    /// time reads [`Self::run_parts`] and pays nothing, which is the specialization this makes it
971    /// possible to skip writing until a sweep says it is worth it.
972    #[must_use]
973    pub fn positions(&self) -> Option<(Cow<'_, [u32]>, &Self)> {
974        match &self.body {
975            Body::Dictionary { codes, values } => Some((Cow::Borrowed(codes), values.as_ref())),
976            Body::Runs { ends, values } => {
977                let mut at = Vec::with_capacity(self.len);
978                for (run, &stop) in ends.iter().enumerate() {
979                    let run = u32::try_from(run).unwrap_or(u32::MAX);
980                    at.resize(stop as usize, run);
981                }
982                Some((Cow::Owned(at), values.as_ref()))
983            }
984            _ => None,
985        }
986    }
987
988    /// The bits and what they mean, for a bit packed vector, and `None` for any other form.
989    ///
990    /// What a kernel needs to stay in code space. A comparison against a literal is the case that
991    /// pays: `column > 900` over a column packed from a base of 40 is `code > 860`, which is the
992    /// same shift and mask the read was going to do anyway and no unpacking at all, and a literal
993    /// outside the packed range answers the whole vector without reading a bit of it. None of that
994    /// can be written without seeing the width and the base.
995    #[must_use]
996    pub fn packed_parts(&self) -> Option<Packed<'_>> {
997        match &self.body {
998            Body::Packed { words, width, base, offset } => {
999                Some(Packed { words, width: *width, base: *base, offset: *offset })
1000            }
1001            _ => None,
1002        }
1003    }
1004
1005    /// The views and the arena, for either form that stores strings, and `None` for the rest.
1006    ///
1007    /// This is to the two string forms what [`Self::positions`] is to the two forms that point
1008    /// somewhere else. A flat varchar column owns its arena and a string view column shares one, and
1009    /// a kernel reading a row wants the view and the bytes either way, so every specialization
1010    /// written against this covers both forms and neither has to be reopened when a third way of
1011    /// holding an arena arrives.
1012    ///
1013    /// The arena is whatever the long strings live in, which for a column over a page is the page,
1014    /// including the parts of it no view points at. Only the views say which bytes are a row.
1015    #[must_use]
1016    pub fn text_parts(&self) -> Option<(&[StringView], &[u8])> {
1017        match &self.body {
1018            Body::Flat(Data::Varlen(column)) => Some((column.views(), column.arena())),
1019            Body::Views { views, arena } => Some((views, arena)),
1020            _ => None,
1021        }
1022    }
1023
1024    /// The codes and the table, for an FSST vector, and `None` for any other form.
1025    ///
1026    /// What a kernel needs to stay in code space. An equality filter is the case that pays, and it
1027    /// pays completely: the literal is compressed once against the same table and after that a row
1028    /// matches exactly when its code bytes match, because compressing is a function and so is
1029    /// decompressing. No row is decompressed at all. An ordering comparison cannot do that, since a
1030    /// symbol code says nothing about where its symbol sorts, so those decompress and say so.
1031    #[must_use]
1032    pub fn coded_parts(&self) -> Option<Coded<'_>> {
1033        match &self.body {
1034            Body::Coded { codes, spans, table } => Some(Coded { codes, spans, table }),
1035            _ => None,
1036        }
1037    }
1038
1039    /// The start and the step, for a sequence vector, and `None` for any other form.
1040    #[must_use]
1041    pub fn sequence_parts(&self) -> Option<(i64, i64)> {
1042        match self.body {
1043            Body::Sequence { start, step } => Some((start, step)),
1044            _ => None,
1045        }
1046    }
1047
1048    /// The value at `index`, as a single value.
1049    ///
1050    /// This is the slow path on purpose. It is what a result set is read out with and what a test
1051    /// asserts on, and an operator that calls it per row is an operator that has already lost the
1052    /// argument the vector interface exists to win.
1053    #[must_use]
1054    pub fn value_at(&self, index: usize) -> Value {
1055        if index >= self.len || !self.validity.is_valid(index) {
1056            return Value::Null;
1057        }
1058        match &self.body {
1059            Body::Constant(value) => value.as_ref().clone(),
1060            Body::Sequence { start, step } => Value::BigInt(start + step * index as i64),
1061            Body::Dictionary { codes, values } => match codes.get(index) {
1062                Some(&code) => values.value_at(code as usize),
1063                None => Value::Null,
1064            },
1065            Body::Runs { ends, values } => match run_holding(ends, index) {
1066                Some(run) => values.value_at(run),
1067                None => Value::Null,
1068            },
1069            // One value unpacked into a run of one, so that what a packed value means is decided in
1070            // the same place a flat one is rather than in a second copy of the type mapping that
1071            // could drift from it. It allocates, which this path is allowed to do and the typed
1072            // unpack in `copied` is not, and it is the reason anything about to read a packed
1073            // column a row at a time should flatten it once instead.
1074            Body::Packed { words, width, base, offset } => {
1075                unpack(&self.ty, words, *offset, *width, *base, &[index])
1076                    .map_or(Value::Null, |data| value_from(&self.ty, &data, 0))
1077            }
1078            // The bytes are where the arena has them, and what they are read as is the logical
1079            // type's business, so this hands the row to the same reader a flat column goes through
1080            // rather than deciding here that a `BLOB` is a string.
1081            Body::Views { views, arena } => {
1082                match views.get(index).and_then(|v| v.bytes_in(arena)) {
1083                    Some(bytes) => bytes_as(&self.ty, bytes),
1084                    None => Value::Null,
1085                }
1086            }
1087            // One row decompressed on its own, which is the property the form is chosen for. It
1088            // allocates, which this path is allowed to do, and it is the reason anything about to
1089            // read a compressed column a row at a time should flatten it once instead.
1090            Body::Coded { codes, spans, table } => {
1091                match spans.get(index).and_then(|&(from, to)| {
1092                    let mut out = Vec::new();
1093                    table.decompress(codes.get(from as usize..to as usize)?, &mut out).ok()?;
1094                    Some(out)
1095                }) {
1096                    Some(bytes) => bytes_as(&self.ty, &bytes),
1097                    None => Value::Null,
1098                }
1099            }
1100            Body::Flat(data) => value_from(&self.ty, data, index),
1101        }
1102    }
1103
1104    /// The text at `index`, borrowed rather than copied.
1105    ///
1106    /// [`Self::value_at`] on a `VARCHAR` column allocates a `String` per call, and a group by that
1107    /// reads a string column keys on one string per input row. This hands back the bytes where they
1108    /// already are, so a caller with somewhere to put them does not go to the allocator at all.
1109    ///
1110    /// `None` for a null, for an index past the end, for a column that is not `VARCHAR`, and for the
1111    /// constant and sequence forms, whose values are not stored per position. A caller that gets
1112    /// `None` has to fall back to [`Self::value_at`], which is correct for all of those.
1113    #[must_use]
1114    pub fn text_at(&self, index: usize) -> Option<&str> {
1115        if self.ty != LogicalType::Varchar || index >= self.len || !self.validity.is_valid(index) {
1116            return None;
1117        }
1118        match &self.body {
1119            Body::Flat(data) => data.str_at(index),
1120            Body::Dictionary { codes, values } => {
1121                values.text_at(usize::try_from(*codes.get(index)?).ok()?)
1122            }
1123            Body::Runs { ends, values } => values.text_at(run_holding(ends, index)?),
1124            Body::Views { views, arena } => {
1125                std::str::from_utf8(views.get(index)?.bytes_in(arena)?).ok()
1126            }
1127            _ => None,
1128        }
1129    }
1130
1131    /// The variable length bytes at `index`, borrowed without validating or copying them.
1132    ///
1133    /// String data is validated when it enters a vector. Hashing and equality only need its bytes,
1134    /// so those kernels should not pay for UTF-8 validation again on every read.
1135    #[must_use]
1136    pub fn bytes_at(&self, index: usize) -> Option<&[u8]> {
1137        if index >= self.len || !self.validity.is_valid(index) {
1138            return None;
1139        }
1140        match &self.body {
1141            Body::Constant(value) => match value.as_ref() {
1142                Value::Varchar(text) => Some(text.as_bytes()),
1143                Value::Blob(bytes) => Some(bytes),
1144                _ => None,
1145            },
1146            Body::Dictionary { codes, values } => {
1147                values.bytes_at(usize::try_from(*codes.get(index)?).ok()?)
1148            }
1149            Body::Runs { ends, values } => values.bytes_at(run_holding(ends, index)?),
1150            Body::Views { views, arena } => views.get(index)?.bytes_in(arena),
1151            Body::Flat(data) => data.bytes_at(index),
1152            // The same `None` [`Self::text_at`] gives, for the same reason. A compressed row is not
1153            // anywhere in its plain bytes, so there is nothing here to hand back a borrow of, and a
1154            // caller that gets `None` goes to `value_at` and gets the row decompressed into a value.
1155            Body::Coded { .. } | Body::Sequence { .. } | Body::Packed { .. } => None,
1156        }
1157    }
1158
1159    /// The signed integer at `index`, widened, read without building a [`Value`].
1160    ///
1161    /// The integer sibling of [`Self::bytes_at`], and it is here for the same caller. A group by on
1162    /// an integer column compares one key per input row against the group it probed, and doing that
1163    /// through [`Self::value_at`] built and dropped a sixty four byte value a row at a time for a
1164    /// number that was already sitting in the column.
1165    ///
1166    /// Widened to `i128` because that is what [`Data::signed_at`] hands back underneath, and one
1167    /// method that covers every signed width is worth more than five that do not. A caller that
1168    /// wants a narrower type narrows it, which is a range check against a value in a register.
1169    ///
1170    /// The types this answers for are the ones whose flat data is read through `signed_at`, so the
1171    /// five signed integer widths and the decimal, date, time and timestamp types that are stored
1172    /// in them. A decimal answers with its unscaled value, which is the number the column holds.
1173    ///
1174    /// `None` for a null, for an index past the end, for a column of any other type, and for the
1175    /// packed and compressed forms, whose rows are not stored as integers anywhere a read can reach
1176    /// without unpacking. A caller that gets `None` falls back to [`Self::value_at`], which is
1177    /// correct for all of those.
1178    #[must_use]
1179    pub fn signed_at(&self, index: usize) -> Option<i128> {
1180        if index >= self.len || !self.validity.is_valid(index) {
1181            return None;
1182        }
1183        match &self.body {
1184            Body::Flat(data) => data.signed_at(index),
1185            Body::Constant(value) => match value.as_ref() {
1186                Value::TinyInt(x) => Some(i128::from(*x)),
1187                Value::SmallInt(x) => Some(i128::from(*x)),
1188                Value::Integer(x) | Value::Date(x) => Some(i128::from(*x)),
1189                Value::BigInt(x) | Value::Time(x) | Value::Timestamp(x) => Some(i128::from(*x)),
1190                Value::HugeInt(x) | Value::Decimal { unscaled: x, .. } => Some(*x),
1191                _ => None,
1192            },
1193            // The same arithmetic [`Self::value_at`] does on a sequence, so the two agree about a
1194            // sequence that runs off the end of the width it is stored in.
1195            Body::Sequence { start, step } => {
1196                Some(i128::from(start.wrapping_add(step.wrapping_mul(index as i64))))
1197            }
1198            Body::Dictionary { codes, values } => {
1199                values.signed_at(usize::try_from(*codes.get(index)?).ok()?)
1200            }
1201            Body::Runs { ends, values } => values.signed_at(run_holding(ends, index)?),
1202            // The same `None` [`Self::bytes_at`] gives, for the same reason. A packed or compressed
1203            // row is not an integer anywhere until it has been unpacked, and a caller that gets
1204            // `None` goes to `value_at` and gets the row unpacked into a value.
1205            Body::Coded { .. } | Body::Packed { .. } | Body::Views { .. } => None,
1206        }
1207    }
1208
1209    /// Every value in order, as single values.
1210    pub fn iter(&self) -> impl Iterator<Item = Value> + '_ {
1211        (0..self.len).map(|index| self.value_at(index))
1212    }
1213
1214    /// A contiguous run of the values, in the form they are already in.
1215    ///
1216    /// This is the cut [`Self::gather`] cannot do. A gather walks a dictionary to its leaf and
1217    /// copies, so gathering a piece of a dictionary encoded column hands back a flat one, and a
1218    /// caller that only wanted the first thousand rows of a page has silently paid for a copy and
1219    /// thrown the dictionary away. A group by over a dictionary encoded column is the case that
1220    /// cares, and it is most of ClickBench.
1221    ///
1222    /// So each form is cut as itself. A dictionary keeps its dictionary and slices its codes, a
1223    /// sequence stays arithmetic with its start moved along, a constant stays a shorter constant,
1224    /// and a flat body is the one that genuinely has to copy its range.
1225    ///
1226    /// The dictionary itself is shared rather than copied, so a cut is the codes and nothing else.
1227    /// It used to be copied, and on a read of a ClickBench partition that copy was ten percent of
1228    /// the cycles: a page holds one dictionary and is cut into chunk sized pieces, so the whole
1229    /// dictionary was copied once per chunk to be read the same way each time.
1230    ///
1231    /// # Errors
1232    ///
1233    /// If the range runs past the end of the vector, or if the type has no flat layout and the
1234    /// body is one that has to be copied.
1235    pub fn slice(&self, at: usize, len: usize) -> Result<Self> {
1236        let end = at.checked_add(len).ok_or_else(|| Error::internal("a slice that wraps"))?;
1237        if end > self.len {
1238            return Err(Error::internal(format!("rows {at} to {end} of a vector of {}", self.len)));
1239        }
1240        if at == 0 && len == self.len {
1241            return Ok(self.clone());
1242        }
1243        let validity = Validity::from_iter(len, |row| self.validity.is_valid(at + row));
1244        let body = match &self.body {
1245            Body::Constant(value) => Body::Constant(value.clone()),
1246            Body::Sequence { start, step } => {
1247                Body::Sequence { start: start + step * at as i64, step: *step }
1248            }
1249            Body::Dictionary { codes, values } => {
1250                Body::Dictionary { codes: codes[at..end].to_vec(), values: Arc::clone(values) }
1251            }
1252            // The bits are not byte aligned, so a cut either repacks them or moves the row the
1253            // reading starts at. Moving it is one addition and repacking is a pass, and a page is
1254            // cut into chunk sized pieces often enough that the difference is the form.
1255            Body::Packed { words, width, base, offset } => Body::Packed {
1256                words: Arc::clone(words),
1257                width: *width,
1258                base: *base,
1259                offset: offset + at,
1260            },
1261            // The cut a flat string column cannot do. Sixteen bytes a row move and the payload stays
1262            // where the page put it, so taking a chunk out of a column of long strings costs the
1263            // same as taking one out of a column of integers. A flat varchar body copies every byte
1264            // of every long string in the range instead, which is the measurement written down in
1265            // `Chunk::compact`: compaction loses on a varchar column, and this is the half of the
1266            // reason that is about cutting rather than about selecting.
1267            Body::Views { views, arena } => {
1268                Body::Views { views: views[at..end].to_vec(), arena: Arc::clone(arena) }
1269            }
1270            // The spans are absolute positions in the shared codes, so a cut is a run of them and
1271            // nothing has to be rebased. One page of compressed strings, one table, and as many
1272            // chunks over it as the reader wants.
1273            Body::Coded { codes, spans, table } => Body::Coded {
1274                codes: Arc::clone(codes),
1275                spans: spans[at..end].to_vec(),
1276                table: Arc::clone(table),
1277            },
1278            // Only the runs the range touches survive, the first and last of them cut back to where
1279            // the range starts and stops, and every end moved to be relative to the new row zero. A
1280            // cut of a hundred rows out of a column of a hundred million is a handful of runs, which
1281            // is the reason this form is worth cutting as itself rather than copying out.
1282            Body::Runs { ends, values } if len > 0 => {
1283                let first = run_holding(ends, at).unwrap_or(0);
1284                let last = run_holding(ends, end - 1).unwrap_or(first);
1285                let cut: Vec<u32> = ends[first..=last]
1286                    .iter()
1287                    .map(|&stop| stop.min(end as u32) - at as u32)
1288                    .collect();
1289                let values = values.slice(first, last - first + 1)?;
1290                Body::Runs { ends: cut, values: Arc::new(values) }
1291            }
1292            // An empty cut has no run to point at and an empty run length body would be a vector of
1293            // no runs claiming a length, so it comes back as the empty flat vector instead.
1294            Body::Runs { .. } => return self.gather(&[]),
1295            // The one form with nowhere to point, so its range is copied out. A gather is the
1296            // right tool here and does no more than this would: a flat body has no dictionary
1297            // under it for the gather to flatten.
1298            Body::Flat(_) => {
1299                let indices: Vec<u32> =
1300                    (at..end).map(|row| u32::try_from(row).unwrap_or(u32::MAX)).collect();
1301                return self.gather(&indices);
1302            }
1303        };
1304        Ok(Self { ty: self.ty.clone(), len, validity, body })
1305    }
1306
1307    /// The same values in flat form.
1308    ///
1309    /// Flattening a vector that is already flat is free. Flattening any other form costs a copy,
1310    /// which is exactly why the other forms exist and why nothing on the hot path should call
1311    /// this. It is here for the operators that genuinely cannot do better and for the tests that
1312    /// check the other forms against it.
1313    ///
1314    /// A call that copies counts itself against [`Cause::Flatten`], because a flatten on a hot path
1315    /// is the most expensive thing in this crate and the only way to find one is to have the number.
1316    /// A call on a vector that is already flat does not count, since it neither copies nor gives
1317    /// anything up.
1318    ///
1319    /// # Errors
1320    ///
1321    /// If the type is one this crate cannot store flat yet, which today means the nested types.
1322    pub fn flatten(&self) -> Result<Self> {
1323        if let Body::Flat(_) = self.body {
1324            return Ok(self.clone());
1325        }
1326        slow::took(Cause::Flatten);
1327        self.copied((0..self.len).collect(), false)
1328    }
1329
1330    /// The values at the given positions, copied, in a form that does not point back at this vector.
1331    ///
1332    /// This is the copying counterpart to [`Self::dictionary`], and the two are the two halves of
1333    /// the decision `spec/07-execution.md` section 7.1 describes. Which half is right is measured
1334    /// rather than argued, and [`Chunk::compact`](crate::Chunk::compact) is where the measurement
1335    /// is written down.
1336    ///
1337    /// A dictionary chain is walked to its leaf first and the codes composed on the way down, so the
1338    /// copy runs once over the data rather than once per level, and a position that is null at any
1339    /// level comes out null here. The copy is a typed loop per physical layout rather than a `Value`
1340    /// per row, which is the whole point of it and is what [`Self::flatten`] now goes through too.
1341    ///
1342    /// # Errors
1343    ///
1344    /// If the type has no flat layout, which today means the nested types.
1345    pub fn gather(&self, indices: &[u32]) -> Result<Self> {
1346        self.copied(indices.iter().map(|&index| index as usize).collect(), true)
1347    }
1348
1349    /// The copy both [`Self::gather`] and [`Self::flatten`] are.
1350    ///
1351    /// `forms_stay` is the one thing the two want differently. A gather of a constant is a shorter
1352    /// constant and copying it out would be a thousand writes of the same value for nothing, and a
1353    /// gather of string views is a shorter run of views over the same arena rather than a copy of
1354    /// the bytes. Flattening promises flat form to a caller that is about to read the data slice, so
1355    /// for that one both of them have to be written out.
1356    fn copied(&self, at: Vec<usize>, forms_stay: bool) -> Result<Self> {
1357        let rows = at.len();
1358        let (at, leaf) = self.resolve(at);
1359        let live: Vec<bool> = at.iter().map(|&index| index != NOWHERE).collect();
1360        let validity = Validity::from_run(&live);
1361        let body = match &leaf.body {
1362            // Every position holds the same value, so the only thing the gather can change is the
1363            // length and which positions are null. A gather with no null in it is still a constant.
1364            Body::Constant(value) => {
1365                if forms_stay && matches!(validity, Validity::AllValid) {
1366                    return Ok(Self::constant(self.ty.clone(), value.as_ref().clone(), rows));
1367                }
1368                let mut data = empty_data_for(&self.ty)?;
1369                for &index in &at {
1370                    push_value(&mut data, if index == NOWHERE { &Value::Null } else { value })?;
1371                }
1372                Body::Flat(data)
1373            }
1374            // A sequence is arithmetic rather than storage, so the gather is the arithmetic done at
1375            // the positions asked for, and a null writes the zero every other layout writes.
1376            Body::Sequence { start, step } => Body::Flat(Data::Int64(
1377                at.iter()
1378                    .map(|&index| if index == NOWHERE { 0 } else { start + step * index as i64 })
1379                    .collect(),
1380            )),
1381            // A flat body with no values is the untyped null, so every position asked for is null
1382            // whatever was asked for. Going through the copy would build a run of no values and
1383            // call it `rows` long, which is a vector whose length and data disagree.
1384            Body::Flat(Data::Empty) => {
1385                return Ok(Self::constant(self.ty.clone(), Value::Null, rows));
1386            }
1387            Body::Flat(data) => Body::Flat(copy_of(data, &at)),
1388            // The one form whose copy is arithmetic rather than a move of bytes. It goes through a
1389            // typed loop per layout the way the flat copy does, because the alternative is a `Value`
1390            // per row and this is the path a flatten of a scanned column takes.
1391            Body::Packed { words, width, base, offset } => {
1392                Body::Flat(unpack(&self.ty, words, *offset, *width, *base, &at)?)
1393            }
1394            // A gather keeps the form, which is what makes selecting rows out of a string column
1395            // cost sixteen bytes a row instead of the bytes of the strings. The arena it shares is
1396            // the whole arena and not the part the kept rows point at, so a selection that throws
1397            // most of a page away goes on holding the page. That is the trade the form is: a cut and
1398            // a filter are cheap and the memory comes back when the last vector over the page goes,
1399            // and a caller that wants the bytes narrowed asks for a flatten.
1400            Body::Views { views, arena } if forms_stay => Body::Views {
1401                views: at
1402                    .iter()
1403                    .map(|&index| views.get(index).copied().unwrap_or_else(StringView::empty))
1404                    .collect(),
1405                arena: Arc::clone(arena),
1406            },
1407            // Flattening promises a data slice, so the bytes are copied out into an arena of their
1408            // own and the shared one is let go of. The total is known before any of it is copied,
1409            // the way the flat copy works it out, so the new arena is one allocation.
1410            Body::Views { views, arena } => {
1411                let mut out = StringColumn::with_capacity(at.len());
1412                out.reserve_bytes(
1413                    at.iter()
1414                        .filter_map(|&index| views.get(index))
1415                        .filter(|view| !view.is_inline())
1416                        .map(StringView::len)
1417                        .sum(),
1418                );
1419                for &index in &at {
1420                    let bytes = views.get(index).and_then(|view| view.bytes_in(arena));
1421                    out.push_bytes(bytes.unwrap_or_default());
1422                }
1423                Body::Flat(Data::Varlen(out))
1424            }
1425            // A gather keeps the form, because the codes do not move and a span survives being put
1426            // in an order the codes are not in. A position that resolved to nowhere gets the empty
1427            // span, which decompresses to no bytes, which is the zero every other layout writes.
1428            Body::Coded { codes, spans, table } if forms_stay => Body::Coded {
1429                codes: Arc::clone(codes),
1430                spans: at
1431                    .iter()
1432                    .map(|&index| spans.get(index).copied().unwrap_or((0, 0)))
1433                    .collect(),
1434                table: Arc::clone(table),
1435            },
1436            // Flattening decompresses, which is the price of the data slice it promises. The scratch
1437            // buffer is reused across rows, so this is one allocation for the whole column rather
1438            // than one per row the way reading it a value at a time would be.
1439            Body::Coded { codes, spans, table } => {
1440                let mut out = StringColumn::with_capacity(at.len());
1441                let mut scratch = Vec::new();
1442                for &index in &at {
1443                    scratch.clear();
1444                    let span = spans
1445                        .get(index)
1446                        .and_then(|&(from, to)| codes.get(from as usize..to as usize));
1447                    if let Some(span) = span {
1448                        table.decompress(span, &mut scratch)?;
1449                    }
1450                    out.push_bytes(&scratch);
1451                }
1452                Body::Flat(Data::Varlen(out))
1453            }
1454            // Unreachable, because `resolve` walks past both of the forms that point at another
1455            // vector and stops at the first body that does not.
1456            Body::Dictionary { .. } | Body::Runs { .. } => {
1457                return Err(Error::internal(
1458                    "a form that points somewhere survived being resolved",
1459                ));
1460            }
1461        };
1462        Ok(Self { ty: self.ty.clone(), len: rows, validity, body })
1463    }
1464
1465    /// Where each wanted position lives in the first body that is not a dictionary, and that body.
1466    ///
1467    /// A position that is null anywhere on the way down, or past the end of anything on the way
1468    /// down, comes back as [`NOWHERE`]. That single sentinel is what keeps the copy loop from
1469    /// carrying a validity mask alongside the positions it is already walking.
1470    fn resolve(&self, mut at: Vec<usize>) -> (Vec<usize>, &Self) {
1471        let mut source = self;
1472        loop {
1473            for slot in &mut at {
1474                if *slot >= source.len || !source.validity.is_valid(*slot) {
1475                    *slot = NOWHERE;
1476                }
1477            }
1478            source = match &source.body {
1479                Body::Dictionary { codes, values } => {
1480                    for slot in &mut at {
1481                        *slot = match codes.get(*slot) {
1482                            Some(&code) => code as usize,
1483                            None => NOWHERE,
1484                        };
1485                    }
1486                    values.as_ref()
1487                }
1488                // A run length body is a dictionary whose code is worked out from the position
1489                // rather than stored, so the walk down is the same walk with a search where the
1490                // lookup was. `NOWHERE` searches for nothing and stays `NOWHERE`.
1491                Body::Runs { ends, values } => {
1492                    for slot in &mut at {
1493                        *slot = run_holding(ends, *slot).unwrap_or(NOWHERE);
1494                    }
1495                    values.as_ref()
1496                }
1497                _ => return (at, source),
1498            };
1499        }
1500    }
1501}
1502
1503/// So that a kernel can take its operands as either a list of vectors or a list of references.
1504///
1505/// A caller that built a `Vec<Vector>` and a caller whose operands are already somewhere else, in a
1506/// chunk or in an evaluator's scratch, want the same kernel. Without this the second kind has to
1507/// clone every operand into a `Vec` to satisfy the signature, and a clone of a vector is a copy of
1508/// the whole column, so the type would be charging real memory traffic for nothing.
1509impl AsRef<Vector> for Vector {
1510    fn as_ref(&self) -> &Vector {
1511        self
1512    }
1513}
1514
1515/// The bits of a packed vector and what they mean, for a kernel that wants to stay in code space.
1516///
1517/// Borrowed from the vector rather than owning anything, so getting one costs nothing and a kernel
1518/// that finds it cannot use them has given up nothing by asking.
1519#[derive(Debug, Clone, Copy)]
1520pub struct Packed<'a> {
1521    words: &'a [u64],
1522    width: u32,
1523    base: i128,
1524    offset: usize,
1525}
1526
1527impl Packed<'_> {
1528    /// How many bits one code takes, between one and [`PACKED_WIDTH_MAX`].
1529    #[must_use]
1530    pub fn width(&self) -> u32 {
1531        self.width
1532    }
1533
1534    /// What zero means, so that the value of a row is the base plus its code.
1535    #[must_use]
1536    pub fn base(&self) -> i128 {
1537        self.base
1538    }
1539
1540    /// The largest value this vector can be holding, whatever it is actually holding.
1541    ///
1542    /// With [`Self::base`] this is the pair a comparison kernel wants first. A literal outside the
1543    /// two answers every row of the vector the same way, which is a whole chunk decided without a
1544    /// bit being read, and that is the case a zone map would have caught if there were one here.
1545    #[must_use]
1546    pub fn ceiling(&self) -> i128 {
1547        self.base + i128::from(u64::MAX >> (u64::BITS - self.width))
1548    }
1549
1550    /// The code of row `row`, which is its value minus [`Self::base`].
1551    ///
1552    /// Out of range rows read as zero rather than panicking, the way every other accessor in this
1553    /// file answers for a row that is not there.
1554    #[must_use]
1555    pub fn code(&self, row: usize) -> u64 {
1556        code_at(self.words, (self.offset + row) * self.width as usize, self.width)
1557    }
1558
1559    /// Which code a value would have, and `None` for a value this vector cannot be holding.
1560    ///
1561    /// The translation a comparison does once per vector so that it does not have to unpack once per
1562    /// row. `None` is the useful answer rather than a failure: it says the literal is outside the
1563    /// packed range, so every row compares against it the same way.
1564    #[must_use]
1565    pub fn code_of(&self, value: i128) -> Option<u64> {
1566        u64::try_from(value.checked_sub(self.base)?).ok().filter(|&code| code <= self.mask())
1567    }
1568
1569    /// The largest code the width allows.
1570    fn mask(&self) -> u64 {
1571        u64::MAX >> (u64::BITS - self.width)
1572    }
1573}
1574
1575/// The widest a packed code is allowed to be.
1576///
1577/// Sixty three rather than sixty four so that a mask is `u64::MAX >> (64 - width)` with no shift of
1578/// a whole word in it, and reading a code is one branch on whether it straddles rather than two. A
1579/// sixty four bit code saves nothing anyway, since it is the layout it came from.
1580pub const PACKED_WIDTH_MAX: u32 = 63;
1581
1582/// How much smaller packing has to be before it is worth the shift and the mask on every read.
1583///
1584/// Two, so a column packs when the bits come to half the flat size or less. A column that would save
1585/// a tenth stays flat, because a tenth of a column is not worth turning every read of it into
1586/// arithmetic, and the whole argument for the form is that a narrow column saves most of itself.
1587pub const PACKING_PAYS_AT: usize = 2;
1588
1589/// How much smaller compressing has to be before it is worth a decompression on every read.
1590///
1591/// Two, the same rule packing follows and for the same reason. FSST gets about that on text, so a
1592/// column of English or of URLs compresses and a column of short codes or of random bytes does not,
1593/// which is the right answer for both.
1594pub const FSST_PAYS_AT: usize = 2;
1595
1596/// The codes of a compressed column and the table they are against.
1597///
1598/// Handed out by [`Vector::coded_parts`] so a kernel can work in code space. Nothing here
1599/// decompresses, which is the point: [`Self::encode`] puts the literal into the same space the rows
1600/// are already in, and after that an equality test is a byte slice comparison.
1601#[derive(Debug, Clone, Copy)]
1602pub struct Coded<'a> {
1603    codes: &'a [u8],
1604    spans: &'a [(u32, u32)],
1605    table: &'a SymbolTable,
1606}
1607
1608impl Coded<'_> {
1609    /// The table every row in this vector is compressed against.
1610    #[must_use]
1611    pub fn table(&self) -> &SymbolTable {
1612        self.table
1613    }
1614
1615    /// The code bytes of one row, still compressed.
1616    #[must_use]
1617    pub fn row(&self, row: usize) -> Option<&[u8]> {
1618        let &(from, to) = self.spans.get(row)?;
1619        self.codes.get(from as usize..to as usize)
1620    }
1621
1622    /// Some bytes in the code space this vector is in.
1623    ///
1624    /// The literal side of an equality filter. Compressing is a function of the table and the bytes,
1625    /// so two strings compress to the same codes exactly when they are the same string, and an
1626    /// equality test on the codes is an equality test on the strings with no decompression in it.
1627    #[must_use]
1628    pub fn encode(&self, bytes: &[u8]) -> Vec<u8> {
1629        let mut out = Vec::with_capacity(bytes.len());
1630        self.table.compress(bytes, &mut out);
1631        out
1632    }
1633}
1634
1635/// How many words hold `len` codes of `width` bits.
1636fn words_for(len: usize, width: u32) -> usize {
1637    (len * width as usize).div_ceil(u64::BITS as usize)
1638}
1639
1640/// The lowest and highest value a type's layout can hold, and `None` for a type with no integer one.
1641///
1642/// This is also the test of whether a type can be packed at all, and it is the only one, so the
1643/// layouts listed here and the layouts [`pack`] and [`unpack`] know how to walk are the same list
1644/// from the same macro and cannot drift apart.
1645fn layout_range(ty: &LogicalType) -> Option<(i128, i128)> {
1646    use rudb_common::PhysicalType as P;
1647    macro_rules! ranges {
1648        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1649            match ty.physical() {
1650                $(P::$variant => Some((i128::from(<$native>::MIN), i128::from(<$native>::MAX))),)+
1651                _ => None,
1652            }
1653        };
1654    }
1655    crate::for_each_layout!(exact, ranges)
1656}
1657
1658/// The lowest and highest value in the first `len` slots of a run of integer data.
1659///
1660/// `None` for data that is not integers, which is what says a column cannot be packed. The null
1661/// slots are in the span, holding whatever zero was written into them, which
1662/// [`Vector::bit_packed`] says more about.
1663fn span_of(data: &Data, len: usize) -> Option<(i128, i128)> {
1664    macro_rules! spans {
1665        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1666            match data {
1667                $(Data::$variant(values) => {
1668                    let mut low = i128::MAX;
1669                    let mut high = i128::MIN;
1670                    for &value in values.as_slice().iter().take(len) {
1671                        let value = i128::from(value);
1672                        low = low.min(value);
1673                        high = high.max(value);
1674                    }
1675                    (low <= high).then_some((low, high))
1676                })+
1677                _ => None,
1678            }
1679        };
1680    }
1681    crate::for_each_layout!(exact, spans)
1682}
1683
1684/// The first `len` values of a run of integer data, written out as codes of `width` bits from `base`.
1685fn pack(data: &Data, len: usize, base: i128, width: u32) -> Vec<u64> {
1686    let mut words = vec![0u64; words_for(len, width)];
1687    macro_rules! packing {
1688        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1689            match data {
1690                $(Data::$variant(values) => {
1691                    for (row, &value) in values.as_slice().iter().take(len).enumerate() {
1692                        // In range because `base` and `width` came from the span of this same run.
1693                        let code = u64::try_from(i128::from(value) - base).unwrap_or(0);
1694                        write_code(&mut words, row * width as usize, width, code);
1695                    }
1696                })+
1697                _ => {}
1698            }
1699        };
1700    }
1701    crate::for_each_layout!(exact, packing);
1702    words
1703}
1704
1705/// The codes at the given rows, unpacked into the flat layout the type calls for.
1706///
1707/// A row of [`NOWHERE`] writes the layout's zero, which is the rule [`copy_of`] follows for the same
1708/// reason: every layout here is a parallel array to a validity mask, so a null takes a slot.
1709///
1710/// # Errors
1711///
1712/// If the type has no flat layout, which a packed vector cannot have and which is checked when one
1713/// is built, so an error here is a bug rather than a caller mistake.
1714fn unpack(
1715    ty: &LogicalType,
1716    words: &[u64],
1717    offset: usize,
1718    width: u32,
1719    base: i128,
1720    at: &[usize],
1721) -> Result<Data> {
1722    let mut out = empty_data_for(ty)?;
1723    let value_of = |row: usize| {
1724        if row == NOWHERE {
1725            return None;
1726        }
1727        Some(base + i128::from(code_at(words, (offset + row) * width as usize, width)))
1728    };
1729    macro_rules! unpacking {
1730        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1731            match &mut out {
1732                $(Data::$variant(values) => {
1733                    values.reserve(at.len());
1734                    for &row in at {
1735                        // In range because both ends of it were checked when the vector was built.
1736                        let value = value_of(row)
1737                            .and_then(|value| <$native>::try_from(value).ok())
1738                            .unwrap_or($zero);
1739                        values.push(value);
1740                    }
1741                })+
1742                _ => {
1743                    return Err(Error::internal(format!(
1744                        "a {ty} vector was packed, which no integer layout allows"
1745                    )));
1746                }
1747            }
1748        };
1749    }
1750    crate::for_each_layout!(exact, unpacking);
1751    Ok(out)
1752}
1753
1754/// The `width` bits starting at `bit`, low end first.
1755///
1756/// Zero for bits past the end of the words, which keeps a read of a row that is not there from
1757/// panicking and matches what every other accessor here does with one.
1758fn code_at(words: &[u64], bit: usize, width: u32) -> u64 {
1759    let word = bit / u64::BITS as usize;
1760    let shift = (bit % u64::BITS as usize) as u32;
1761    let mask = u64::MAX >> (u64::BITS - width);
1762    let low = words.get(word).copied().unwrap_or(0) >> shift;
1763    let taken = u64::BITS - shift;
1764    if taken >= width {
1765        return low & mask;
1766    }
1767    // The code straddles two words, and `taken` is under the width here so it is under sixty four,
1768    // which is what makes the shift below one the hardware will do rather than one it refuses.
1769    let high = words.get(word + 1).copied().unwrap_or(0) << taken;
1770    (low | high) & mask
1771}
1772
1773/// Writes `width` bits of `code` starting at `bit`, over words that started out zero.
1774fn write_code(words: &mut [u64], bit: usize, width: u32, code: u64) {
1775    let word = bit / u64::BITS as usize;
1776    let shift = (bit % u64::BITS as usize) as u32;
1777    words[word] |= code << shift;
1778    let taken = u64::BITS - shift;
1779    if taken < width {
1780        words[word + 1] |= code >> taken;
1781    }
1782}
1783
1784/// One level of dictionary out of however many levels were handed to [`Vector::dictionary`].
1785///
1786/// Every dictionary in the system is built through that constructor and every one of them comes
1787/// through here first, so the invariant this maintains is that the vector a dictionary points at is
1788/// never itself a dictionary that could have been composed away. That makes the work a single `if`
1789/// rather than a loop: the inner vector was already composed when it was built, so composing the
1790/// outer codes through it leaves the result no deeper than the inner vector already was.
1791///
1792/// The codes are indexed rather than fetched with `get`, because the caller has already walked the
1793/// whole outer array to check that every code is in range and the inner array is exactly as long as
1794/// the vector those codes were checked against.
1795fn compose(codes: Vec<u32>, values: Vector) -> (Vec<u32>, Vector) {
1796    // A dictionary carrying a validity of its own is one whose nulls live at this level rather than
1797    // in the values, which is the one thing composition cannot carry down with it.
1798    if !matches!(values.validity, Validity::AllValid) {
1799        return (codes, values);
1800    }
1801    let Vector { ty, len, validity, body } = values;
1802    match body {
1803        Body::Dictionary { codes: inner, values: leaf } => {
1804            debug_assert!(
1805                !matches!(leaf.body, Body::Dictionary { .. })
1806                    || !matches!(leaf.validity, Validity::AllValid),
1807                "a dictionary was stacked on a dictionary without going through the constructor"
1808            );
1809            // The leaf is shared, so taking it out of the `Arc` copies it when something else is
1810            // still holding the same dictionary. That is the rare path: a dictionary over a
1811            // dictionary only arrives from a caller that built one that way, and the cut that made
1812            // sharing worth doing produces neither.
1813            (codes.iter().map(|&code| inner[code as usize]).collect(), Arc::unwrap_or_clone(leaf))
1814        }
1815        body => (codes, Vector { ty, len, validity, body }),
1816    }
1817}
1818
1819/// How many rows a run has to cover on average before run length encoding is smaller.
1820///
1821/// A run costs its value plus the four bytes of its end, so on a four byte column a run of two rows
1822/// breaks even and a run of three wins. Wider columns win sooner and narrower ones later, and this
1823/// is the one ratio for all of them because a threshold per width is a table that has to be right
1824/// nine times rather than once. It is a constant with a name so that the sweep that eventually moves
1825/// it has something to move.
1826const RUNS_PAY_AT: usize = 2;
1827
1828/// Which run holds `row`, given ends that are exclusive and increasing.
1829///
1830/// A binary search rather than a scan, because the callers that ask this are the ones that are not
1831/// walking the runs in order: a single value read out of a result set, or a gather at scattered
1832/// positions. Anything walking in order should be reading [`Vector::run_parts`] instead, which is
1833/// what the form is for.
1834fn run_holding(ends: &[u32], row: usize) -> Option<usize> {
1835    let row = u32::try_from(row).ok()?;
1836    let run = match ends.binary_search(&row) {
1837        // The ends are exclusive, so landing exactly on one means the row is the first of the next.
1838        Ok(at) => at + 1,
1839        Err(at) => at,
1840    };
1841    (run < ends.len()).then_some(run)
1842}
1843
1844/// The row each run ends at, for a flat body read alongside the validity that goes with it.
1845///
1846/// Two adjacent nulls are one run, because a reader of either gets a null and cannot tell them
1847/// apart. A null between two equal values is three runs for the same reason, since the null is a
1848/// value of the column as far as anything reading it is concerned.
1849///
1850/// The comparison is per layout rather than per `Value`, which is the whole reason this is a macro.
1851/// A `Value` a row would allocate a string per row on a `VARCHAR` column and would be the exact
1852/// defect `cargo xtask rowloop` exists to fail the build on.
1853fn boundaries(data: &Data, validity: &Validity, len: usize) -> Vec<u32> {
1854    if len == 0 {
1855        return Vec::new();
1856    }
1857    let breaks = |ends: &mut Vec<u32>, mut differs: Box<dyn FnMut(usize, usize) -> bool + '_>| {
1858        for row in 1..len {
1859            let same = match (validity.is_valid(row), validity.is_valid(row - 1)) {
1860                (false, false) => true,
1861                (true, true) => !differs(row, row - 1),
1862                _ => false,
1863            };
1864            if !same {
1865                ends.push(u32::try_from(row).unwrap_or(u32::MAX));
1866            }
1867        }
1868        ends.push(u32::try_from(len).unwrap_or(u32::MAX));
1869    };
1870    let mut ends = Vec::new();
1871    macro_rules! walked {
1872        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1873            match data {
1874                // No values at all, so every row is the same null and the column is one run.
1875                Data::Empty => ends.push(u32::try_from(len).unwrap_or(u32::MAX)),
1876                $(Data::$variant(values) => {
1877                    breaks(&mut ends, Box::new(|a, b| values.get(a) != values.get(b)));
1878                })+
1879                Data::Varlen(values) => {
1880                    breaks(&mut ends, Box::new(|a, b| values.bytes(a) != values.bytes(b)));
1881                }
1882            }
1883        };
1884    }
1885    crate::for_each_layout!(fixed, walked);
1886    ends
1887}
1888
1889/// The position of a value that is not anywhere, because it is null or out of range.
1890///
1891/// `usize::MAX` rather than an `Option<usize>`, because the copy loop's bounds check rejects it for
1892/// free and an `Option` would put a second branch next to the one already there.
1893const NOWHERE: usize = usize::MAX;
1894
1895/// A run of data copied at the given positions, with a zero wherever the position is [`NOWHERE`].
1896///
1897/// A zero and not a skip, because every layout here is a parallel array to a validity mask and a
1898/// short one would put every value after the first null at the wrong index. It is the same rule
1899/// [`push_value`] follows for a null.
1900fn copy_of(data: &Data, at: &[usize]) -> Data {
1901    macro_rules! copied {
1902        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1903            match data {
1904                Data::Empty => Data::Empty,
1905                $(Data::$variant(values) => {
1906                    let mut out = Buffer::with_capacity(at.len());
1907                    for &index in at {
1908                        // One bounds check rather than a null test and a bounds check, because
1909                        // `NOWHERE` is past the end of every slice there can be.
1910                        out.push(values.get(index).copied().unwrap_or($zero));
1911                    }
1912                    Data::$variant(out)
1913                })+
1914                // The one layout where a gather is a copy of bytes rather than a copy of fixed
1915                // width slots, and the reason compaction is a decision rather than a default on a
1916                // string column.
1917                Data::Varlen(values) => {
1918                    let mut out = StringColumn::with_capacity(at.len());
1919                    // The bytes are known before any of them are copied, because a view carries its
1920                    // length and the wanted positions are already in hand, so the arena is one
1921                    // allocation rather than a run of doublings that each copy what the last one
1922                    // copied.
1923                    let views = values.views();
1924                    out.reserve_bytes(
1925                        at.iter()
1926                            .filter_map(|&index| views.get(index))
1927                            .filter(|view| !view.is_inline())
1928                            .map(StringView::len)
1929                            .sum(),
1930                    );
1931                    for &index in at {
1932                        out.push_from(values, index);
1933                    }
1934                    Data::Varlen(out)
1935                }
1936            }
1937        };
1938    }
1939    crate::for_each_layout!(fixed, copied)
1940}
1941
1942/// The physical layout a run of data is in, for the check that it matches its type.
1943///
1944/// The two enums name their variants the same way on purpose, so this is one generated arm rather
1945/// than sixteen chances to pair the wrong two up.
1946fn layout_of(data: &Data) -> rudb_common::PhysicalType {
1947    use rudb_common::PhysicalType as P;
1948    macro_rules! layouts {
1949        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1950            match data {
1951                Data::Empty => P::Empty,
1952                $(Data::$variant(_) => P::$variant,)+
1953            }
1954        };
1955    }
1956    crate::for_each_layout!(all, layouts)
1957}
1958
1959/// One value out of a run of data, given what the run means.
1960///
1961/// The match is on the logical type rather than on the data, because the data cannot tell a `DATE`
1962/// from an `INTEGER` and that is the whole reason the two are kept apart.
1963fn value_from(ty: &LogicalType, data: &Data, index: usize) -> Value {
1964    let signed = || data.signed_at(index);
1965    let unsigned = || data.unsigned_at(index);
1966    let value = match ty {
1967        LogicalType::Boolean => match data {
1968            Data::Bool(v) => v.get(index).map(|&x| Value::Boolean(x)),
1969            _ => None,
1970        },
1971        LogicalType::TinyInt => signed().and_then(|x| i8::try_from(x).ok()).map(Value::TinyInt),
1972        LogicalType::SmallInt => signed().and_then(|x| i16::try_from(x).ok()).map(Value::SmallInt),
1973        LogicalType::Integer => signed().and_then(|x| i32::try_from(x).ok()).map(Value::Integer),
1974        LogicalType::BigInt => signed().and_then(|x| i64::try_from(x).ok()).map(Value::BigInt),
1975        LogicalType::HugeInt => signed().map(Value::HugeInt),
1976        LogicalType::UTinyInt => unsigned().and_then(|x| u8::try_from(x).ok()).map(Value::UTinyInt),
1977        LogicalType::USmallInt => {
1978            unsigned().and_then(|x| u16::try_from(x).ok()).map(Value::USmallInt)
1979        }
1980        LogicalType::UInteger => {
1981            unsigned().and_then(|x| u32::try_from(x).ok()).map(Value::UInteger)
1982        }
1983        LogicalType::UBigInt => unsigned().and_then(|x| u64::try_from(x).ok()).map(Value::UBigInt),
1984        LogicalType::UHugeInt => unsigned().map(Value::UHugeInt),
1985        LogicalType::Float => match data {
1986            Data::Float32(v) => v.get(index).map(|&x| Value::Float(x)),
1987            _ => None,
1988        },
1989        LogicalType::Double => match data {
1990            Data::Float64(v) => v.get(index).map(|&x| Value::Double(x)),
1991            _ => None,
1992        },
1993        LogicalType::Decimal { width, scale } => {
1994            signed().map(|unscaled| Value::Decimal { unscaled, width: *width, scale: *scale })
1995        }
1996        LogicalType::Varchar | LogicalType::Blob | LogicalType::Bit => {
1997            data.bytes_at(index).map(|bytes| bytes_as(ty, bytes))
1998        }
1999        LogicalType::Date => signed().and_then(|x| i32::try_from(x).ok()).map(Value::Date),
2000        LogicalType::Time | LogicalType::TimeTz => {
2001            signed().and_then(|x| i64::try_from(x).ok()).map(Value::Time)
2002        }
2003        LogicalType::Timestamp
2004        | LogicalType::TimestampS
2005        | LogicalType::TimestampMs
2006        | LogicalType::TimestampNs
2007        | LogicalType::TimestampTz => {
2008            signed().and_then(|x| i64::try_from(x).ok()).map(Value::Timestamp)
2009        }
2010        LogicalType::Interval => match data {
2011            Data::Interval(v) => {
2012                v.get(index).map(|&(months, days, micros)| Value::Interval { months, days, micros })
2013            }
2014            _ => None,
2015        },
2016        _ => None,
2017    };
2018    value.unwrap_or(Value::Null)
2019}
2020
2021/// One row of a string column as a value, given what its bytes are meant to be read as.
2022///
2023/// Both forms that hold strings come through here, so a row that is a `BLOB` in a flat column is a
2024/// `BLOB` in a string view column too. Bytes that are not text in a `VARCHAR` column are a null
2025/// rather than a panic, since everything that got in went in as a string and a column that has
2026/// something else in it is a bug somewhere earlier that a read should not turn into a crash.
2027fn bytes_as(ty: &LogicalType, bytes: &[u8]) -> Value {
2028    match ty {
2029        LogicalType::Varchar => {
2030            std::str::from_utf8(bytes).map_or(Value::Null, |text| Value::Varchar(text.to_owned()))
2031        }
2032        LogicalType::Blob | LogicalType::Bit => Value::Blob(bytes.to_vec()),
2033        _ => Value::Null,
2034    }
2035}
2036
2037/// An empty run of data of the right layout for a type.
2038fn empty_data_for(ty: &LogicalType) -> Result<Data> {
2039    use rudb_common::PhysicalType as P;
2040    macro_rules! empties {
2041        ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2042            match ty.physical() {
2043                P::Empty => Data::Empty,
2044                $(P::$variant => Data::$variant(Buffer::new()),)+
2045                P::Varlen => Data::Varlen(StringColumn::new()),
2046                other => {
2047                    return Err(Error::not_implemented(format!(
2048                        "a flat vector of {other:?} data, which arrives with the storage layer"
2049                    )));
2050                }
2051            }
2052        };
2053    }
2054    Ok(crate::for_each_layout!(fixed, empties))
2055}
2056
2057/// Appends one value to a run of data, or a zero of the right shape when it is null.
2058///
2059/// The zero matters. A null still occupies a position, the validity mask is what says it is null,
2060/// and a run of data with a hole in it would put every value after the hole in the wrong place.
2061fn push_value(data: &mut Data, value: &Value) -> Result<()> {
2062    macro_rules! push {
2063        ($vec:expr, $variant:path, $zero:expr) => {
2064            match value {
2065                Value::Null => $vec.push($zero),
2066                $variant(x) => $vec.push(*x),
2067                other => {
2068                    return Err(Error::internal(format!(
2069                        "{other:?} does not belong in this vector"
2070                    )));
2071                }
2072            }
2073        };
2074    }
2075    // A decimal is stored as its unscaled integer in whatever width its precision needs, which
2076    // `LogicalType::physical` decides and which is why the same `Value::Decimal` is at home in four
2077    // different runs. The narrowing cannot fail for a value the binder produced, because the width
2078    // that chose the run is the width in the value, but it is checked rather than assumed because
2079    // an unchecked cast here would silently store a different number.
2080    macro_rules! decimal {
2081        ($vec:expr, $ty:ty, $unscaled:expr) => {
2082            match <$ty>::try_from(*$unscaled) {
2083                Ok(x) => $vec.push(x),
2084                Err(_) => {
2085                    return Err(Error::internal(format!(
2086                        "an unscaled decimal of {} does not fit the run its precision chose",
2087                        $unscaled
2088                    )));
2089                }
2090            }
2091        };
2092    }
2093    match data {
2094        Data::Empty => {}
2095        Data::Bool(v) => push!(v, Value::Boolean, false),
2096        Data::Int8(v) => push!(v, Value::TinyInt, 0),
2097        Data::Int16(v) => match value {
2098            Value::Null => v.push(0),
2099            Value::SmallInt(x) => v.push(*x),
2100            Value::Decimal { unscaled, .. } => decimal!(v, i16, unscaled),
2101            other => return Err(Error::internal(format!("{other:?} is not a 16 bit value"))),
2102        },
2103        Data::Int32(v) => match value {
2104            Value::Null => v.push(0),
2105            Value::Integer(x) | Value::Date(x) => v.push(*x),
2106            Value::Decimal { unscaled, .. } => decimal!(v, i32, unscaled),
2107            other => return Err(Error::internal(format!("{other:?} is not a 32 bit value"))),
2108        },
2109        Data::Int64(v) => match value {
2110            Value::Null => v.push(0),
2111            Value::BigInt(x) | Value::Time(x) | Value::Timestamp(x) => v.push(*x),
2112            Value::Decimal { unscaled, .. } => decimal!(v, i64, unscaled),
2113            other => return Err(Error::internal(format!("{other:?} is not a 64 bit value"))),
2114        },
2115        Data::Int128(v) => match value {
2116            Value::Null => v.push(0),
2117            Value::HugeInt(x) => v.push(*x),
2118            Value::Decimal { unscaled, .. } => v.push(*unscaled),
2119            other => return Err(Error::internal(format!("{other:?} is not a 128 bit value"))),
2120        },
2121        Data::UInt8(v) => push!(v, Value::UTinyInt, 0),
2122        Data::UInt16(v) => push!(v, Value::USmallInt, 0),
2123        Data::UInt32(v) => push!(v, Value::UInteger, 0),
2124        Data::UInt64(v) => push!(v, Value::UBigInt, 0),
2125        Data::UInt128(v) => push!(v, Value::UHugeInt, 0),
2126        Data::Float32(v) => push!(v, Value::Float, 0.0),
2127        Data::Float64(v) => push!(v, Value::Double, 0.0),
2128        Data::Interval(v) => match value {
2129            Value::Null => v.push((0, 0, 0)),
2130            Value::Interval { months, days, micros } => v.push((*months, *days, *micros)),
2131            other => return Err(Error::internal(format!("{other:?} is not an interval"))),
2132        },
2133        Data::Varlen(column) => match value {
2134            Value::Null => {
2135                column.push("");
2136            }
2137            Value::Varchar(text) => {
2138                column.push(text);
2139            }
2140            // A blob goes in as the bytes it is. The column stores a length and some bytes either
2141            // way, so text is the reading of one rather than a different column, and a blob that
2142            // is not UTF-8 is stored exactly like one that happens to be.
2143            Value::Blob(bytes) => {
2144                column.push_bytes(bytes);
2145            }
2146            other => return Err(Error::internal(format!("{other:?} is not a string"))),
2147        },
2148    }
2149    Ok(())
2150}
2151
2152#[cfg(test)]
2153mod tests {
2154    use std::sync::Arc;
2155
2156    use rudb_common::{LogicalType, Value};
2157
2158    use super::{Body, Data, FSST_PAYS_AT, Form, VECTOR_SIZE, Vector};
2159    use crate::buffer::Buffer;
2160    use crate::fsst::SymbolTable;
2161    use crate::string::{StringColumn, StringView};
2162    use crate::validity::Validity;
2163
2164    fn integers(values: &[i32]) -> Vector {
2165        Vector::flat(LogicalType::Integer, Data::Int32(values.to_vec().into())).unwrap()
2166    }
2167
2168    #[test]
2169    fn a_clustered_column_becomes_runs_and_reads_back_the_same() {
2170        let mut values = Vec::new();
2171        for (value, times) in [(7, 400), (8, 300), (7, 324)] {
2172            values.extend(std::iter::repeat_n(value, times));
2173        }
2174        let flat = integers(&values);
2175        let runs = flat.run_encoded().unwrap();
2176        assert_eq!(runs.form(), Form::Rle);
2177        assert_eq!(runs.run_parts().expect("runs").0, [400, 700, 1024]);
2178        assert_eq!(runs.len(), flat.len());
2179        assert_eq!(runs.iter().collect::<Vec<_>>(), flat.iter().collect::<Vec<_>>());
2180        assert!(
2181            runs.footprint() * 10 < flat.footprint(),
2182            "three runs against a thousand rows: {} against {}",
2183            runs.footprint(),
2184            flat.footprint()
2185        );
2186    }
2187
2188    /// The check is worth having in both directions. A form that is only ever bigger than what it
2189    /// replaced is a form that costs a pass over the column to decide not to use.
2190    #[test]
2191    fn a_column_that_does_not_repeat_is_left_flat() {
2192        let flat = integers(&(0..1024).collect::<Vec<i32>>());
2193        assert_eq!(flat.run_encoded().unwrap().form(), Form::Flat);
2194        // Two runs over four rows is exactly break even on a four byte column, and break even is
2195        // not a reason to change form.
2196        assert_eq!(integers(&[1, 1, 2, 2]).run_encoded().unwrap().form(), Form::Flat);
2197        assert_eq!(integers(&[1, 1, 1, 2, 2]).run_encoded().unwrap().form(), Form::Rle);
2198    }
2199
2200    #[test]
2201    fn two_nulls_beside_each_other_are_one_run_and_a_null_between_two_equals_is_a_break() {
2202        let mut values = vec![Value::Integer(4), Value::Integer(4)];
2203        values.extend([Value::Null, Value::Null, Value::Null]);
2204        values.extend(std::iter::repeat_n(Value::Integer(4), 5));
2205        let flat = Vector::from_values(LogicalType::Integer, &values).unwrap();
2206        let runs = flat.run_encoded().unwrap();
2207        assert_eq!(runs.run_parts().expect("runs").0, [2, 5, 10]);
2208        assert_eq!(runs.iter().collect::<Vec<_>>(), values);
2209    }
2210
2211    #[test]
2212    fn slicing_runs_keeps_them_runs_and_cuts_the_first_and_last_one_back() {
2213        let flat = integers(&[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]);
2214        let runs = flat.run_encoded().unwrap();
2215        let piece = runs.slice(3, 6).unwrap();
2216        assert_eq!(piece.form(), Form::Rle, "the form is the whole point");
2217        assert_eq!(piece.run_parts().expect("runs").0, [1, 5, 6]);
2218        assert_eq!(
2219            piece.iter().collect::<Vec<_>>(),
2220            flat.slice(3, 6).unwrap().iter().collect::<Vec<_>>()
2221        );
2222        assert_eq!(runs.slice(0, 0).unwrap().len(), 0);
2223        assert_eq!(runs.slice(0, 12).unwrap().form(), Form::Rle);
2224    }
2225
2226    #[test]
2227    fn gathering_out_of_runs_walks_to_the_values_the_way_it_walks_a_dictionary() {
2228        let mut values = vec![Value::Varchar("red".into()); 4];
2229        values.extend([Value::Null, Value::Null, Value::Null]);
2230        values.extend(vec![Value::Varchar("blue".into()); 4]);
2231        let runs =
2232            Vector::from_values(LogicalType::Varchar, &values).unwrap().run_encoded().unwrap();
2233        assert_eq!(runs.form(), Form::Rle);
2234        let picked = runs.gather(&[8, 0, 5, 2]).unwrap();
2235        assert_eq!(picked.form(), Form::Flat, "a gather copies, whatever it gathered from");
2236        assert_eq!(
2237            picked.iter().collect::<Vec<_>>(),
2238            [values[8].clone(), values[0].clone(), Value::Null, values[2].clone()]
2239        );
2240        assert_eq!(runs.text_at(1), Some("red"));
2241        assert_eq!(runs.text_at(5), None, "a null has no text");
2242        assert_eq!(runs.flatten().unwrap().iter().collect::<Vec<_>>(), values);
2243    }
2244
2245    /// A run length vector over a run length vector turns one search per row into two, and there is
2246    /// nothing in the engine that builds one, so it is refused rather than composed.
2247    #[test]
2248    fn runs_of_runs_are_refused_and_runs_of_a_dictionary_are_not() {
2249        let inner = integers(&[1, 1, 1, 1, 2]).run_encoded().unwrap();
2250        assert_eq!(inner.form(), Form::Rle);
2251        let error = Vector::runs(vec![2, 8], inner).unwrap_err();
2252        assert!(error.to_string().contains("runs of runs"), "{error}");
2253
2254        let words = Vector::from_values(
2255            LogicalType::Varchar,
2256            &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
2257        )
2258        .unwrap();
2259        let dictionary = Vector::dictionary(vec![1, 0], words).unwrap();
2260        let stacked = Vector::runs(vec![4, 9], dictionary).unwrap();
2261        assert_eq!(stacked.len(), 9);
2262        assert_eq!(stacked.value_at(3), Value::Varchar("blue".into()));
2263        assert_eq!(stacked.value_at(4), Value::Varchar("red".into()));
2264    }
2265
2266    #[test]
2267    fn run_ends_have_to_increase_and_there_is_one_value_for_each_of_them() {
2268        let values = integers(&[1, 2]);
2269        assert!(Vector::runs(vec![4], values.clone()).is_err(), "two values and one run");
2270        assert!(Vector::runs(vec![4, 4], values.clone()).is_err(), "an end that repeats");
2271        assert!(Vector::runs(vec![4, 2], values.clone()).is_err(), "an end that goes backwards");
2272        assert!(Vector::runs(vec![0, 2], values.clone()).is_err(), "a first run holding no rows");
2273        assert_eq!(Vector::runs(vec![4, 9], values).unwrap().len(), 9);
2274    }
2275
2276    #[test]
2277    fn a_form_that_is_already_compact_is_left_where_it_is() {
2278        let constant = Vector::constant(LogicalType::Integer, Value::Integer(1), 1000);
2279        assert_eq!(constant.run_encoded().unwrap().form(), Form::Constant);
2280        assert_eq!(Vector::sequence(0, 1, 1000).run_encoded().unwrap().form(), Form::Sequence);
2281    }
2282
2283    /// What makes one accessor cover both forms. A dictionary hands back the codes it stores and a
2284    /// run length vector works the same numbers out, and a kernel writing `values[at[row]]` reads
2285    /// the same rows out of either.
2286    #[test]
2287    fn both_forms_that_point_somewhere_hand_back_a_position_per_row() {
2288        let words = Vector::from_values(
2289            LogicalType::Varchar,
2290            &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
2291        )
2292        .unwrap();
2293        let runs = Vector::runs(vec![3, 5], words.clone()).unwrap();
2294        let (at, values) = runs.positions().expect("runs point somewhere");
2295        assert_eq!(at.as_ref(), [0, 0, 0, 1, 1]);
2296        assert_eq!(values.value_at(at[3] as usize), runs.value_at(3));
2297
2298        let dictionary = Vector::dictionary(vec![1, 0, 1], words).unwrap();
2299        let (at, values) = dictionary.positions().expect("a dictionary points somewhere");
2300        assert_eq!(at.as_ref(), [1, 0, 1]);
2301        assert_eq!(values.value_at(at[0] as usize), dictionary.value_at(0));
2302
2303        assert!(integers(&[1, 2, 3]).positions().is_none(), "a flat vector points at itself");
2304        assert!(Vector::sequence(0, 1, 4).positions().is_none(), "a sequence stores nothing");
2305    }
2306
2307    #[test]
2308    fn slicing_a_dictionary_keeps_it_a_dictionary_where_gathering_would_not() {
2309        let values = Vector::from_values(
2310            LogicalType::Varchar,
2311            &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
2312        )
2313        .unwrap();
2314        let vector = Vector::dictionary(vec![0, 1, 1, 0, 1], values).unwrap();
2315
2316        let piece = vector.slice(1, 3).unwrap();
2317        assert_eq!(piece.form(), Form::Dictionary, "the form is the whole point");
2318        assert_eq!(piece.len(), 3);
2319        assert_eq!(
2320            piece.iter().collect::<Vec<_>>(),
2321            [
2322                Value::Varchar("blue".into()),
2323                Value::Varchar("blue".into()),
2324                Value::Varchar("red".into())
2325            ]
2326        );
2327        assert_eq!(vector.gather(&[1, 2, 3]).unwrap().form(), Form::Flat, "which a gather loses");
2328    }
2329
2330    #[test]
2331    fn slicing_a_dictionary_shares_the_dictionary_rather_than_copying_it() {
2332        // The assertion is about the address and not about the values, because the values were
2333        // right when the dictionary was copied too. A page holds one dictionary and is cut into a
2334        // chunk of codes at a time, so copying the dictionary here is a copy of every string in it
2335        // per chunk, and on a read of a ClickBench partition it was ten percent of the cycles.
2336        let values = Vector::from_values(
2337            LogicalType::Varchar,
2338            &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
2339        )
2340        .unwrap();
2341        let vector = Vector::dictionary(vec![0, 1, 1, 0, 1], values).unwrap();
2342        let Body::Dictionary { values: whole, .. } = &vector.body else {
2343            panic!("a dictionary vector holds a dictionary");
2344        };
2345
2346        let piece = vector.slice(1, 3).unwrap();
2347        let Body::Dictionary { codes, values: cut } = &piece.body else {
2348            panic!("a slice of a dictionary is a dictionary");
2349        };
2350        assert!(Arc::ptr_eq(whole, cut), "the cut copied the dictionary");
2351        assert_eq!(codes, &[1, 1, 0], "the codes are the part that is cut");
2352
2353        // And a cut of a cut shares it too, since that is what a scan does to a page it reads twice.
2354        let again = piece.slice(1, 2).unwrap();
2355        let Body::Dictionary { values: cut, .. } = &again.body else {
2356            panic!("a slice of a slice of a dictionary is a dictionary");
2357        };
2358        assert!(Arc::ptr_eq(whole, cut), "the second cut copied the dictionary");
2359        assert_eq!(
2360            again.iter().collect::<Vec<_>>(),
2361            [Value::Varchar("blue".into()), Value::Varchar("red".into())]
2362        );
2363    }
2364
2365    #[test]
2366    fn a_slice_carries_the_nulls_that_were_in_its_range_and_not_the_others() {
2367        let vector =
2368            integers(&[1, 2, 3, 4]).with_validity(Validity::from_run(&[false, true, false, true]));
2369        let piece = vector.slice(1, 2).unwrap();
2370        assert!(piece.validity().is_valid(0));
2371        assert!(!piece.validity().is_valid(1));
2372        assert_eq!(piece.value_at(1), Value::Null);
2373    }
2374
2375    #[test]
2376    fn slicing_a_sequence_moves_its_start_rather_than_writing_the_values_out() {
2377        let vector = Vector::sequence(100, 5, 10);
2378        let piece = vector.slice(3, 4).unwrap();
2379        assert_eq!(piece.form(), Form::Sequence);
2380        assert_eq!(
2381            piece.iter().collect::<Vec<_>>(),
2382            [Value::BigInt(115), Value::BigInt(120), Value::BigInt(125), Value::BigInt(130)]
2383        );
2384    }
2385
2386    #[test]
2387    fn slicing_a_constant_is_a_shorter_constant() {
2388        let vector = Vector::constant(LogicalType::Integer, Value::Integer(9), 8);
2389        let piece = vector.slice(2, 3).unwrap();
2390        assert_eq!(piece.form(), Form::Constant);
2391        assert_eq!(piece.len(), 3);
2392        assert_eq!(piece.value_at(2), Value::Integer(9));
2393    }
2394
2395    #[test]
2396    fn slicing_the_whole_vector_hands_it_back_as_it_was() {
2397        let vector = integers(&[1, 2, 3]);
2398        assert_eq!(
2399            vector.slice(0, 3).unwrap().iter().collect::<Vec<_>>(),
2400            [Value::Integer(1), Value::Integer(2), Value::Integer(3)]
2401        );
2402    }
2403
2404    #[test]
2405    fn a_slice_past_the_end_is_an_error_rather_than_a_short_vector() {
2406        let error = integers(&[1, 2, 3]).slice(2, 2).unwrap_err();
2407        assert!(error.to_string().contains("of a vector of 3"), "{error}");
2408    }
2409
2410    #[test]
2411    fn the_vector_size_is_the_one_the_design_is_built_around() {
2412        // 1024 and not DuckDB's 2048. A validity mask is 16 u64 words and a vector of string views
2413        // is 16 KiB, both of which are consequences of this number rather than coincidences.
2414        assert_eq!(VECTOR_SIZE, 1024);
2415        assert_eq!(VECTOR_SIZE / 64, 16);
2416    }
2417
2418    #[test]
2419    fn a_flat_vector_reads_back_what_was_put_in_it() {
2420        let vector = integers(&[1, 2, 3]);
2421        assert_eq!(vector.form(), Form::Flat);
2422        assert_eq!(vector.len(), 3);
2423        assert_eq!(vector.value_at(1), Value::Integer(2));
2424        assert_eq!(
2425            vector.iter().collect::<Vec<_>>(),
2426            vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)]
2427        );
2428    }
2429
2430    #[test]
2431    fn a_vector_built_from_values_reads_the_same_values_back() {
2432        let vector = Vector::from_values(
2433            LogicalType::Varchar,
2434            &[
2435                Value::Varchar("a".to_string()),
2436                Value::Null,
2437                Value::Varchar("a string too long to sit inside a view".to_string()),
2438            ],
2439        )
2440        .expect("strings and a null");
2441        assert_eq!(vector.len(), 3);
2442        assert_eq!(vector.value_at(0), Value::Varchar("a".to_string()));
2443        assert_eq!(vector.value_at(1), Value::Null);
2444        assert_eq!(
2445            vector.value_at(2),
2446            Value::Varchar("a string too long to sit inside a view".to_string())
2447        );
2448    }
2449
2450    /// A null still occupies a position. If it did not then every value after it would read back
2451    /// one place to the left, which is the kind of bug that looks like a storage bug for a week.
2452    #[test]
2453    fn a_null_in_the_middle_does_not_move_the_values_after_it() {
2454        let vector = Vector::from_values(
2455            LogicalType::Integer,
2456            &[Value::Integer(1), Value::Null, Value::Integer(3)],
2457        )
2458        .expect("integers and a null");
2459        assert_eq!(vector.value_at(2), Value::Integer(3));
2460        assert!(vector.validity().has_nulls(3), "the middle one is null");
2461    }
2462
2463    #[test]
2464    fn a_value_the_type_cannot_hold_is_refused() {
2465        let wrong = Vector::from_values(LogicalType::Integer, &[Value::Varchar("x".to_string())]);
2466        assert!(wrong.is_err(), "a string is not an integer");
2467    }
2468
2469    #[test]
2470    fn a_type_that_does_not_match_its_layout_is_refused_at_construction() {
2471        // One comparison here against a wrong answer read out three layers later.
2472        let wrong = Vector::flat(LogicalType::Varchar, Data::Int32(vec![1].into()));
2473        assert!(wrong.is_err());
2474        let right = Vector::flat(LogicalType::Date, Data::Int32(vec![1].into()));
2475        assert!(right.is_ok(), "a date is stored in an i32 and that has to be allowed");
2476    }
2477
2478    #[test]
2479    fn a_constant_vector_costs_one_value_whatever_its_length() {
2480        let vector = Vector::constant(LogicalType::Integer, Value::Integer(7), VECTOR_SIZE);
2481        assert_eq!(vector.form(), Form::Constant);
2482        assert_eq!(vector.len(), VECTOR_SIZE);
2483        assert_eq!(vector.value_at(0), Value::Integer(7));
2484        assert_eq!(vector.value_at(VECTOR_SIZE - 1), Value::Integer(7));
2485        assert_eq!(vector.value_at(VECTOR_SIZE), Value::Null, "past the end is null, not a panic");
2486    }
2487
2488    #[test]
2489    fn a_constant_null_is_all_invalid_without_being_told() {
2490        let vector = Vector::constant(LogicalType::Integer, Value::Null, 8);
2491        assert_eq!(vector.validity(), &Validity::AllInvalid);
2492        assert_eq!(vector.value_at(3), Value::Null);
2493    }
2494
2495    #[test]
2496    fn a_sequence_vector_is_sixteen_bytes_of_row_identifiers() {
2497        let vector = Vector::sequence(100, 1, VECTOR_SIZE);
2498        assert_eq!(vector.form(), Form::Sequence);
2499        assert_eq!(vector.value_at(0), Value::BigInt(100));
2500        assert_eq!(vector.value_at(923), Value::BigInt(1023));
2501        let stepped = Vector::sequence(0, 5, 4);
2502        assert_eq!(
2503            stepped.iter().collect::<Vec<_>>(),
2504            vec![Value::BigInt(0), Value::BigInt(5), Value::BigInt(10), Value::BigInt(15)]
2505        );
2506    }
2507
2508    #[test]
2509    fn a_dictionary_vector_reads_through_its_codes() {
2510        let mut column = StringColumn::new();
2511        column.push("red");
2512        column.push("green");
2513        let values = Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap();
2514        let vector = Vector::dictionary(vec![0, 1, 1, 0], values).unwrap();
2515        assert_eq!(vector.form(), Form::Dictionary);
2516        assert_eq!(vector.logical_type(), &LogicalType::Varchar);
2517        assert_eq!(vector.value_at(2), Value::Varchar("green".into()));
2518        assert_eq!(vector.len(), 4);
2519    }
2520
2521    /// The accessor a group by keys a string column through, which has to agree with `value_at` on
2522    /// every position or two rows holding one string end up in two groups.
2523    #[test]
2524    fn text_is_read_where_it_already_is_for_the_forms_that_store_it() {
2525        let mut column = StringColumn::new();
2526        column.push("red");
2527        column.push("green");
2528        column.push("");
2529        let flat = Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap();
2530        for index in 0..flat.len() {
2531            assert_eq!(flat.text_at(index).map(str::to_string), text_of(&flat.value_at(index)));
2532        }
2533        let dictionary = Vector::dictionary(vec![1, 0, 1, 2], flat).unwrap();
2534        for index in 0..dictionary.len() {
2535            assert_eq!(
2536                dictionary.text_at(index).map(str::to_string),
2537                text_of(&dictionary.value_at(index))
2538            );
2539        }
2540        assert_eq!(dictionary.text_at(4), None, "past the end");
2541    }
2542
2543    /// The forms and types that have no text to hand back, which a caller answers by falling back
2544    /// to `value_at`. A blob is the one that would be a correctness bug rather than a slow path,
2545    /// since its bytes are not required to be text and it is not a `VARCHAR` either way.
2546    #[test]
2547    fn text_is_refused_where_it_is_not_stored_as_itself() {
2548        let nulls =
2549            Vector::from_values(LogicalType::Varchar, &[Value::Varchar("red".into()), Value::Null])
2550                .unwrap();
2551        assert_eq!(nulls.text_at(0), Some("red"));
2552        assert_eq!(nulls.text_at(1), None, "a null has no text");
2553        let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("red".into()), 3);
2554        assert_eq!(constant.text_at(0), None, "a constant is not stored per position");
2555        assert_eq!(integers(&[1, 2]).text_at(0), None, "an integer is not text");
2556        let mut bytes = StringColumn::new();
2557        bytes.push("red");
2558        let blob = Vector::flat(LogicalType::Blob, Data::Varlen(bytes)).unwrap();
2559        assert_eq!(blob.text_at(0), None, "a blob is not a varchar");
2560    }
2561
2562    /// The accessor a group by keys an integer column through, which has to agree with `value_at`
2563    /// on every position or two rows holding one number end up in two groups.
2564    #[test]
2565    fn a_signed_integer_is_read_where_it_already_is_for_the_forms_that_store_it() {
2566        let flat = integers(&[7, -3, 0, 2]);
2567        for index in 0..flat.len() {
2568            assert_eq!(flat.signed_at(index), signed_of(&flat.value_at(index)), "flat {index}");
2569        }
2570        let dictionary = Vector::dictionary(vec![1, 0, 3, 2], flat).unwrap();
2571        for index in 0..dictionary.len() {
2572            assert_eq!(
2573                dictionary.signed_at(index),
2574                signed_of(&dictionary.value_at(index)),
2575                "dictionary {index}"
2576            );
2577        }
2578        assert_eq!(dictionary.signed_at(4), None, "past the end");
2579
2580        let runs = Vector::runs(vec![2, 5], integers(&[4, 9])).unwrap();
2581        for index in 0..runs.len() {
2582            assert_eq!(runs.signed_at(index), signed_of(&runs.value_at(index)), "run {index}");
2583        }
2584        let constant = Vector::constant(LogicalType::BigInt, Value::BigInt(11), 3);
2585        assert_eq!(constant.signed_at(2), Some(11));
2586        let sequence = Vector::sequence(100, 5, 4);
2587        for index in 0..sequence.len() {
2588            assert_eq!(
2589                sequence.signed_at(index),
2590                signed_of(&sequence.value_at(index)),
2591                "sequence {index}"
2592            );
2593        }
2594    }
2595
2596    /// The forms and types that have no integer to hand back, which a caller answers by falling
2597    /// back to `value_at`. Reading one of these as a key that does not match rather than as a key
2598    /// that has to be built is how a packed column ends up with every row in its own group.
2599    #[test]
2600    fn a_signed_integer_is_refused_where_it_is_not_stored_as_itself() {
2601        let nulls =
2602            Vector::from_values(LogicalType::BigInt, &[Value::BigInt(4), Value::Null]).unwrap();
2603        assert_eq!(nulls.signed_at(0), Some(4));
2604        assert_eq!(nulls.signed_at(1), None, "a null is not a number");
2605        let packed = integers(&[1, 2, 3, 1]).bit_packed().unwrap();
2606        assert_eq!(
2607            packed.signed_at(0),
2608            None,
2609            "a packed row is not an integer until it is unpacked"
2610        );
2611        let mut bytes = StringColumn::new();
2612        bytes.push("red");
2613        let text = Vector::flat(LogicalType::Varchar, Data::Varlen(bytes)).unwrap();
2614        assert_eq!(text.signed_at(0), None, "a string is not a number");
2615        let double = Vector::flat(LogicalType::Double, Data::Float64(vec![1.5].into())).unwrap();
2616        assert_eq!(double.signed_at(0), None, "a double is not a signed integer");
2617    }
2618
2619    /// The integer of a value, for comparing `signed_at` against `value_at` position by position.
2620    fn signed_of(value: &Value) -> Option<i128> {
2621        match value {
2622            Value::TinyInt(x) => Some(i128::from(*x)),
2623            Value::SmallInt(x) => Some(i128::from(*x)),
2624            Value::Integer(x) | Value::Date(x) => Some(i128::from(*x)),
2625            Value::BigInt(x) | Value::Time(x) | Value::Timestamp(x) => Some(i128::from(*x)),
2626            Value::HugeInt(x) | Value::Decimal { unscaled: x, .. } => Some(*x),
2627            _ => None,
2628        }
2629    }
2630
2631    /// The text of a value, for comparing `text_at` against `value_at` position by position.
2632    fn text_of(value: &Value) -> Option<String> {
2633        match value {
2634            Value::Varchar(text) => Some(text.clone()),
2635            _ => None,
2636        }
2637    }
2638
2639    #[test]
2640    fn a_dictionary_code_past_the_end_is_refused() {
2641        // The alternative is a silent read of the wrong value, which is the failure mode the
2642        // entire M3 design has to be careful about.
2643        let values = integers(&[1, 2]);
2644        assert!(Vector::dictionary(vec![0, 2], values).is_err());
2645        // The check runs on the highest code rather than the first bad one, so it has to say that
2646        // no codes at all is fine even when there are no values for them to point at either.
2647        let empty = Vector::dictionary(Vec::new(), integers(&[])).expect("no codes, no values");
2648        assert_eq!(empty.len(), 0);
2649        // And a code of zero against an empty dictionary is still past the end.
2650        assert!(Vector::dictionary(vec![0], integers(&[])).is_err());
2651    }
2652
2653    #[test]
2654    fn every_form_flattens_to_the_same_values_it_reads_out() {
2655        // This is the shape of the equivalence testing in spec/16-testing.md section 16.2, in
2656        // miniature and long before there is an encoded kernel to point it at. A form that reads
2657        // out one way and flattens another is the exact bug that testing exists to catch.
2658        let mut column = StringColumn::new();
2659        column.push("alpha");
2660        column.push("beta");
2661        let dictionary = Vector::dictionary(
2662            vec![1, 0, 1],
2663            Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap(),
2664        )
2665        .unwrap();
2666        let cases = [
2667            Vector::constant(LogicalType::Integer, Value::Integer(3), 5),
2668            Vector::sequence(7, -2, 5),
2669            dictionary,
2670        ];
2671        for vector in cases {
2672            let flat = vector.flatten().unwrap();
2673            assert_eq!(flat.form(), Form::Flat);
2674            assert_eq!(flat.len(), vector.len());
2675            for index in 0..vector.len() {
2676                assert_eq!(flat.value_at(index), vector.value_at(index), "at {index}");
2677            }
2678        }
2679    }
2680
2681    #[test]
2682    fn a_null_still_occupies_a_position_after_flattening() {
2683        // The reason push_value writes a zero for a null rather than skipping it. A run of data
2684        // with a hole in it puts every value after the hole in the wrong place, and the validity
2685        // mask is what says the position is null.
2686        let vector = Vector::sequence(0, 1, 4).with_validity(Validity::from_iter(4, |i| i != 1));
2687        let flat = vector.flatten().unwrap();
2688        assert_eq!(flat.value_at(0), Value::BigInt(0));
2689        assert_eq!(flat.value_at(1), Value::Null);
2690        assert_eq!(flat.value_at(2), Value::BigInt(2));
2691        assert_eq!(flat.value_at(3), Value::BigInt(3));
2692    }
2693
2694    /// A dictionary holds its nulls in the vector it points at, so its own validity is all valid
2695    /// and reading that instead of the values turns a null into whatever zero means for the type.
2696    /// A filter over a nullable column produces exactly this vector, so the bug reaches a result
2697    /// set as `LEFT JOIN` padding that comes back as zeros.
2698    #[test]
2699    fn a_null_behind_a_dictionary_survives_flattening() {
2700        let values =
2701            Vector::from_values(LogicalType::Integer, &[Value::Integer(3), Value::Null]).unwrap();
2702        let dictionary = Vector::dictionary(vec![1, 0, 1], values).unwrap();
2703        let flat = dictionary.flatten().unwrap();
2704        assert_eq!(flat.value_at(0), Value::Null);
2705        assert_eq!(flat.value_at(1), Value::Integer(3));
2706        assert_eq!(flat.value_at(2), Value::Null);
2707    }
2708
2709    /// The property that makes `gather` usable at all: it has to be the same function as reading the
2710    /// wanted positions one at a time, over every form, or compaction changes answers.
2711    #[test]
2712    fn gathering_reads_what_reading_one_position_at_a_time_reads() {
2713        let mut column = StringColumn::new();
2714        column.push("alpha");
2715        column.push("beta");
2716        column.push("gamma");
2717        let cases = [
2718            integers(&[10, 20, 30, 40]),
2719            integers(&[10, 20, 30, 40]).with_validity(Validity::from_iter(4, |i| i != 2)),
2720            Vector::constant(LogicalType::Integer, Value::Integer(9), 4),
2721            Vector::sequence(100, -7, 4),
2722            Vector::sequence(100, -7, 4).with_validity(Validity::from_iter(4, |i| i % 2 == 0)),
2723            Vector::dictionary(
2724                vec![2, 0, 1, 2],
2725                Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap(),
2726            )
2727            .unwrap(),
2728            Vector::dictionary(
2729                vec![1, 0, 1, 0],
2730                Vector::from_values(LogicalType::Integer, &[Value::Integer(5), Value::Null])
2731                    .unwrap(),
2732            )
2733            .unwrap(),
2734        ];
2735        let wanted = [3_u32, 0, 2, 2, 1];
2736        for vector in cases {
2737            let gathered = vector.gather(&wanted).unwrap();
2738            assert_eq!(gathered.len(), wanted.len());
2739            assert_eq!(gathered.logical_type(), vector.logical_type());
2740            for (slot, &index) in wanted.iter().enumerate() {
2741                assert_eq!(
2742                    gathered.value_at(slot),
2743                    vector.value_at(index as usize),
2744                    "slot {slot} of {:?}",
2745                    vector.form()
2746                );
2747            }
2748        }
2749    }
2750
2751    /// A gather past the end is not an error, because the selection that produced the indices is
2752    /// checked by its caller and the one thing that must not happen here is a read of the wrong
2753    /// value. An index nothing answers is null, which is what an outer join pad needs anyway.
2754    #[test]
2755    fn gathering_a_position_that_is_not_there_is_a_null_and_not_a_wrong_value() {
2756        let vector = integers(&[1, 2, 3]);
2757        let gathered = vector.gather(&[2, 9]).unwrap();
2758        assert_eq!(gathered.value_at(0), Value::Integer(3));
2759        assert_eq!(gathered.value_at(1), Value::Null);
2760    }
2761
2762    /// The vector with nothing in it at all, which is what an untyped `NULL` is stored as. Every
2763    /// position asked for is past its end, so the answer is nulls and the length has to be the
2764    /// length that was asked for rather than the length that was there.
2765    #[test]
2766    fn gathering_from_a_vector_of_no_values_is_that_many_nulls() {
2767        let vector = Vector::flat(LogicalType::Null, Data::Empty).unwrap();
2768        let gathered = vector.gather(&[0, 1, 2]).unwrap();
2769        assert_eq!(gathered.len(), 3);
2770        assert_eq!(gathered.value_at(0), Value::Null);
2771        assert_eq!(gathered.value_at(2), Value::Null);
2772    }
2773
2774    /// Every position holds the same value, so a gather with no hole in it has nothing to copy and
2775    /// the result is the constant again rather than a run of a thousand copies of it.
2776    #[test]
2777    fn gathering_a_constant_stays_a_constant() {
2778        let vector = Vector::constant(LogicalType::Integer, Value::Integer(4), 100);
2779        let gathered = vector.gather(&[7, 7, 99]).unwrap();
2780        assert_eq!(gathered.form(), Form::Constant);
2781        assert_eq!(gathered.len(), 3);
2782        assert_eq!(gathered.value_at(2), Value::Integer(4));
2783    }
2784
2785    /// A dictionary over a dictionary is what a second filter over an already filtered chunk builds,
2786    /// and the gather has to walk to the bottom of that chain rather than one step down it. The
2787    /// constructor composes the ordinary chain away, so the one built here is the kind it cannot,
2788    /// which is a level holding nulls of its own.
2789    #[test]
2790    fn gathering_walks_a_dictionary_over_a_dictionary_to_the_values() {
2791        let inner = Vector::dictionary(vec![2, 1, 0], integers(&[7, 8, 9]))
2792            .unwrap()
2793            .with_validity(Validity::from_iter(3, |index| index != 2));
2794        let outer = Vector::dictionary(vec![1, 2], inner).unwrap();
2795        let gathered = outer.gather(&[0, 1]).unwrap();
2796        assert_eq!(gathered.form(), Form::Flat);
2797        assert_eq!(gathered.value_at(0), Value::Integer(8));
2798        assert_eq!(gathered.value_at(1), Value::Null);
2799    }
2800
2801    /// Two filters over one chunk build a dictionary over a dictionary, four conjuncts pushed down
2802    /// separately build four levels of it, and every level is a dependent load on every later read
2803    /// of every row plus a code array that cannot be freed. Composing at construction is one pass
2804    /// over the codes the range check was walking anyway.
2805    #[test]
2806    fn a_dictionary_over_a_dictionary_is_composed_into_one_level() {
2807        let inner = Vector::dictionary(vec![2, 1, 0], integers(&[7, 8, 9])).unwrap();
2808        let outer = Vector::dictionary(vec![1, 2], inner).unwrap();
2809        let (codes, values) = outer.dictionary_parts().unwrap();
2810        assert_eq!(codes, [1, 0]);
2811        assert_eq!(values.form(), Form::Flat);
2812        assert_eq!(outer.value_at(0), Value::Integer(8));
2813        assert_eq!(outer.value_at(1), Value::Integer(7));
2814    }
2815
2816    /// The invariant stated as the thing it is there for, which is that the depth does not grow with
2817    /// the number of filters. Four levels stacked one at a time are one level at the end of it.
2818    #[test]
2819    fn stacking_dictionaries_does_not_make_them_deeper() {
2820        let mut vector = integers(&[10, 20, 30, 40]);
2821        for _ in 0..4 {
2822            vector = Vector::dictionary(vec![3, 2, 1, 0], vector).unwrap();
2823        }
2824        let (codes, values) = vector.dictionary_parts().unwrap();
2825        assert_eq!(values.form(), Form::Flat);
2826        assert_eq!(codes, [0, 1, 2, 3]);
2827        assert_eq!(
2828            vector.iter().collect::<Vec<_>>(),
2829            integers(&[10, 20, 30, 40]).iter().collect::<Vec<_>>()
2830        );
2831    }
2832
2833    /// Composing has to carry the nulls down with it. The values hold them, the codes point at them,
2834    /// and a composed code that lands on a null position is still a null.
2835    #[test]
2836    fn composing_a_dictionary_keeps_the_nulls_its_values_hold() {
2837        let values =
2838            Vector::from_values(LogicalType::Integer, &[Value::Integer(3), Value::Null]).unwrap();
2839        let inner = Vector::dictionary(vec![1, 0, 1], values).unwrap();
2840        let outer = Vector::dictionary(vec![0, 1], inner).unwrap();
2841        assert_eq!(outer.dictionary_parts().unwrap().1.form(), Form::Flat);
2842        assert_eq!(outer.value_at(0), Value::Null);
2843        assert_eq!(outer.value_at(1), Value::Integer(3));
2844    }
2845
2846    /// The one level composition cannot go past. A dictionary that was given a validity of its own is
2847    /// saying its nulls are at that level rather than in the values, and pointing the outer codes
2848    /// straight at the values would read through the holes instead of stopping at them.
2849    #[test]
2850    fn a_dictionary_holding_its_own_nulls_is_not_composed_past() {
2851        let inner = Vector::dictionary(vec![0, 1, 2], integers(&[1, 2, 3]))
2852            .unwrap()
2853            .with_validity(Validity::from_iter(3, |index| index != 1));
2854        let outer = Vector::dictionary(vec![1, 2, 0], inner).unwrap();
2855        assert_eq!(outer.dictionary_parts().unwrap().1.form(), Form::Dictionary);
2856        assert_eq!(outer.value_at(0), Value::Null);
2857        assert_eq!(outer.value_at(1), Value::Integer(3));
2858        assert_eq!(outer.value_at(2), Value::Integer(1));
2859    }
2860
2861    /// The difference between the two questions about nulls, which a group by got wrong. A filtered
2862    /// chunk is dictionary vectors, those are built with every row marked present at their own
2863    /// level, and the nulls are down in the values. So the mask says the row has a value and the
2864    /// row does not.
2865    #[test]
2866    fn a_null_behind_a_dictionary_reads_as_null_even_though_the_mask_says_otherwise() {
2867        let values = Vector::flat(LogicalType::Integer, Data::Int32(vec![0, 7].into()))
2868            .unwrap()
2869            .with_validity(Validity::from_iter(2, |index| index != 0));
2870        let vector = Vector::dictionary(vec![0, 1, 0], values).unwrap();
2871        assert!(vector.validity().is_valid(0), "the mask at this level says present");
2872        assert!(vector.is_null_at(0));
2873        assert!(!vector.is_null_at(1));
2874        assert!(vector.is_null_at(2));
2875        assert!(vector.is_null_at(3), "a row past the end is null");
2876    }
2877
2878    /// The same for runs, which are built the same way and keep their nulls in the same place.
2879    #[test]
2880    fn a_null_inside_a_run_reads_as_null_even_though_the_mask_says_otherwise() {
2881        let values = Vector::flat(LogicalType::Integer, Data::Int32(vec![0, 7].into()))
2882            .unwrap()
2883            .with_validity(Validity::from_iter(2, |index| index != 0));
2884        let vector = Vector::runs(vec![2, 3], values).unwrap();
2885        assert!(vector.validity().is_valid(0));
2886        assert!(vector.is_null_at(0));
2887        assert!(vector.is_null_at(1));
2888        assert!(!vector.is_null_at(2));
2889    }
2890
2891    /// Every other form keeps its nulls in its own mask, so the two answers agree there.
2892    #[test]
2893    fn the_forms_that_hold_their_own_nulls_answer_the_same_either_way() {
2894        let flat = Vector::flat(LogicalType::Integer, Data::Int32(vec![0, 7].into()))
2895            .unwrap()
2896            .with_validity(Validity::from_iter(2, |index| index != 0));
2897        let constant = Vector::constant(LogicalType::Integer, Value::Null, 2);
2898        let sequence = Vector::sequence(10, 2, 2);
2899        for vector in [flat, constant, sequence] {
2900            for row in 0..vector.len() {
2901                assert_eq!(vector.is_null_at(row), !vector.validity().is_valid(row));
2902            }
2903        }
2904    }
2905
2906    #[test]
2907    fn flattening_a_flat_vector_is_the_same_vector() {
2908        let vector = integers(&[1, 2, 3]);
2909        assert_eq!(vector.flatten().unwrap(), vector);
2910    }
2911
2912    #[test]
2913    fn a_decimal_reads_its_width_and_scale_from_the_type_and_not_the_data() {
2914        let ty = LogicalType::decimal(9, 2).unwrap();
2915        let vector = Vector::flat(ty, Data::Int32(vec![1234].into())).unwrap();
2916        assert_eq!(vector.value_at(0), Value::Decimal { unscaled: 1234, width: 9, scale: 2 });
2917        assert_eq!(vector.value_at(0).to_string(), "12.34");
2918    }
2919
2920    #[test]
2921    fn a_decimal_writes_into_whichever_of_the_four_runs_its_precision_chose() {
2922        // The read path worked at every width and the write path only accepted the 128 bit run, so
2923        // `SELECT 2.5` produced a value nothing could store. All four widths round trip now.
2924        for (width, scale, unscaled) in
2925            [(4u8, 1u8, 25i128), (9, 2, 1234), (18, 3, 123_456), (38, 4, 1_234_567)]
2926        {
2927            let ty = LogicalType::decimal(width, scale).unwrap();
2928            let value = Value::Decimal { unscaled, width, scale };
2929            let vector = Vector::from_values(ty, &[value.clone(), Value::Null]).unwrap();
2930            assert_eq!(vector.value_at(0), value, "a decimal of width {width}");
2931            assert_eq!(vector.value_at(1), Value::Null, "a null decimal of width {width}");
2932        }
2933    }
2934
2935    /// The bytes a blob holds are not required to be text, and a vector of them used to refuse the
2936    /// ones that were not. A byte array column in a Parquet file that nothing annotated is a blob,
2937    /// which is what ClickHouse writes and what ten of the ClickBench queries compare against, so
2938    /// this is the path those take rather than a corner of the type system.
2939    #[test]
2940    fn a_blob_holds_bytes_that_are_not_text() {
2941        let bytes = |raw: &[u8]| Value::Blob(raw.to_vec());
2942        let values = [
2943            bytes(b"a\xffb"),
2944            bytes(b"\x00\x01\x02"),
2945            Value::Null,
2946            bytes(b"\xed\xa0\x80 and long enough to leave the view"),
2947            bytes(b""),
2948        ];
2949        let vector = Vector::from_values(LogicalType::Blob, &values).unwrap();
2950        for (index, value) in values.iter().enumerate() {
2951            assert_eq!(&vector.value_at(index), value, "row {index}");
2952        }
2953    }
2954
2955    #[test]
2956    fn a_decimal_too_wide_for_the_run_its_type_chose_is_an_error_and_not_a_wrong_number() {
2957        // Only reachable by hand, since a value's width is what picked the run. Truncating here
2958        // would store a different number and say nothing about it.
2959        let ty = LogicalType::decimal(4, 1).unwrap();
2960        let value = Value::Decimal { unscaled: 1_000_000, width: 4, scale: 1 };
2961        let error = Vector::from_values(ty, &[value]).unwrap_err();
2962        assert!(error.to_string().contains("does not fit"), "{error}");
2963    }
2964
2965    #[test]
2966    fn a_flat_vector_costs_its_values_and_a_constant_costs_one() {
2967        let flat = integers(&[1; 1000]);
2968        assert!(
2969            flat.footprint() >= 4000,
2970            "a thousand i32 are four thousand bytes: {}",
2971            flat.footprint()
2972        );
2973        // The forms that compute their values rather than storing them cost nothing per value,
2974        // which is the point of having them and is what the memory limit should see.
2975        let constant = Vector::constant(LogicalType::Integer, Value::Integer(1), 1_000_000);
2976        assert!(constant.footprint() < 200, "a constant is one value: {}", constant.footprint());
2977        let sequence = Vector::sequence(0, 1, 1_000_000);
2978        assert!(sequence.footprint() < 200, "a sequence is two numbers: {}", sequence.footprint());
2979    }
2980
2981    #[test]
2982    fn a_string_vector_costs_the_bytes_of_its_long_strings() {
2983        let short =
2984            Vector::from_values(LogicalType::Varchar, &[Value::Varchar("red".into())]).unwrap();
2985        let long = "a string well past the sixteen bytes a view holds inline".to_string();
2986        let spilled =
2987            Vector::from_values(LogicalType::Varchar, &[Value::Varchar(long.clone())]).unwrap();
2988        assert!(
2989            spilled.footprint() >= short.footprint() + long.len(),
2990            "the arena is counted: {} against {}",
2991            spilled.footprint(),
2992            short.footprint()
2993        );
2994    }
2995
2996    /// The cases worth checking are the widths where a code straddles a word boundary, which is
2997    /// every width that does not divide sixty four, and the two ends of the range.
2998    #[test]
2999    fn a_narrow_column_packs_and_reads_back_the_same_at_every_width() {
3000        for width in 1..=20u32 {
3001            let span = (1i64 << width) - 1;
3002            let values: Vec<i64> =
3003                (0..1000).map(|row| 1_000_000 + (row * 7919) % (span + 1)).collect();
3004            let flat =
3005                Vector::flat(LogicalType::BigInt, Data::Int64(values.clone().into())).unwrap();
3006            let packed = flat.bit_packed().unwrap();
3007            assert_eq!(packed.len(), flat.len());
3008            assert_eq!(
3009                packed.iter().collect::<Vec<_>>(),
3010                flat.iter().collect::<Vec<_>>(),
3011                "width {width} read back differently"
3012            );
3013        }
3014    }
3015
3016    #[test]
3017    fn the_width_is_the_bits_the_range_needs_and_not_the_bits_the_type_has() {
3018        let values: Vec<i32> = (0..1024).map(|row| 40 + (row * 2560) / 1023).collect();
3019        let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
3020        let packed = flat.bit_packed().unwrap();
3021        assert_eq!(packed.form(), Form::BitPacked);
3022        let parts = packed.packed_parts().expect("packed");
3023        assert_eq!(parts.width(), 12, "0 to 2560 is twelve bits");
3024        assert_eq!(parts.base(), 40);
3025        assert!(
3026            packed.footprint() * 2 < flat.footprint(),
3027            "twelve bits against thirty two: {} against {}",
3028            packed.footprint(),
3029            flat.footprint()
3030        );
3031    }
3032
3033    /// The check is worth having in both directions, the way the run length one is. A form that is
3034    /// only ever bigger than what it replaced costs a pass over the column to decide not to use.
3035    #[test]
3036    fn a_column_that_uses_its_whole_type_is_left_flat() {
3037        let values: Vec<i32> = (0..1024).map(|row| row * 2_000_000 - 1_000_000_000).collect();
3038        let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
3039        assert_eq!(flat.bit_packed().unwrap().form(), Form::Flat);
3040    }
3041
3042    /// A column of one value would pack to no bits at all, and one run is smaller than any packing
3043    /// of it, so the two forms do not fight over that column.
3044    #[test]
3045    fn a_column_of_one_value_is_left_to_the_run_length_form() {
3046        let flat = integers(&[9; 1024]);
3047        assert_eq!(flat.bit_packed().unwrap().form(), Form::Flat);
3048        assert_eq!(flat.run_encoded().unwrap().form(), Form::Rle);
3049    }
3050
3051    #[test]
3052    fn a_string_column_has_no_range_to_pack() {
3053        let text = Vector::from_values(
3054            LogicalType::Varchar,
3055            &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
3056        )
3057        .unwrap();
3058        assert_eq!(text.bit_packed().unwrap().form(), Form::Flat);
3059    }
3060
3061    /// The cut is the reason the form carries a row to start reading at. It stays packed, it shares
3062    /// the same words, and it reads the rows the range asked for.
3063    #[test]
3064    fn a_cut_of_a_packed_column_stays_packed_and_shares_its_bits() {
3065        let values: Vec<i32> = (0..1024).map(|row| 100 + row % 300).collect();
3066        let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
3067        let packed = flat.bit_packed().unwrap();
3068        let cut = packed.slice(500, 24).unwrap();
3069        assert_eq!(cut.form(), Form::BitPacked);
3070        assert_eq!(cut.len(), 24);
3071        assert_eq!(
3072            cut.iter().collect::<Vec<_>>(),
3073            flat.slice(500, 24).unwrap().iter().collect::<Vec<_>>()
3074        );
3075        assert!(
3076            cut.footprint() >= packed.footprint(),
3077            "a cut shares the words rather than copying a piece of them"
3078        );
3079    }
3080
3081    #[test]
3082    fn a_gather_of_a_packed_column_comes_out_flat_and_keeps_the_nulls() {
3083        let values: Vec<i32> = (0..64).map(|row| 10 + row).collect();
3084        let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
3085        let packed =
3086            flat.bit_packed().unwrap().with_validity(Validity::from_iter(64, |row| row % 3 != 0));
3087        let taken = packed.gather(&[0, 1, 2, 3, 62]).unwrap();
3088        assert_eq!(taken.form(), Form::Flat);
3089        assert_eq!(
3090            taken.iter().collect::<Vec<_>>(),
3091            vec![
3092                Value::Null,
3093                Value::Integer(11),
3094                Value::Integer(12),
3095                Value::Null,
3096                Value::Integer(72)
3097            ]
3098        );
3099    }
3100
3101    /// The pair a comparison kernel asks for before it reads a bit. A literal inside the range has a
3102    /// code and a literal outside it does not, which answers the whole vector at once.
3103    #[test]
3104    fn a_literal_outside_the_packed_range_has_no_code() {
3105        let values: Vec<i32> = (0..256).map(|row| 1000 + row).collect();
3106        let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
3107        let packed = flat.bit_packed().unwrap();
3108        let parts = packed.packed_parts().expect("packed");
3109        assert_eq!(parts.code_of(1000), Some(0));
3110        assert_eq!(parts.code_of(1100), Some(100));
3111        assert_eq!(parts.code_of(999), None);
3112        assert!(parts.ceiling() >= 1255);
3113        assert_eq!(parts.code_of(parts.ceiling() + 1), None);
3114    }
3115
3116    /// The bits arriving from a file rather than from a flat vector, which is what the form is for.
3117    #[test]
3118    fn packed_bits_can_be_handed_in_without_a_flat_vector_to_start_from() {
3119        let packed = Vector::packed(LogicalType::SmallInt, vec![0x0000_0000_0000_4321], 4, 7, 4)
3120            .expect("four codes of four bits");
3121        assert_eq!(
3122            packed.iter().collect::<Vec<_>>(),
3123            vec![Value::SmallInt(8), Value::SmallInt(9), Value::SmallInt(10), Value::SmallInt(11)]
3124        );
3125    }
3126
3127    #[test]
3128    fn packed_bits_that_could_not_hold_what_they_claim_are_refused() {
3129        assert!(Vector::packed(LogicalType::Varchar, vec![0], 4, 0, 4).is_err(), "not an integer");
3130        assert!(Vector::packed(LogicalType::Integer, vec![0], 0, 0, 4).is_err(), "no width");
3131        assert!(Vector::packed(LogicalType::Integer, vec![0], 64, 0, 4).is_err(), "too wide");
3132        assert!(Vector::packed(LogicalType::Integer, vec![0], 8, 0, 9).is_err(), "too few words");
3133        assert!(Vector::packed(LogicalType::TinyInt, vec![0], 8, 100, 8).is_err(), "would not fit");
3134    }
3135
3136    /// A column of strings long enough that the payload is in the arena rather than in the views.
3137    fn long_strings(count: usize) -> Vector {
3138        let values: Vec<Value> = (0..count)
3139            .map(|row| {
3140                Value::Varchar(format!("a string too long to sit inside a view, number {row}"))
3141            })
3142            .collect();
3143        Vector::from_values(LogicalType::Varchar, &values).unwrap()
3144    }
3145
3146    #[test]
3147    fn a_string_column_in_view_form_reads_back_the_same_strings() {
3148        let flat = long_strings(40);
3149        let shared = flat.clone().shared_text().unwrap();
3150        assert_eq!(shared.form(), Form::StringView);
3151        assert_eq!(shared.len(), 40);
3152        for row in 0..40 {
3153            assert_eq!(shared.value_at(row), flat.value_at(row), "row {row}");
3154            assert_eq!(shared.text_at(row), flat.text_at(row), "row {row}");
3155        }
3156    }
3157
3158    #[test]
3159    fn a_short_string_is_read_out_of_its_view_and_never_out_of_the_arena() {
3160        let flat = Vector::from_values(
3161            LogicalType::Varchar,
3162            &[Value::Varchar("red".into()), Value::Varchar("green".into()), Value::Null],
3163        )
3164        .unwrap();
3165        let shared = flat.shared_text().unwrap();
3166        // Nothing went to the arena, so the whole column resolves with an empty one.
3167        let (views, arena) = shared.text_parts().unwrap();
3168        assert!(arena.is_empty(), "three short strings need no arena");
3169        assert_eq!(views[0].bytes_in(arena), Some(&b"red"[..]));
3170        assert_eq!(shared.value_at(1), Value::Varchar("green".into()));
3171        assert_eq!(shared.value_at(2), Value::Null, "the validity came across");
3172    }
3173
3174    #[test]
3175    fn a_cut_of_a_view_column_shares_the_arena_rather_than_copying_the_bytes() {
3176        let shared = long_strings(64).shared_text().unwrap();
3177        let cut = shared.slice(16, 8).unwrap();
3178        assert_eq!(cut.form(), Form::StringView, "a cut of views is views");
3179        assert_eq!(cut.len(), 8);
3180        assert_eq!(cut.value_at(0), shared.value_at(16));
3181        assert_eq!(cut.value_at(7), shared.value_at(23));
3182        // The arena is the same bytes at the same address, which is the whole point of the form.
3183        let (_, whole) = shared.text_parts().unwrap();
3184        let (_, piece) = cut.text_parts().unwrap();
3185        assert_eq!(piece.as_ptr(), whole.as_ptr(), "the cut shares the page");
3186        assert_eq!(piece.len(), whole.len());
3187    }
3188
3189    #[test]
3190    fn a_flat_string_column_has_to_copy_the_bytes_its_cut_keeps() {
3191        let flat = long_strings(64);
3192        let cut = flat.slice(16, 8).unwrap();
3193        assert_eq!(cut.form(), Form::Flat);
3194        let (_, whole) = flat.text_parts().unwrap();
3195        let (_, piece) = cut.text_parts().unwrap();
3196        assert!(piece.len() < whole.len(), "the flat cut carries only what it kept");
3197    }
3198
3199    #[test]
3200    fn a_gather_of_a_view_column_keeps_the_form_and_a_flatten_copies_out_of_it() {
3201        let shared = long_strings(32).shared_text().unwrap();
3202        let picked: Vec<u32> = (0..32).step_by(3).collect();
3203        let gathered = shared.gather(&picked).unwrap();
3204        assert_eq!(gathered.form(), Form::StringView, "selecting rows moves views, not bytes");
3205        assert_eq!(gathered.len(), picked.len());
3206        for (row, &from) in picked.iter().enumerate() {
3207            assert_eq!(gathered.value_at(row), shared.value_at(from as usize), "row {row}");
3208        }
3209        let flattened = gathered.flatten().unwrap();
3210        assert_eq!(flattened.form(), Form::Flat);
3211        assert_eq!(flattened.iter().collect::<Vec<_>>(), gathered.iter().collect::<Vec<_>>());
3212        // The flatten is what narrows the bytes, so the arena it built holds only the rows it kept.
3213        let (_, narrowed) = flattened.text_parts().unwrap();
3214        let (_, whole) = shared.text_parts().unwrap();
3215        assert!(narrowed.len() < whole.len(), "flattening lets the page go");
3216    }
3217
3218    #[test]
3219    fn a_null_in_a_view_column_survives_being_gathered_and_flattened() {
3220        let shared = long_strings(8)
3221            .with_validity(Validity::from_iter(8, |row| row % 3 != 0))
3222            .shared_text()
3223            .unwrap();
3224        let gathered = shared.gather(&[0, 1, 2, 3, 4]).unwrap();
3225        let expected =
3226            [Value::Null, shared.value_at(1), shared.value_at(2), Value::Null, shared.value_at(4)];
3227        assert_eq!(gathered.iter().collect::<Vec<_>>(), expected);
3228        assert_eq!(gathered.flatten().unwrap().iter().collect::<Vec<_>>(), expected);
3229    }
3230
3231    #[test]
3232    fn both_string_forms_hand_a_kernel_the_same_views_and_the_same_bytes() {
3233        let flat = long_strings(6);
3234        let shared = flat.clone().shared_text().unwrap();
3235        let (flat_views, flat_arena) = flat.text_parts().unwrap();
3236        let (shared_views, shared_arena) = shared.text_parts().unwrap();
3237        assert_eq!(flat_views.len(), shared_views.len());
3238        for row in 0..6 {
3239            assert_eq!(
3240                flat_views[row].bytes_in(flat_arena),
3241                shared_views[row].bytes_in(shared_arena),
3242                "row {row}"
3243            );
3244        }
3245        // Nothing else answers this, which is what keeps a kernel from taking it for a string column.
3246        assert!(Vector::sequence(0, 1, 4).text_parts().is_none());
3247        assert!(integers(&[1, 2, 3]).text_parts().is_none());
3248    }
3249
3250    #[test]
3251    fn a_column_that_is_not_strings_cannot_be_held_as_views() {
3252        let views = vec![StringView::inline("red")];
3253        let arena = Arc::new(Buffer::new());
3254        let wrong = Vector::string_views(LogicalType::Integer, views, arena);
3255        assert!(wrong.is_err(), "an integer column has no views");
3256        assert_eq!(integers(&[1, 2]).shared_text().unwrap().form(), Form::Flat, "left alone");
3257    }
3258
3259    /// A column with enough repeated structure for a symbol table to find something, which is what
3260    /// a real text column has and a column of random bytes does not.
3261    fn sentences(count: usize) -> Vector {
3262        let values: Vec<Value> = (0..count)
3263            .map(|row| {
3264                Value::Varchar(format!(
3265                    "http://example.test/catalogue/section/{}/item/{row}",
3266                    row % 7
3267                ))
3268            })
3269            .collect();
3270        Vector::from_values(LogicalType::Varchar, &values).unwrap()
3271    }
3272
3273    #[test]
3274    fn a_compressed_column_reads_back_the_strings_that_went_into_it() {
3275        let flat = sentences(64);
3276        let coded = flat.clone().compressed().unwrap();
3277        assert_eq!(coded.form(), Form::Fsst, "a text column compresses");
3278        assert_eq!(coded.len(), 64);
3279        for row in 0..64 {
3280            assert_eq!(coded.value_at(row), flat.value_at(row), "row {row}");
3281        }
3282        assert_eq!(coded.flatten().unwrap(), flat, "flattening is the column it came from");
3283    }
3284
3285    #[test]
3286    fn compressing_halves_the_bytes_or_the_column_is_left_flat() {
3287        let flat = sentences(200);
3288        let coded = flat.clone().compressed().unwrap();
3289        let parts = coded.coded_parts().expect("compressed");
3290        // Read through the flat column, because the compressed one has no bytes to hand back where
3291        // they are and answers `None` to `text_at` rather than decompressing into a borrow.
3292        assert_eq!(coded.text_at(0), None, "nothing to borrow until it is flattened");
3293        let plain: usize = (0..200).map(|row| flat.text_at(row).map_or(0, str::len)).sum();
3294        let codes: usize = (0..200).map(|row| parts.row(row).map_or(0, <[u8]>::len)).sum();
3295        assert!(codes * FSST_PAYS_AT <= plain, "{codes} codes against {plain} bytes");
3296        // Text with no repeated structure in it gives a table nothing longer than a byte to find,
3297        // so the codes are the bytes and the column stays where it is rather than paying a
3298        // decompression per read to save nothing.
3299        let mut seed = 0x2545_f491_4f6c_dd1du64;
3300        let values: Vec<Value> = (0..256)
3301            .map(|_| {
3302                let mut text = String::new();
3303                while text.len() < 12 {
3304                    seed = seed.wrapping_mul(6_364_136_223_846_793_005).wrapping_add(1);
3305                    text.push(char::from(b'!' + ((seed >> 33) % 90) as u8));
3306                }
3307                Value::Varchar(text)
3308            })
3309            .collect();
3310        let noise = Vector::from_values(LogicalType::Varchar, &values).unwrap();
3311        assert_eq!(noise.compressed().unwrap().form(), Form::Flat);
3312    }
3313
3314    #[test]
3315    fn a_cut_of_a_compressed_column_shares_the_codes_and_the_table() {
3316        let coded = sentences(64).compressed().unwrap();
3317        let cut = coded.slice(8, 16).unwrap();
3318        assert_eq!(cut.form(), Form::Fsst);
3319        assert_eq!(cut.len(), 16);
3320        for row in 0..16 {
3321            assert_eq!(cut.value_at(row), coded.value_at(8 + row), "row {row}");
3322        }
3323        let (whole, piece) = (coded.coded_parts().unwrap(), cut.coded_parts().unwrap());
3324        assert_eq!(piece.row(0), whole.row(8), "the spans point into the same codes");
3325    }
3326
3327    #[test]
3328    fn a_gather_of_a_compressed_column_stays_compressed_and_keeps_the_nulls() {
3329        let coded = sentences(32)
3330            .with_validity(Validity::from_iter(32, |row| row % 5 != 2))
3331            .compressed()
3332            .unwrap();
3333        let picked: Vec<u32> = (0..32).step_by(2).collect();
3334        let gathered = coded.gather(&picked).unwrap();
3335        assert_eq!(gathered.form(), Form::Fsst, "selecting rows moves spans, not bytes");
3336        for (row, &from) in picked.iter().enumerate() {
3337            assert_eq!(gathered.value_at(row), coded.value_at(from as usize), "row {row}");
3338        }
3339        assert_eq!(
3340            gathered.flatten().unwrap().iter().collect::<Vec<_>>(),
3341            gathered.iter().collect::<Vec<_>>()
3342        );
3343    }
3344
3345    #[test]
3346    fn a_literal_lands_in_the_same_codes_the_row_holding_it_does() {
3347        let coded = sentences(40).compressed().unwrap();
3348        let parts = coded.coded_parts().expect("compressed");
3349        let text = coded.value_at(11);
3350        let Value::Varchar(text) = text else { panic!("a string column reads back strings") };
3351        assert_eq!(parts.encode(text.as_bytes()), parts.row(11).expect("row 11"));
3352        assert_ne!(parts.encode(b"something else entirely"), parts.row(11).unwrap());
3353    }
3354
3355    #[test]
3356    fn codes_that_run_past_what_is_there_are_refused() {
3357        let table = Arc::new(SymbolTable::empty());
3358        let codes = Arc::new(vec![1u8, 2, 3, 4]);
3359        let good = vec![(0u32, 2u32), (2, 4)];
3360        assert!(
3361            Vector::coded(LogicalType::Varchar, Arc::clone(&codes), good, Arc::clone(&table))
3362                .is_ok()
3363        );
3364        let past = vec![(0u32, 9u32)];
3365        assert!(
3366            Vector::coded(LogicalType::Varchar, Arc::clone(&codes), past, Arc::clone(&table))
3367                .is_err(),
3368            "a span past the end of the codes"
3369        );
3370        let backwards = vec![(3u32, 1u32)];
3371        assert!(
3372            Vector::coded(LogicalType::Varchar, Arc::clone(&codes), backwards, Arc::clone(&table))
3373                .is_err(),
3374            "a span that ends before it starts"
3375        );
3376        let wrong = vec![(0u32, 2u32)];
3377        assert!(
3378            Vector::coded(LogicalType::Integer, codes, wrong, table).is_err(),
3379            "an integer column has no codes"
3380        );
3381    }
3382
3383    #[test]
3384    fn a_view_pointing_past_its_arena_is_refused_at_construction() {
3385        let long = "a string too long to sit inside a view";
3386        let arena: Arc<Buffer<u8>> = Arc::new(long.as_bytes().to_vec().into());
3387        let good = vec![StringView::over(long.as_bytes(), 0)];
3388        assert!(Vector::string_views(LogicalType::Varchar, good, Arc::clone(&arena)).is_ok());
3389        let bad = vec![StringView::over(long.as_bytes(), 4)];
3390        assert!(
3391            Vector::string_views(LogicalType::Varchar, bad, arena).is_err(),
3392            "four bytes short of what the view claims"
3393        );
3394    }
3395}