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//! The nested forms are the odd ones out in a different direction. The forms above are all ways of
25//! writing a column of scalars down more cheaply, and a nested value is not a scalar at all, so
26//! [`Form::List`] and [`Form::Struct`] are each the only form their column has rather than one of
27//! several it could be in. A list is a child vector of every element plus a start and a length per
28//! row. A struct is one child per field with no entries at all, because a struct row holds one value
29//! per field rather than a run of them. Either way the children are ordinary vectors and can be in any
30//! of the forms above, which is where a nested column gets made smaller.
31//!
32//! **What is not here yet.** Buffers are owned. Section 7.1 says a vector borrowed from a buffer
33//! managed page carries a pin, and there is no buffer manager until M2, so there is nothing to pin
34//! and pretending otherwise would be an interface built against an imaginary caller. `ARRAY` is not
35//! stored yet either, and it is a composition of what is here rather than a new shape: it is a list
36//! whose length is the type's rather than the row's, the way a `MAP` is a list whose child is a two
37//! field struct of keys and values. `UNION` is the one that is genuinely different, since it is one
38//! child per member plus a tag saying which member each row is in.
39
40use std::borrow::Cow;
41use std::sync::Arc;
42
43use rudb_common::{Cause, Error, Field, LogicalType, Result, Value, slow};
44
45use crate::buffer::Buffer;
46use crate::fsst::SymbolTable;
47use crate::string::{StringColumn, StringView};
48use crate::validity::Validity;
49
50/// How many values are in a full vector.
51///
52/// 1024 rather than DuckDB's 2048, per `spec/04-architecture.md` section 4.3. It is the FastLanes
53/// unit, it makes a validity mask exactly 16 `u64` words, and it keeps a vector of 16 byte string
54/// views at 16 KiB, which is the size at which several of these fit in L1 together rather than
55/// evicting each other.
56pub const VECTOR_SIZE: usize = 1024;
57
58/// What the key field of a map's child struct is called.
59///
60/// A map is stored as a list of two field structs, and these are the two names. They are DuckDB's, and
61/// they are also the names the Parquet specification gives a map's repeated group, so a reader that
62/// builds one of these from a file finds the names already agreed rather than translated.
63pub const MAP_KEY: &str = "key";
64
65/// What the value field of a map's child struct is called. See [`MAP_KEY`].
66pub const MAP_VALUE: &str = "value";
67
68/// What [`Vector::map_parts`] hands back: one entry per row, then the keys and then the values.
69///
70/// A name rather than the triple written out, because the triple written out is over the complexity
71/// clippy allows and because a kernel that takes these as an argument should be able to say so in one
72/// word.
73pub type MapParts<'a> = (&'a [(u32, u32)], &'a Vector, &'a Vector);
74
75/// Which physical form a vector is in.
76///
77/// An operator asks this once per vector and then takes the path it wants, which is the one branch
78/// per vector that the whole design is willing to spend.
79///
80/// Not exhaustive, and that is a decision rather than an oversight. `Encoded` is the fifth form
81/// and it arrives at layer three with the specialization contract. If this enum were exhaustive,
82/// the day it lands is the day every kernel in the workspace stops compiling, and the pressure at
83/// that moment would be to add an arm to each of them in a hurry rather than to think about what
84/// each one should do with an encoded vector. A required fallback arm means each kernel already
85/// has a correct answer for a form it has never seen, and specializing it is then a change that
86/// can be made one kernel at a time with a benchmark next to it.
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88#[non_exhaustive]
89pub enum Form {
90 /// One value per position.
91 Flat,
92 /// One value, repeated.
93 Constant,
94 /// A start and a step, computed rather than stored.
95 Sequence,
96 /// Codes into a smaller vector of distinct values.
97 Dictionary,
98 /// Integers stored in as many bits as the range of the column needs, offset from a base.
99 ///
100 /// The form a narrow integer column is in. A ClickBench `ResolutionWidth` is a `SMALLINT` whose
101 /// values live between 0 and 2560, which is twelve bits, so the column is three quarters of the
102 /// size it was and the pages behind it are three quarters of the reads. What it costs is a shift
103 /// and a mask per value, which is why this is worth it at storage and at rest and is not a form
104 /// anything should be building in the middle of a pipeline.
105 BitPacked,
106 /// Sixteen byte views over an arena the vector shares rather than owns.
107 ///
108 /// The form a varchar column is in once more than one vector is looking at the same page. A flat
109 /// varchar vector owns its arena, so cutting a chunk out of it copies every byte of every long
110 /// string in the range, and on ClickBench that is most of what reading `URL` costs. Sharing the
111 /// arena makes the cut the views and nothing else, the way a dictionary cut is the codes and
112 /// nothing else.
113 StringView,
114 /// Strings compressed against one symbol table, each row on its own.
115 ///
116 /// The form a text column is in at rest. FSST is about half the bytes on the ClickBench `URL`
117 /// and `Title` columns, and unlike a block compressor it keeps random access, so reading row
118 /// four million does not decompress the four million before it. What it costs is a decompression
119 /// per row read, which is why an equality filter over it is worth writing in code space: the
120 /// literal compresses once and the rows never decompress at all.
121 Fsst,
122 /// One value per run, with the row each run ends at.
123 ///
124 /// The form a clustered column is in. `hits` is written in time order, so `EventDate` is a few
125 /// hundred runs over a hundred million rows, and a sum over it is a few hundred multiplications
126 /// rather than a hundred million additions. Dictionary says which distinct values there are and
127 /// this says where they stop, and a column can want either one without wanting the other.
128 Rle,
129 /// A child vector of every element, and a start and a length per row.
130 ///
131 /// The form a `LIST` column is in, and the only form it has. The others are all ways of writing
132 /// down a column of scalars more cheaply and this is the shape a nested value has at all, so a
133 /// list vector reports this whether or not anything has tried to make it smaller. Making it
134 /// smaller happens in the child, which is an ordinary vector and can be any of the forms above.
135 ///
136 /// A `MAP` column reports this too, because a map is a list whose child is a two field struct and
137 /// the bytes really are a list's. This enum is about the physical layout, and the logical type is
138 /// what remembers the difference, which is the same division `LogicalType::physical` already makes.
139 List,
140 /// One child vector per field, each as long as the vector itself.
141 ///
142 /// The form a `STRUCT` column is in, and the only form it has, for the reason [`Form::List`] is
143 /// the only form a list has. A struct holds exactly one value per field per row rather than a run
144 /// of them, so there are no entries here and the children line up with the rows one to one, which
145 /// makes a cut a cut of every child and a gather a gather of every child. Each child is an
146 /// ordinary vector and can be in any of the forms above, so that is where a struct column gets
147 /// made smaller.
148 Struct,
149}
150
151/// The values of a flat vector, one Rust vector per physical type.
152///
153/// The variants are physical rather than logical, which is what lets `DATE` and `INTEGER` share
154/// storage and share a kernel. What a run of `i32` means is the vector's logical type's business.
155#[derive(Debug, Clone, PartialEq)]
156#[non_exhaustive]
157pub enum Data {
158 /// No values, for the type of an untyped `NULL`.
159 Empty,
160 /// One byte per value.
161 Bool(Buffer<bool>),
162 /// 8 bit signed.
163 Int8(Buffer<i8>),
164 /// 16 bit signed.
165 Int16(Buffer<i16>),
166 /// 32 bit signed.
167 Int32(Buffer<i32>),
168 /// 64 bit signed.
169 Int64(Buffer<i64>),
170 /// 128 bit signed.
171 Int128(Buffer<i128>),
172 /// 8 bit unsigned.
173 UInt8(Buffer<u8>),
174 /// 16 bit unsigned.
175 UInt16(Buffer<u16>),
176 /// 32 bit unsigned.
177 UInt32(Buffer<u32>),
178 /// 64 bit unsigned.
179 UInt64(Buffer<u64>),
180 /// 128 bit unsigned.
181 UInt128(Buffer<u128>),
182 /// IEEE 754 binary32.
183 Float32(Buffer<f32>),
184 /// IEEE 754 binary64.
185 Float64(Buffer<f64>),
186 /// The months, days and microseconds triple.
187 Interval(Buffer<(i32, i32, i64)>),
188 /// Strings, as 16 byte views plus the arena the long ones live in.
189 Varlen(StringColumn),
190}
191
192impl Data {
193 /// How many values are stored.
194 ///
195 /// The match below has no wildcard arm, and that is what makes this function the check that
196 /// keeps [`for_each_layout`](crate::for_each_layout) honest. A variant added to this enum
197 /// without being added to the `all` group fails to compile here, which is a line in a build log
198 /// rather than a layout quietly missing from six kernels.
199 #[must_use]
200 pub fn len(&self) -> usize {
201 macro_rules! lengths {
202 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
203 match self {
204 Self::Empty => 0,
205 $(Self::$variant(values) => values.len(),)+
206 }
207 };
208 }
209 crate::for_each_layout!(all, lengths)
210 }
211
212 /// Whether there are no values.
213 #[must_use]
214 pub fn is_empty(&self) -> bool {
215 self.len() == 0
216 }
217
218 /// How many bytes of memory these values are holding.
219 ///
220 /// One arm per layout through the same macro as [`Data::len`], for the same reason: a layout
221 /// added without a size here is a layout the memory limit would charge nothing for, and a
222 /// buffer that is free is a buffer that can be grown until the process dies.
223 #[must_use]
224 pub fn footprint(&self) -> usize {
225 macro_rules! sizes {
226 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
227 match self {
228 Self::Empty => 0,
229 $(Self::$variant(values) => values.footprint(),)+
230 }
231 };
232 }
233 crate::for_each_layout!(all, sizes)
234 }
235
236 /// An integer at `index`, widened, for any of the signed integer layouts.
237 ///
238 /// Used by the decimal path, which needs the unscaled value out of whichever width the width
239 /// and scale picked, and by anything else that would otherwise repeat the same five arms.
240 #[must_use]
241 pub fn signed_at(&self, index: usize) -> Option<i128> {
242 macro_rules! widened {
243 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
244 match self {
245 $(Self::$variant(v) => v.get(index).map(|&x| i128::from(x)),)+
246 _ => None,
247 }
248 };
249 }
250 crate::for_each_layout!(signed, widened)
251 }
252
253 /// An unsigned integer at `index`, widened.
254 #[must_use]
255 pub fn unsigned_at(&self, index: usize) -> Option<u128> {
256 macro_rules! widened {
257 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
258 match self {
259 $(Self::$variant(v) => v.get(index).map(|&x| u128::from(x)),)+
260 _ => None,
261 }
262 };
263 }
264 crate::for_each_layout!(unsigned, widened)
265 }
266
267 /// The string at `index`, for a `Varlen`.
268 #[must_use]
269 pub fn str_at(&self, index: usize) -> Option<&str> {
270 match self {
271 Self::Varlen(column) => column.get(index),
272 _ => None,
273 }
274 }
275
276 /// The bytes at `index`, for a `Varlen`, whatever they are.
277 ///
278 /// What a `BLOB` reads through, since the bytes of one are not required to be text and
279 /// [`Self::str_at`] answers `None` for the ones that are not.
280 #[must_use]
281 pub fn bytes_at(&self, index: usize) -> Option<&[u8]> {
282 match self {
283 Self::Varlen(column) => column.bytes(index),
284 _ => None,
285 }
286 }
287}
288
289/// A type, a length, a validity representation and some data.
290#[derive(Debug, Clone, PartialEq)]
291pub struct Vector {
292 ty: LogicalType,
293 len: usize,
294 validity: Validity,
295 body: Body,
296}
297
298/// What the vector holds, which is what its form is decided by.
299#[derive(Debug, Clone, PartialEq)]
300enum Body {
301 Flat(Data),
302 Constant(Box<Value>),
303 Sequence {
304 start: i64,
305 step: i64,
306 },
307 /// The values are behind an `Arc` rather than a `Box` because slicing shares them.
308 ///
309 /// A dictionary vector is cut once per chunk and the dictionary itself is the same dictionary
310 /// every time, so a `Box` meant a copy of every value in it per cut. On the ClickBench columns
311 /// that are dictionary encoded the dictionary is larger than the chunk of codes pointing into
312 /// it, and copying it was ten percent of the cycles of reading the file.
313 ///
314 /// Nothing here mutates a dictionary in place, so sharing one is only ever a read, and the one
315 /// place that wants an owned copy of the values is [`compose`], which asks for one.
316 Dictionary {
317 codes: Vec<u32>,
318 values: Arc<Vector>,
319 stable: bool,
320 },
321 /// Integer codes of `width` bits each, packed end to end, each one an offset from `base`.
322 ///
323 /// Row `r` is the `width` bits starting at bit `(offset + r) * width`, read little end first, so
324 /// a code that straddles a word boundary has its low bits in the earlier word. `offset` is what
325 /// lets a cut of a packed column be free: the bits are not byte aligned, so a slice either
326 /// repacks or remembers where it starts, and remembering is one addition per read.
327 ///
328 /// The words are behind an `Arc` for the reason the dictionary's values are. A page is packed
329 /// once and cut into chunk sized pieces, and copying the words per cut would undo most of what
330 /// the packing saved.
331 Packed {
332 words: Arc<Vec<u64>>,
333 width: u32,
334 base: i128,
335 offset: usize,
336 },
337 /// The views of a string column, over an arena that other vectors are reading at the same time.
338 ///
339 /// The views are owned because a cut is a different run of views, and the arena is shared
340 /// because a cut is the same bytes. That split is the whole form: sixteen bytes a row move and
341 /// the payload does not, however many cuts a page is taken in.
342 ///
343 /// A row's bytes are found the same way [`StringColumn`] finds them, through
344 /// [`StringView::bytes_in`], so a short string never reads the arena at all and the two ways of
345 /// holding strings cannot answer a row differently.
346 Views {
347 views: Vec<StringView>,
348 arena: Arc<Buffer<u8>>,
349 },
350 /// Text owned by a storage source and fetched by position.
351 ExternalText {
352 source: Arc<dyn TextSource>,
353 },
354 /// The FSST codes of every row, end to end, with one symbol table over all of them.
355 ///
356 /// A span rather than a run of offsets, because a gather keeps this form and a gather puts the
357 /// rows in an order the codes are not in. Eight bytes a row either way, and the span is the one
358 /// that survives being permuted.
359 ///
360 /// The codes and the table are shared for the reason a dictionary's values are: one table is
361 /// trained per page and every chunk cut out of it points at the same one. A table is sixty five
362 /// thousand hash slots, so a table per chunk would cost more than the compression saves.
363 Coded {
364 codes: Arc<Vec<u8>>,
365 spans: Vec<(u32, u32)>,
366 table: Arc<SymbolTable>,
367 },
368 /// One value per run, with the row each run ends at, exclusive and increasing.
369 ///
370 /// Ends rather than lengths, because every reader of this wants to know which run holds a row
371 /// and ends answer that with a binary search while lengths answer it with a running total. The
372 /// two are the same information and only one of them is the one that gets asked for.
373 ///
374 /// The values are behind an `Arc` for the reason the dictionary's are: a page is cut into chunk
375 /// sized pieces and the values are the same values every time.
376 Runs {
377 ends: Vec<u32>,
378 values: Arc<Vector>,
379 },
380 /// One child vector holding every element of every row, and a start and a length per row.
381 ///
382 /// Start and length rather than the run of offsets Arrow carries, because offsets say where a
383 /// row ends by saying where the next one begins, and that is only true while the rows are in
384 /// order and none is skipped. A gather permutes the rows and a filter drops them, both of which
385 /// this form has to survive without copying the child, so each row says where its own elements
386 /// are and nothing is implied about its neighbour.
387 ///
388 /// The child is behind an `Arc` for the reason a dictionary's values are. A cut of a list column
389 /// is the entries and nothing else, so a page of lists taken in chunk sized pieces holds one
390 /// child however many pieces it is read in, and the elements outside the cut stay reachable but
391 /// unreferenced rather than being copied out.
392 ///
393 /// A null list and an empty list are different rows and this is where the difference lives. A
394 /// null is the validity mask at this level being false, the same as for any other type, and its
395 /// entry is `(start, 0)` and never read. An empty list is a valid row whose entry is `(start, 0)`
396 /// as well. So the entry alone does not say which one a row is, the mask does, which is the same
397 /// division of labour every other form here uses.
398 ///
399 /// A `MAP` is stored here too, with a [`Body::Fields`] child of `key` and `value`. Everything above
400 /// is true of it unchanged, which is the point of storing it this way: the cut, the gather and the
401 /// null rule are written once and a map inherits all three.
402 Nested {
403 entries: Vec<(u32, u32)>,
404 child: Arc<Vector>,
405 },
406 /// One child vector per field, in the order the type names them, each as long as this vector.
407 ///
408 /// No entries, which is the whole difference from [`Body::Nested`]. A list row is a run of
409 /// elements so it needs to say where its run is, and a struct row is one value per field so row
410 /// `r` of field `f` is position `r` of child `f` and there is nothing to record. That makes a cut
411 /// a cut of every child and a gather a gather of every child, both at the same positions, rather
412 /// than a rewrite of an index.
413 ///
414 /// The children are behind an `Arc` for the reason a dictionary's values are, and it pays off less
415 /// often here. A cut of a list column shares its child untouched because the entries carry the
416 /// range, and a cut of a struct column has to cut each child, so the sharing only survives the
417 /// cases where nothing moves. It is still worth having, because a struct of a hundred fields
418 /// handed between operators is a hundred pointers rather than a hundred columns.
419 ///
420 /// A null struct is the validity mask at this level being false and says nothing about the
421 /// children, which still hold whatever was put in them at that row. That is DuckDB's behaviour and
422 /// it is the reason this form cannot decide a row is null by looking down: the mask is the answer,
423 /// the same as it is for a list.
424 Fields {
425 children: Vec<Arc<Vector>>,
426 },
427}
428
429/// Random access to immutable text kept by a storage reader.
430pub trait TextSource: std::fmt::Debug + Send + Sync {
431 /// Number of values available.
432 fn len(&self) -> usize;
433 /// Whether this source has no values.
434 fn is_empty(&self) -> bool {
435 self.len() == 0
436 }
437 /// Bytes at one position, or no value when the position is outside the source.
438 fn bytes_at(&self, index: usize) -> Result<Option<&[u8]>>;
439 /// Byte length at one position without requiring the payload when the source has an index.
440 fn bytes_len_at(&self, index: usize) -> Result<Option<usize>> {
441 Ok(self.bytes_at(index)?.map(<[u8]>::len))
442 }
443 /// Resident bytes retained by this source.
444 fn footprint(&self) -> usize;
445 /// Whether another source presents the same values.
446 fn equal(&self, other: &dyn TextSource) -> bool {
447 self.len() == other.len()
448 && (0..self.len()).all(|index| {
449 matches!(
450 (self.bytes_at(index), other.bytes_at(index)),
451 (Ok(left), Ok(right)) if left == right
452 )
453 })
454 }
455}
456
457impl PartialEq for dyn TextSource {
458 fn eq(&self, other: &Self) -> bool {
459 self.equal(other)
460 }
461}
462
463impl Vector {
464 /// A flat vector of `data`, all valid.
465 ///
466 /// # Errors
467 ///
468 /// If the data's physical layout is not the one the type calls for. That check is here rather
469 /// than left to the caller because a vector whose type and layout disagree is a wrong answer
470 /// waiting to be read out, and it costs one comparison at construction to prevent.
471 pub fn flat(ty: LogicalType, data: Data) -> Result<Self> {
472 let len = data.len();
473 if !matches!(data, Data::Empty) && layout_of(&data) != ty.physical() {
474 return Err(Error::internal(format!(
475 "a {ty} vector cannot hold {:?} data",
476 layout_of(&data)
477 )));
478 }
479 Ok(Self { ty, len, validity: Validity::AllValid, body: Body::Flat(data) })
480 }
481
482 /// A flat vector built from single values, with the nulls among them turning into validity.
483 ///
484 /// The slow way in, and the only way in that anything outside this crate has. It is what an
485 /// `INSERT`, a `VALUES` clause and a test build a column with, all of which arrive holding
486 /// values rather than a run of `i32`. Nothing on a scan path calls it: a scan produces a run of
487 /// data directly and hands it to [`Self::flat`].
488 ///
489 /// # Errors
490 ///
491 /// If a value is not one the type can hold, or if the type is one there is no vector for yet,
492 /// which today means `ARRAY` and `UNION`. A `LIST`, a `STRUCT` and a `MAP` are routed to their own
493 /// builders and come back built.
494 pub fn from_values(ty: LogicalType, values: &[Value]) -> Result<Self> {
495 match &ty {
496 LogicalType::List(element) => {
497 return Self::list_from_values(element.as_ref().clone(), values);
498 }
499 LogicalType::Struct(fields) => return Self::struct_from_values(fields, values),
500 LogicalType::Map(key, value) => {
501 return Self::map_from_values(key.as_ref().clone(), value.as_ref().clone(), values);
502 }
503 _ => {}
504 }
505 let mut data = empty_data_for(&ty)?;
506 for value in values {
507 push_value(&mut data, value)?;
508 }
509 let validity = Validity::from_iter(values.len(), |index| !values[index].is_null());
510 Ok(Self { ty, len: values.len(), validity, body: Body::Flat(data) })
511 }
512
513 /// A list vector of `element`, built from one [`Value::List`] per row.
514 ///
515 /// The elements of every row go into one child vector end to end, so a row's elements are a
516 /// contiguous range of it and a row is a start and a length into it. That is what makes a cut of
517 /// this form the entries and nothing else.
518 ///
519 /// A null row contributes no elements and gets an entry of length zero, which is the same entry
520 /// an empty list gets. The two are told apart by the validity mask rather than by the entry, for
521 /// the reason written on [`Body::Nested`].
522 fn list_from_values(element: LogicalType, values: &[Value]) -> Result<Self> {
523 let mut flat = Vec::new();
524 let mut entries = Vec::with_capacity(values.len());
525 for value in values {
526 let start = u32::try_from(flat.len())
527 .map_err(|_| Error::internal("a list column with more than u32 elements in it"))?;
528 match value {
529 Value::Null => entries.push((start, 0)),
530 Value::List { values: held, .. } => {
531 let len = u32::try_from(held.len())
532 .map_err(|_| Error::internal("a list longer than u32"))?;
533 flat.extend_from_slice(held);
534 entries.push((start, len));
535 }
536 other => {
537 return Err(Error::internal(format!(
538 "{other:?} does not belong in a list vector"
539 )));
540 }
541 }
542 }
543 // The element type is the column's rather than any one value's. A `Value::List` carries what
544 // it thinks it is empty of, and a column built from a row of `INTEGER[]` and a row of
545 // `[]::NULL[]` would otherwise take its type from whichever row came first.
546 let child = Self::from_values(element, &flat)?;
547 let validity = Validity::from_iter(values.len(), |index| !values[index].is_null());
548 Ok(Self {
549 ty: LogicalType::list(child.ty.clone()),
550 len: values.len(),
551 validity,
552 body: Body::Nested { entries, child: Arc::new(child) },
553 })
554 }
555
556 /// A list vector over a child that already exists, one entry per row.
557 ///
558 /// What a scan and a list returning kernel build, both of which produce the elements in bulk and
559 /// then say which row each range belongs to. Every row is valid, since a caller with nulls to
560 /// record adds them with [`Self::with_validity`].
561 ///
562 /// # Errors
563 ///
564 /// If an entry runs past the end of the child, which would be a row that reads elements belonging
565 /// to nobody and is the one mistake this form makes easy.
566 pub fn list(entries: Vec<(u32, u32)>, child: Vector) -> Result<Self> {
567 let reach = child.len();
568 for &(start, len) in &entries {
569 if start as usize + len as usize > reach {
570 return Err(Error::internal(format!(
571 "a list entry of {len} at {start} in a child of {reach}"
572 )));
573 }
574 }
575 Ok(Self {
576 ty: LogicalType::list(child.ty.clone()),
577 len: entries.len(),
578 validity: Validity::AllValid,
579 body: Body::Nested { entries, child: Arc::new(child) },
580 })
581 }
582
583 /// A struct vector of `fields`, built from one [`Value::Struct`] per row.
584 ///
585 /// One pass per field rather than one pass per row, because each field becomes its own child
586 /// vector and a child is built from a run of values of one type. So a struct of three fields over
587 /// a thousand rows is three calls to [`Self::from_values`] and not a thousand.
588 ///
589 /// The fields are matched by name and not by position. A `Value::Struct` carries its names, and a
590 /// caller that built one in a different order from the type's would otherwise get the values
591 /// silently transposed into the wrong columns, which is the kind of wrong answer that reads as
592 /// right. A row missing a field the type names is an error rather than a null for the same reason.
593 ///
594 /// A null row is a null in every child as well as a false bit in the mask here. [`Body::Fields`]
595 /// says a null struct is allowed to have readable children and that is about a struct built out of
596 /// children that already exist, where whatever is underneath is the caller's. Built from values
597 /// there is nothing underneath to keep, so the children get the null.
598 fn struct_from_values(fields: &[Field], values: &[Value]) -> Result<Self> {
599 let mut children = Vec::with_capacity(fields.len());
600 for field in fields {
601 let mut column = Vec::with_capacity(values.len());
602 for value in values {
603 column.push(match value {
604 Value::Null => Value::Null,
605 Value::Struct(held) => held
606 .iter()
607 .find(|(name, _)| *name == field.name)
608 .map(|(_, held)| held.clone())
609 .ok_or_else(|| {
610 Error::internal(format!(
611 "a struct row with no {} field in it",
612 field.name
613 ))
614 })?,
615 other => {
616 return Err(Error::internal(format!(
617 "{other:?} does not belong in a struct vector"
618 )));
619 }
620 });
621 }
622 children.push(Arc::new(Self::from_values(field.ty.clone(), &column)?));
623 }
624 let validity = Validity::from_iter(values.len(), |index| !values[index].is_null());
625 Ok(Self {
626 ty: LogicalType::Struct(fields.to_vec()),
627 len: values.len(),
628 validity,
629 body: Body::Fields { children },
630 })
631 }
632
633 /// A struct vector over children that already exist, one per field.
634 ///
635 /// What a scan and a struct returning kernel build, both of which produce each field as a column
636 /// and then put them side by side. Every row is valid, since a caller with nulls to record adds
637 /// them with [`Self::with_validity`].
638 ///
639 /// # Errors
640 ///
641 /// If there are no fields, or if the children are not all the same length. The first is not a
642 /// fussy restriction: a struct vector with no children has no child to take its length from, so a
643 /// zero field struct column would be a length with nothing to check it against, and a caller that
644 /// wants a column of empty structs wants a constant vector of one.
645 pub fn structure(children: Vec<(String, Vector)>) -> Result<Self> {
646 let Some((_, first)) = children.first() else {
647 return Err(Error::internal("a struct vector of no fields, which has no length"));
648 };
649 let len = first.len();
650 for (name, child) in &children {
651 if child.len() != len {
652 return Err(Error::internal(format!(
653 "a {} field of {} rows beside a struct of {len}",
654 name,
655 child.len()
656 )));
657 }
658 }
659 let fields = children
660 .iter()
661 .map(|(name, child)| Field::new(name.clone(), child.ty.clone()))
662 .collect();
663 let children = children.into_iter().map(|(_, child)| Arc::new(child)).collect();
664 Ok(Self {
665 ty: LogicalType::Struct(fields),
666 len,
667 validity: Validity::AllValid,
668 body: Body::Fields { children },
669 })
670 }
671
672 /// The children, for a struct vector, and `None` for any other form.
673 ///
674 /// The accessor a kernel over a struct column reads, and the reason field extraction is free:
675 /// picking one field out of a struct is picking one of these, so a projection of `s.a` hands back
676 /// a vector that already exists rather than reading a row at a time and rebuilding a column.
677 #[must_use]
678 pub fn struct_parts(&self) -> Option<&[Arc<Self>]> {
679 match &self.body {
680 Body::Fields { children } => Some(children),
681 _ => None,
682 }
683 }
684
685 /// A map vector, built from one [`Value::Map`] per row.
686 ///
687 /// A map is a list whose child is a two field struct of keys and values, which is what DuckDB
688 /// stores and what Arrow and Parquet store, so this is the list builder and the struct builder
689 /// composed rather than a third layout. The keys of every row go into one column end to end, the
690 /// values into another beside it, and a row is a start and a length into the pair.
691 ///
692 /// The field names are [`MAP_KEY`] and [`MAP_VALUE`] because those are the names DuckDB gives them
693 /// and the names anything reading a Parquet map field will expect to find.
694 ///
695 /// A null row and an empty map are both an entry of length zero, told apart by the validity mask,
696 /// for the reason written on [`Body::Nested`].
697 fn map_from_values(key: LogicalType, value: LogicalType, values: &[Value]) -> Result<Self> {
698 let mut keys = Vec::new();
699 let mut held = Vec::new();
700 let mut entries = Vec::with_capacity(values.len());
701 for row in values {
702 let start = u32::try_from(keys.len())
703 .map_err(|_| Error::internal("a map column with more than u32 entries in it"))?;
704 match row {
705 Value::Null => entries.push((start, 0)),
706 Value::Map { entries: pairs, .. } => {
707 let len = u32::try_from(pairs.len())
708 .map_err(|_| Error::internal("a map with more than u32 entries"))?;
709 for (one, other) in pairs {
710 keys.push(one.clone());
711 held.push(other.clone());
712 }
713 entries.push((start, len));
714 }
715 other => {
716 return Err(Error::internal(format!(
717 "{other:?} does not belong in a map vector"
718 )));
719 }
720 }
721 }
722 // The two types are the column's rather than any one row's, for the reason the list builder
723 // takes the element type from the column: a row that is the empty map carries whatever it was
724 // built as being empty of, and the column is not entitled to take its type from that.
725 let child = Self::structure(vec![
726 (MAP_KEY.to_string(), Self::from_values(key, &keys)?),
727 (MAP_VALUE.to_string(), Self::from_values(value, &held)?),
728 ])?;
729 let ty = LogicalType::map(
730 fields_of(&child.ty)[0].ty.clone(),
731 fields_of(&child.ty)[1].ty.clone(),
732 );
733 let validity = Validity::from_iter(values.len(), |index| !values[index].is_null());
734 Ok(Self {
735 ty,
736 len: values.len(),
737 validity,
738 body: Body::Nested { entries, child: Arc::new(child) },
739 })
740 }
741
742 /// A map vector over a pair of columns that already exist, one entry per row.
743 ///
744 /// What a scan and a map returning kernel build. The keys and the values are two columns of the
745 /// same length, and each row of the map is the same range of both. Every row is valid, since a
746 /// caller with nulls to record adds them with [`Self::with_validity`].
747 ///
748 /// # Errors
749 ///
750 /// If the two columns are different lengths, or if an entry runs past the end of them.
751 pub fn map(entries: Vec<(u32, u32)>, keys: Vector, values: Vector) -> Result<Self> {
752 let key = keys.ty.clone();
753 let value = values.ty.clone();
754 let child =
755 Self::structure(vec![(MAP_KEY.to_string(), keys), (MAP_VALUE.to_string(), values)])?;
756 let mut vector = Self::list(entries, child)?;
757 vector.ty = LogicalType::map(key, value);
758 Ok(vector)
759 }
760
761 /// The entries and the two columns, for a map vector, and `None` for anything else.
762 ///
763 /// Reaches through the struct child that a map is stored as, so that a kernel over a map column
764 /// reads the keys and the values as the two columns they are rather than having to know that the
765 /// pair is spelled as a struct underneath.
766 #[must_use]
767 pub fn map_parts(&self) -> Option<MapParts<'_>> {
768 if !matches!(self.ty, LogicalType::Map(_, _)) {
769 return None;
770 }
771 let (entries, child) = self.list_parts()?;
772 let [keys, values] = child.struct_parts()? else { return None };
773 Some((entries, keys, values))
774 }
775
776 /// The entries and the child, for a list vector, and `None` for any other form.
777 ///
778 /// The accessor a kernel over a list column reads, for the reason
779 /// [`Self::dictionary_parts`] exists: `unnest` over 1024 rows wants the child once and the
780 /// entries once, and reading it through [`Self::value_at`] would build a `Value::List` per row
781 /// and then throw every one of them away.
782 ///
783 /// A map answers here as well, with the struct child it is stored as, because this is a question
784 /// about the layout and a map's layout is a list's. A caller that wants the keys and the values as
785 /// two columns wants [`Self::map_parts`], which reaches through that child.
786 #[must_use]
787 pub fn list_parts(&self) -> Option<(&[(u32, u32)], &Self)> {
788 match &self.body {
789 Body::Nested { entries, child } => Some((entries, child)),
790 _ => None,
791 }
792 }
793
794 /// A vector of `len` copies of one value.
795 ///
796 /// Costs one value regardless of the length, which is what makes a literal in a predicate free
797 /// and what makes a projection of a constant free.
798 #[must_use]
799 pub fn constant(ty: LogicalType, value: Value, len: usize) -> Self {
800 let validity = if value.is_null() { Validity::AllInvalid } else { Validity::AllValid };
801 Self { ty, len, validity, body: Body::Constant(Box::new(value)) }
802 }
803
804 /// A vector of `len` values starting at `start` and stepping by `step`.
805 ///
806 /// This is what a row identifier column is, and it costs sixteen bytes rather than eight
807 /// kilobytes. A scan that produces row ids for a later fetch produces one of these.
808 #[must_use]
809 pub fn sequence(start: i64, step: i64, len: usize) -> Self {
810 Self {
811 ty: LogicalType::BigInt,
812 len,
813 validity: Validity::AllValid,
814 body: Body::Sequence { start, step },
815 }
816 }
817
818 /// A vector of codes into a smaller vector of distinct values.
819 ///
820 /// The form the whole M3 thesis rests on. A dictionary vector handed to a group by is an
821 /// integer column, and an aggregate over one is an aggregate over integers no matter what the
822 /// logical type says.
823 ///
824 /// A dictionary over a dictionary is composed into one level here rather than left as two, so
825 /// the form has a depth of one always and a kernel that reads [`Self::dictionary_parts`] is
826 /// reading the values rather than another layer of codes. Two filters over the same chunk build
827 /// the second case and four conjuncts pushed down separately build four of it.
828 ///
829 /// The cost of leaving them stacked turned out to be a cliff rather than a slope. Every loop in
830 /// `rudb-kernels` reaches for the values behind the codes with [`Self::data`], a dictionary
831 /// pointing at a dictionary has no data to hand back, so the second level does not make the
832 /// kernels slower, it turns them off and drops the work onto the row at a time path that exists
833 /// to be correct rather than fast. Measured on server3 over a chunk of two numeric columns and a
834 /// consumer of two vectorized passes, one level reads at 3.5 nanoseconds a row and two levels at
835 /// 104, and the third and fourth levels cost almost nothing more because the first one had
836 /// already given up everything there was to give. Composing is one pass over the outer codes,
837 /// which the range check above is already making.
838 ///
839 /// The one dictionary that is not composed past is one carrying a validity of its own. A
840 /// dictionary is built all valid and only [`Self::with_validity`] can change that, so such a
841 /// vector is saying that its nulls are at this level rather than in the values it points at, and
842 /// composing past it would drop them.
843 ///
844 /// # Errors
845 ///
846 /// If any code is past the end of the value vector.
847 pub fn dictionary(codes: Vec<u32>, values: Vector) -> Result<Self> {
848 Self::dictionary_over(codes, Arc::new(values))
849 }
850
851 /// The same, over a set of values somebody else is holding too.
852 ///
853 /// The body holds its values in an `Arc` either way, so a caller that already has one has
854 /// nothing to hand over but a pointer. The caller this is for is a Parquet chunk: one dictionary
855 /// page serves every data page of the chunk, and going through [`Self::dictionary`] meant
856 /// copying the whole dictionary into each page's vector on the way to putting it in an `Arc`
857 /// that then had a single holder. On a ClickBench scan that copy was sixteen percent of the
858 /// instructions the query ran.
859 ///
860 /// Composing a dictionary over a dictionary still needs the values by value, so that case takes
861 /// them out of the handle and copies if anybody else is still reading them. Nothing that shares
862 /// a dictionary builds a stacked one, so the two paths do not meet in practice.
863 ///
864 /// The range check takes the highest code rather than stopping at the first bad one. Stopping
865 /// early sounds cheaper and is not, because a loop that can exit anywhere cannot be vectorized
866 /// and a running maximum can, and the only run that would have exited early is the one about to
867 /// fail the query anyway. Every other run reads the whole of `codes` either way. It was 5.2
868 /// percent of a ClickBench scan as a `find`.
869 ///
870 /// # Errors
871 ///
872 /// If any code is past the end of the value vector.
873 pub fn dictionary_over(codes: Vec<u32>, values: Arc<Vector>) -> Result<Self> {
874 let highest = codes.iter().copied().fold(0, u32::max);
875 if !codes.is_empty() && highest as usize >= values.len() {
876 return Err(Error::internal(format!(
877 "dictionary code {highest} is past the end of a {} value dictionary",
878 values.len()
879 )));
880 }
881 let stacked = matches!(values.validity, Validity::AllValid)
882 && matches!(values.body, Body::Dictionary { .. });
883 let (codes, values) = if stacked {
884 let (codes, values) = compose(codes, Arc::unwrap_or_clone(values));
885 (codes, Arc::new(values))
886 } else {
887 (codes, values)
888 };
889 Ok(Self {
890 ty: values.ty.clone(),
891 len: codes.len(),
892 validity: Validity::AllValid,
893 body: Body::Dictionary { codes, values, stable: false },
894 })
895 }
896
897 /// A dictionary whose codes keep the same meaning across every page of its source.
898 pub fn stable_dictionary(codes: Vec<u32>, values: Arc<Vector>) -> Result<Self> {
899 let mut vector = Self::dictionary_over(codes, values)?;
900 if let Body::Dictionary { stable, .. } = &mut vector.body {
901 *stable = true;
902 }
903 Ok(vector)
904 }
905
906 /// A stable dictionary whose caller already found the largest code while decoding it.
907 pub fn stable_dictionary_validated(
908 codes: Vec<u32>,
909 values: Arc<Vector>,
910 highest: Option<u32>,
911 ) -> Result<Self> {
912 if highest.is_some_and(|code| code as usize >= values.len()) {
913 return Err(Error::internal("a stable dictionary code is past its value dictionary"));
914 }
915 Ok(Self {
916 ty: values.ty.clone(),
917 len: codes.len(),
918 validity: Validity::AllValid,
919 body: Body::Dictionary { codes, values, stable: true },
920 })
921 }
922
923 /// A vector of runs, one value each, with the row each run ends at.
924 ///
925 /// `ends` is exclusive and strictly increasing, so run `i` covers the rows from `ends[i - 1]` to
926 /// `ends[i]` and run zero starts at nothing. The length of the vector is the last end.
927 ///
928 /// The depth is one, the same way a dictionary's is, and for a sharper reason. Every kernel that
929 /// wants runs wants the value of a run without another search, and a run length vector over a
930 /// run length vector turns one search into two and then into three. Rather than compose, this
931 /// refuses: nothing in the engine builds a stacked one, because [`Self::run_encoded`] only ever
932 /// reads a flat body, so a stacked one is a caller doing something by hand and the useful answer
933 /// is to say so rather than to quietly do a pass of work they did not ask for.
934 ///
935 /// A run over a dictionary is fine and is not that case. The two forms answer different
936 /// questions and a column that is both clustered and low cardinality genuinely wants both.
937 ///
938 /// # Errors
939 ///
940 /// If there is not exactly one value per run, if the ends do not increase, or if the values are
941 /// themselves run length encoded.
942 pub fn runs(ends: Vec<u32>, values: Vector) -> Result<Self> {
943 if matches!(values.body, Body::Runs { .. }) {
944 return Err(Error::internal("runs of runs, which is two searches to read one row"));
945 }
946 if ends.len() != values.len() {
947 return Err(Error::internal(format!(
948 "{} runs and {} values to put in them",
949 ends.len(),
950 values.len()
951 )));
952 }
953 if ends.windows(2).any(|pair| pair[0] >= pair[1]) || ends.first() == Some(&0) {
954 return Err(Error::internal("run ends that do not increase"));
955 }
956 let len = ends.last().copied().unwrap_or(0) as usize;
957 Ok(Self {
958 ty: values.ty.clone(),
959 len,
960 validity: Validity::AllValid,
961 body: Body::Runs { ends, values: Arc::new(values) },
962 })
963 }
964
965 /// The same values as runs, when there are few enough runs for that to be smaller.
966 ///
967 /// Costs one pass over the column to find out, which is why this is a call somebody makes rather
968 /// than something a constructor does. The decision is the same arithmetic every time: a row in
969 /// flat form costs one value, a run costs one value plus the four bytes of its end, so runs are
970 /// smaller once there are fewer than about half as many runs as rows, and the narrower the
971 /// column the more runs it takes. `RUNS_PAY_AT` is that ratio, written down rather than spelt
972 /// into an `if`, because it is the number a sweep will want to move.
973 ///
974 /// Only a flat body is looked at. A constant and a sequence are already one value and two
975 /// numbers, so there is nothing to win, and a dictionary that is also clustered is a real case
976 /// that wants its codes run length encoded rather than its values, which is a different function
977 /// and not this one.
978 ///
979 /// Two adjacent nulls are one run. Two adjacent equal values with a null between them are three,
980 /// because the null is a value of the column as far as anything reading it is concerned.
981 ///
982 /// # Errors
983 ///
984 /// From the gather this does at the end, and nowhere else. A body that is not flat comes back
985 /// unchanged rather than as an error, so a nested vector never reaches the part that can fail.
986 pub fn run_encoded(&self) -> Result<Self> {
987 let Body::Flat(data) = &self.body else {
988 return Ok(self.clone());
989 };
990 let ends = boundaries(data, &self.validity, self.len);
991 if ends.len().saturating_mul(RUNS_PAY_AT) >= self.len {
992 return Ok(self.clone());
993 }
994 let starts: Vec<u32> =
995 std::iter::once(0).chain(ends.iter().copied()).take(ends.len()).collect();
996 Self::runs(ends, self.gather(&starts)?)
997 }
998
999 /// A vector of `len` integers packed `width` bits each, every one an offset from `base`.
1000 ///
1001 /// The way in for a reader that already has the packed bits, which is what a column file holds
1002 /// and what a network frame carries. Nothing unpacks on the way in, so a scan of a packed column
1003 /// hands the bits straight to the chunk and the cost of the form is paid by whoever reads a
1004 /// value rather than by the scan.
1005 ///
1006 /// The range check is on the two ends rather than on every code, which is the whole check. A
1007 /// code is between zero and `2^width - 1` by construction, so if `base` and `base + 2^width - 1`
1008 /// both fit the column's layout then every value does, and that is two comparisons instead of
1009 /// one per row.
1010 ///
1011 /// # Errors
1012 ///
1013 /// If the type is not one of the integer layouts, if the width is not between one and
1014 /// [`PACKED_WIDTH_MAX`], if there are not enough words for the length, or if either end of the
1015 /// range would not fit the type.
1016 pub fn packed(
1017 ty: LogicalType,
1018 words: Vec<u64>,
1019 width: u32,
1020 base: i128,
1021 len: usize,
1022 ) -> Result<Self> {
1023 let Some((low, high)) = layout_range(&ty) else {
1024 return Err(Error::internal(format!("a {ty} vector has no integer layout to pack")));
1025 };
1026 if width == 0 || width > PACKED_WIDTH_MAX {
1027 return Err(Error::internal(format!(
1028 "a packed width of {width}, which is outside 1 to {PACKED_WIDTH_MAX}"
1029 )));
1030 }
1031 let needed = words_for(len, width);
1032 if words.len() < needed {
1033 return Err(Error::internal(format!(
1034 "{} words for {len} values of {width} bits, which needs {needed}",
1035 words.len()
1036 )));
1037 }
1038 let top = base + i128::from(u64::MAX >> (64 - width));
1039 if base < low || top > high {
1040 return Err(Error::internal(format!(
1041 "packed values from {base} to {top}, which a {ty} cannot hold"
1042 )));
1043 }
1044 Ok(Self {
1045 ty,
1046 len,
1047 validity: Validity::AllValid,
1048 body: Body::Packed { words: Arc::new(words), width, base, offset: 0 },
1049 })
1050 }
1051
1052 /// The same values bit packed, when the range of the column makes that smaller.
1053 ///
1054 /// Costs one pass to find the range and one to write the bits, which is why this is a call
1055 /// somebody makes rather than something a constructor does. It is the counterpart of
1056 /// [`Self::run_encoded`] and the decision has the same shape: a row flat costs the width of its
1057 /// layout, a row packed costs the bits the column's range needs, and the form is worth having
1058 /// only when the second is a good deal smaller than the first. [`PACKING_PAYS_AT`] is that
1059 /// ratio, written down rather than spelt into an `if`, because it is the number a sweep will
1060 /// want to move.
1061 ///
1062 /// Only a flat integer body is looked at. A constant and a sequence are already smaller than any
1063 /// packing of them, a dictionary's codes are the thing that would want packing rather than its
1064 /// values, and a float has no range to pack into since the bits of an `f64` are not an integer
1065 /// that arithmetic on the column agrees with.
1066 ///
1067 /// The range is taken over every slot including the null ones, which hold a zero. A column of
1068 /// large values with one null in it therefore packs a range that reaches down to zero and comes
1069 /// out wider than it needed to be. The alternative is a pass that consults the validity per slot
1070 /// to find the range and a second rule for what to write into a null slot, and this form exists
1071 /// to make reads cheap rather than to squeeze the last bit out of a sparse column.
1072 ///
1073 /// A column whose values are all the same packs to nothing at all, and rather than invent a zero
1074 /// bit code this declines and leaves it to [`Self::run_encoded`], which turns that column into
1075 /// one run and is smaller than any packing of it.
1076 ///
1077 /// # Errors
1078 ///
1079 /// If the packed bits and the length disagree, which would be a bug here rather than a caller
1080 /// doing something wrong.
1081 pub fn bit_packed(&self) -> Result<Self> {
1082 let Body::Flat(data) = &self.body else {
1083 return Ok(self.clone());
1084 };
1085 let Some((low, high)) = span_of(data, self.len) else {
1086 return Ok(self.clone());
1087 };
1088 let Some(range) = high.checked_sub(low).and_then(|range| u64::try_from(range).ok()) else {
1089 return Ok(self.clone());
1090 };
1091 let width = u64::BITS - range.leading_zeros();
1092 if width == 0 || width > PACKED_WIDTH_MAX {
1093 return Ok(self.clone());
1094 }
1095 if words_for(self.len, width) * size_of::<u64>() * PACKING_PAYS_AT > data.footprint() {
1096 return Ok(self.clone());
1097 }
1098 let words = pack(data, self.len, low, width);
1099 let packed = Self::packed(self.ty.clone(), words, width, low, self.len)?;
1100 Ok(packed.with_validity(self.validity.clone()))
1101 }
1102
1103 /// A vector of string views over an arena somebody else is holding too.
1104 ///
1105 /// The way in for a scan that has a page of strings and wants several chunks over it. Each chunk
1106 /// gets its own run of views and they all share the one arena, so the bytes are read where the
1107 /// page put them and nothing copies them.
1108 ///
1109 /// Every view is checked against the arena here rather than when a row is read. That is a pass
1110 /// over the views at construction, which is the same pass the caller just did to build them, and
1111 /// what it buys is that a row of this form cannot resolve to bytes that are not there. The check
1112 /// is on the offsets and not on the bytes, so it says nothing about whether the payload is text,
1113 /// which is the same promise a `BLOB` column makes.
1114 ///
1115 /// # Errors
1116 ///
1117 /// If the type is not one stored as views, or if a view points past the end of the arena.
1118 pub fn string_views(
1119 ty: LogicalType,
1120 views: Vec<StringView>,
1121 arena: Arc<Buffer<u8>>,
1122 ) -> Result<Self> {
1123 if ty.physical() != rudb_common::PhysicalType::Varlen {
1124 return Err(Error::internal(format!("a {ty} vector cannot hold string views")));
1125 }
1126 if views.iter().any(|view| view.bytes_in(&arena).is_none()) {
1127 return Err(Error::internal("a string view points past the end of its arena"));
1128 }
1129 let len = views.len();
1130 Ok(Self { ty, len, validity: Validity::AllValid, body: Body::Views { views, arena } })
1131 }
1132
1133 /// A text vector whose values remain in a storage source until they are read.
1134 pub fn external_text(ty: LogicalType, source: Arc<dyn TextSource>) -> Result<Self> {
1135 if ty.physical() != rudb_common::PhysicalType::Varlen {
1136 return Err(Error::internal(format!(
1137 "a {ty} vector cannot use an external text source"
1138 )));
1139 }
1140 let len = source.len();
1141 Ok(Self { ty, len, validity: Validity::AllValid, body: Body::ExternalText { source } })
1142 }
1143
1144 /// The same strings, in a form where a cut of them does not copy the bytes.
1145 ///
1146 /// The counterpart of [`Self::run_encoded`] and [`Self::bit_packed`] for a string column, and
1147 /// the only one of the three that takes `self` by value. It has to: what it does is move the
1148 /// arena into an `Arc` so nothing copies it again, and a version taking `&self` would start by
1149 /// copying the arena once to have one to move.
1150 ///
1151 /// Anything that is not a flat string column comes back as it was, which includes a column that
1152 /// is already in this form.
1153 ///
1154 /// # Errors
1155 ///
1156 /// Nothing here fails today. The result is a `Result` because the check inside
1157 /// [`Self::string_views`] is worth running on the views this builds rather than trusting that
1158 /// this function built them right.
1159 pub fn shared_text(self) -> Result<Self> {
1160 let Body::Flat(Data::Varlen(column)) = self.body else {
1161 return Ok(self);
1162 };
1163 let (views, arena) = column.into_parts();
1164 let shared = Self::string_views(self.ty, views, Arc::new(arena))?;
1165 Ok(shared.with_validity(self.validity))
1166 }
1167
1168 /// A vector of FSST codes against a table somebody else trained.
1169 ///
1170 /// The way in for a reader that has a page of compressed strings and the table that goes with
1171 /// it. The codes are not copied and the table is not retrained, so laying several chunks over
1172 /// one page costs the spans and nothing else.
1173 ///
1174 /// # Errors
1175 ///
1176 /// If the type is not one stored as text, or if a span runs past the end of the codes.
1177 pub fn coded(
1178 ty: LogicalType,
1179 codes: Arc<Vec<u8>>,
1180 spans: Vec<(u32, u32)>,
1181 table: Arc<SymbolTable>,
1182 ) -> Result<Self> {
1183 if ty.physical() != rudb_common::PhysicalType::Varlen {
1184 return Err(Error::internal(format!("a {ty} vector cannot hold FSST codes")));
1185 }
1186 let end = u32::try_from(codes.len()).unwrap_or(u32::MAX);
1187 if spans.iter().any(|&(from, to)| from > to || to > end) {
1188 return Err(Error::internal("an FSST span runs past the end of the codes"));
1189 }
1190 let len = spans.len();
1191 Ok(Self {
1192 ty,
1193 len,
1194 validity: Validity::AllValid,
1195 body: Body::Coded { codes, spans, table },
1196 })
1197 }
1198
1199 /// The same strings, compressed against a table trained on them.
1200 ///
1201 /// The counterpart of [`Self::run_encoded`] and [`Self::bit_packed`] for a text column, and it
1202 /// takes `self` by value for the reason [`Self::shared_text`] does.
1203 ///
1204 /// The table is trained on every row rather than on a sample. A vector is at most 1024 rows, so
1205 /// the sample would be most of the column anyway, and the systematic sampling
1206 /// `spec/06-compression.md` section 6.3 asks for is a decision about a page and belongs to
1207 /// whoever is holding one.
1208 ///
1209 /// It declines unless the codes are at most half the bytes the strings are. FSST gets about that
1210 /// on text and rather less on anything already short or already random, and below that the
1211 /// decompression per row read is not bought back. A column it declines on comes back as it was.
1212 ///
1213 /// # Errors
1214 ///
1215 /// Nothing here fails today. The result is a `Result` because the checks inside [`Self::coded`]
1216 /// are worth running on what this builds rather than trusting that this built it right.
1217 pub fn compressed(self) -> Result<Self> {
1218 let Body::Flat(Data::Varlen(column)) = &self.body else {
1219 return Ok(self);
1220 };
1221 let rows: Vec<&[u8]> = (0..self.len).filter_map(|row| column.bytes(row)).collect();
1222 if rows.len() != self.len {
1223 return Ok(self);
1224 }
1225 let plain: usize = rows.iter().map(|row| row.len()).sum();
1226 let table = SymbolTable::train(&rows);
1227 let mut codes = Vec::with_capacity(plain);
1228 let mut spans = Vec::with_capacity(self.len);
1229 for row in &rows {
1230 let from = u32::try_from(codes.len()).unwrap_or(u32::MAX);
1231 table.compress(row, &mut codes);
1232 spans.push((from, u32::try_from(codes.len()).unwrap_or(u32::MAX)));
1233 }
1234 if codes.len() * FSST_PAYS_AT > plain {
1235 return Ok(self);
1236 }
1237 let coded = Self::coded(self.ty.clone(), Arc::new(codes), spans, Arc::new(table))?;
1238 Ok(coded.with_validity(self.validity.clone()))
1239 }
1240
1241 /// The same vector with a different validity.
1242 #[must_use]
1243 pub fn with_validity(mut self, validity: Validity) -> Self {
1244 self.validity = validity;
1245 self
1246 }
1247
1248 /// What kind of values these are.
1249 #[must_use]
1250 pub fn logical_type(&self) -> &LogicalType {
1251 &self.ty
1252 }
1253
1254 /// How many values there are.
1255 #[must_use]
1256 pub fn len(&self) -> usize {
1257 self.len
1258 }
1259
1260 /// Whether there are no values.
1261 #[must_use]
1262 pub fn is_empty(&self) -> bool {
1263 self.len == 0
1264 }
1265
1266 /// How many bytes of memory this vector is holding.
1267 ///
1268 /// What the memory limit charges for it. A constant and a sequence hold one value and two
1269 /// numbers however long they are, which is the point of both forms, so the number here is the
1270 /// form's cost and not the column's width times its length.
1271 ///
1272 /// A dictionary counts its values in full, and two vectors sharing one dictionary each report
1273 /// all of it. That over counts, deliberately: working out that two operators are looking at the
1274 /// same `Arc` means threading identity through the accounting, and a limit that over counts
1275 /// refuses a query that would have fit while a limit that under counts lets one through that
1276 /// does not. The first is a worse answer to give and the second is a worse thing to be.
1277 #[must_use]
1278 pub fn footprint(&self) -> usize {
1279 let body = match &self.body {
1280 Body::Flat(data) => data.footprint(),
1281 Body::Constant(value) => value.footprint(),
1282 Body::Sequence { .. } => 0,
1283 Body::Dictionary { codes, values, .. } => {
1284 codes.capacity() * size_of::<u32>() + values.footprint()
1285 }
1286 Body::Packed { words, .. } => words.capacity() * size_of::<u64>(),
1287 // The arena counts in full in every vector sharing it, for the reason a shared
1288 // dictionary does: over counting refuses a query that would have fit and under counting
1289 // admits one that does not, and the first is the better way to be wrong.
1290 Body::Views { views, arena } => {
1291 views.capacity() * size_of::<StringView>() + arena.footprint()
1292 }
1293 Body::ExternalText { source } => source.footprint(),
1294 // The table counts in full in every vector sharing it, the way a shared arena and a
1295 // shared dictionary do. It is the largest of the three and the most shared of them, so
1296 // this is the one place the over counting is worth saying out loud: a page of a hundred
1297 // chunks reports its table a hundred times.
1298 Body::Coded { codes, spans, table } => {
1299 codes.capacity() + spans.capacity() * size_of::<(u32, u32)>() + table.footprint()
1300 }
1301 Body::Runs { ends, values } => ends.capacity() * size_of::<u32>() + values.footprint(),
1302 // The child counts in full in every vector sharing it, the way a shared dictionary and a
1303 // shared arena do, and for the same reason.
1304 Body::Nested { entries, child } => {
1305 entries.capacity() * size_of::<(u32, u32)>() + child.footprint()
1306 }
1307 // Every child in full, the way the list child counts. A struct is as wide as its fields
1308 // are, so this is the one body whose cost is a sum over children rather than one number,
1309 // and a struct of a hundred narrow fields costs what the hundred columns cost.
1310 Body::Fields { children } => {
1311 children.capacity() * size_of::<Arc<Self>>()
1312 + children.iter().map(|child| child.footprint()).sum::<usize>()
1313 }
1314 };
1315 size_of::<Self>() + self.validity.footprint() + body
1316 }
1317
1318 /// Which of the values are not null, at this level and no deeper.
1319 ///
1320 /// This is not the same question as [`Self::is_null_at`] and the difference has already cost
1321 /// one wrong answer. A dictionary and a run length vector keep their nulls in the values they
1322 /// point at rather than in a mask of their own, so both are built with every row marked present
1323 /// here and a row whose value is null reads as valid. A caller that wants to know whether a row
1324 /// is null wants the other one. A caller that wants the mask of a flat column, to copy it or to
1325 /// count it, wants this one.
1326 #[must_use]
1327 pub fn validity(&self) -> &Validity {
1328 &self.validity
1329 }
1330
1331 /// Whether the row at `index` is null, in whichever form the vector is in.
1332 ///
1333 /// Reads through a dictionary or a run to the value it stands for, which is where those two
1334 /// forms keep their nulls, and answers from the mask for every other form. A row past the end
1335 /// is null, the same answer [`Self::value_at`] gives it.
1336 #[must_use]
1337 pub fn is_null_at(&self, index: usize) -> bool {
1338 if index >= self.len || !self.validity.is_valid(index) {
1339 return true;
1340 }
1341 match &self.body {
1342 Body::Dictionary { codes, values, .. } => match codes.get(index) {
1343 Some(&code) => values.is_null_at(code as usize),
1344 None => true,
1345 },
1346 Body::Runs { ends, values } => match run_holding(ends, index) {
1347 Some(run) => values.is_null_at(run),
1348 None => true,
1349 },
1350 _ => false,
1351 }
1352 }
1353
1354 /// Which physical form this vector is in.
1355 #[must_use]
1356 pub fn form(&self) -> Form {
1357 match self.body {
1358 Body::Flat(_) => Form::Flat,
1359 Body::Constant(_) => Form::Constant,
1360 Body::Sequence { .. } => Form::Sequence,
1361 Body::Dictionary { .. } => Form::Dictionary,
1362 Body::Packed { .. } => Form::BitPacked,
1363 Body::Views { .. } => Form::StringView,
1364 Body::ExternalText { .. } => Form::StringView,
1365 Body::Coded { .. } => Form::Fsst,
1366 Body::Runs { .. } => Form::Rle,
1367 Body::Nested { .. } => Form::List,
1368 Body::Fields { .. } => Form::Struct,
1369 }
1370 }
1371
1372 /// The data, for a flat vector, and `None` for any other form.
1373 ///
1374 /// A kernel that wants a slice asks for it and takes the flat path if it gets one. A kernel
1375 /// that can do better on a constant or a dictionary checks [`Self::form`] first.
1376 #[must_use]
1377 pub fn data(&self) -> Option<&Data> {
1378 match &self.body {
1379 Body::Flat(data) => Some(data),
1380 _ => None,
1381 }
1382 }
1383
1384 /// The one value, for a constant vector, and `None` for any other form.
1385 ///
1386 /// A kernel comparing a column against a literal wants the literal once rather than 1024
1387 /// times, and [`Self::value_at`] on a constant clones it on every call because it has to be
1388 /// able to hand back a `Value` for any form. This is the accessor that lets the specialized
1389 /// path hoist the clone out of the loop.
1390 #[must_use]
1391 pub fn constant_value(&self) -> Option<&Value> {
1392 match &self.body {
1393 Body::Constant(value) => Some(value.as_ref()),
1394 _ => None,
1395 }
1396 }
1397
1398 /// The codes and the values, for a dictionary vector, and `None` for any other form.
1399 ///
1400 /// The reason a kernel needs this rather than reading the dictionary through
1401 /// [`Self::value_at`] is the entire argument for the form existing. A filter against a
1402 /// dictionary column of 1024 rows and 40 distinct values is 40 comparisons and 1024 lookups,
1403 /// not 1024 comparisons, and there is no way to write that loop without seeing the codes.
1404 ///
1405 /// Note what the validity of the returned vector means. A dictionary keeps its nulls in the
1406 /// vector it points at, and the dictionary's own validity says nothing about them, so a caller
1407 /// deciding whether row `i` is null has to ask the value vector about `codes[i]` rather than
1408 /// asking this vector about `i`. [`Self::flatten`] has the same note on it for the same
1409 /// reason, because getting this wrong is a null that survives being selected and comes out as
1410 /// a zero.
1411 #[must_use]
1412 pub fn dictionary_parts(&self) -> Option<(&[u32], &Self)> {
1413 match &self.body {
1414 Body::Dictionary { codes, values, .. } => Some((codes, values.as_ref())),
1415 _ => None,
1416 }
1417 }
1418
1419 /// The codes and the shared dictionary handle for a dictionary vector.
1420 ///
1421 /// Storage readers use the identity of this handle to prove that codes from separate pages
1422 /// belong to one table-wide dictionary. Kernels that only read values should continue to use
1423 /// [`Self::dictionary_parts`].
1424 #[must_use]
1425 pub fn shared_dictionary_parts(&self) -> Option<(&[u32], &Arc<Self>)> {
1426 match &self.body {
1427 Body::Dictionary { codes, values, .. } => Some((codes, values)),
1428 _ => None,
1429 }
1430 }
1431
1432 /// Stable codes and their shared values, when storage guarantees one code space across pages.
1433 #[must_use]
1434 pub fn stable_dictionary_parts(&self) -> Option<(&[u32], &Arc<Self>)> {
1435 match &self.body {
1436 Body::Dictionary { codes, values, stable: true } => Some((codes, values)),
1437 _ => None,
1438 }
1439 }
1440
1441 /// The run ends and the run values, for a run length vector, and `None` for any other form.
1442 ///
1443 /// The ends are exclusive and increasing, and there is exactly one value per run, so a kernel
1444 /// that wants to walk this walks the pairs and never asks which run a row is in. That is the
1445 /// whole argument for the form: an aggregate over a clustered column is one multiply per run
1446 /// instead of one add per row, and there is no way to write that loop without seeing the ends.
1447 ///
1448 /// The nulls are in the values, the way a dictionary's are, so a caller deciding whether row `i`
1449 /// is null asks the value vector about the run rather than asking this vector about `i`.
1450 #[must_use]
1451 pub fn run_parts(&self) -> Option<(&[u32], &Self)> {
1452 match &self.body {
1453 Body::Runs { ends, values } => Some((ends, values.as_ref())),
1454 _ => None,
1455 }
1456 }
1457
1458 /// Where each row's value is, for the two forms that keep their values somewhere else.
1459 ///
1460 /// A dictionary and a run length vector are the same shape seen from a kernel: a run of
1461 /// positions and a vector to read them out of. The difference is that a dictionary stores the
1462 /// positions and a run length vector works them out, and a kernel writing `values[at[row]]` does
1463 /// not care which. So every specialization written against [`Self::dictionary_parts`] covers
1464 /// both forms by asking this instead, and the day a third form with an indirection arrives it
1465 /// covers that one too without any of those kernels being reopened.
1466 ///
1467 /// The run length side costs an allocation of one position per row and a pass to fill it, which
1468 /// is the same four bytes a row a dictionary was already carrying and is paid once per kernel
1469 /// call rather than once per row. That is the price of this being one accessor rather than a
1470 /// second arm in eighteen kernels, and it is not the last word: a kernel that wants a run at a
1471 /// time reads [`Self::run_parts`] and pays nothing, which is the specialization this makes it
1472 /// possible to skip writing until a sweep says it is worth it.
1473 #[must_use]
1474 pub fn positions(&self) -> Option<(Cow<'_, [u32]>, &Self)> {
1475 match &self.body {
1476 Body::Dictionary { codes, values, .. } => Some((Cow::Borrowed(codes), values.as_ref())),
1477 Body::Runs { ends, values } => {
1478 let mut at = Vec::with_capacity(self.len);
1479 for (run, &stop) in ends.iter().enumerate() {
1480 let run = u32::try_from(run).unwrap_or(u32::MAX);
1481 at.resize(stop as usize, run);
1482 }
1483 Some((Cow::Owned(at), values.as_ref()))
1484 }
1485 _ => None,
1486 }
1487 }
1488
1489 /// The bits and what they mean, for a bit packed vector, and `None` for any other form.
1490 ///
1491 /// What a kernel needs to stay in code space. A comparison against a literal is the case that
1492 /// pays: `column > 900` over a column packed from a base of 40 is `code > 860`, which is the
1493 /// same shift and mask the read was going to do anyway and no unpacking at all, and a literal
1494 /// outside the packed range answers the whole vector without reading a bit of it. None of that
1495 /// can be written without seeing the width and the base.
1496 #[must_use]
1497 pub fn packed_parts(&self) -> Option<Packed<'_>> {
1498 match &self.body {
1499 Body::Packed { words, width, base, offset } => {
1500 Some(Packed { words, width: *width, base: *base, offset: *offset })
1501 }
1502 _ => None,
1503 }
1504 }
1505
1506 /// The views and the arena, for either form that stores strings, and `None` for the rest.
1507 ///
1508 /// This is to the two string forms what [`Self::positions`] is to the two forms that point
1509 /// somewhere else. A flat varchar column owns its arena and a string view column shares one, and
1510 /// a kernel reading a row wants the view and the bytes either way, so every specialization
1511 /// written against this covers both forms and neither has to be reopened when a third way of
1512 /// holding an arena arrives.
1513 ///
1514 /// The arena is whatever the long strings live in, which for a column over a page is the page,
1515 /// including the parts of it no view points at. Only the views say which bytes are a row.
1516 #[must_use]
1517 pub fn text_parts(&self) -> Option<(&[StringView], &[u8])> {
1518 match &self.body {
1519 Body::Flat(Data::Varlen(column)) => Some((column.views(), column.arena())),
1520 Body::Views { views, arena } => Some((views, arena)),
1521 _ => None,
1522 }
1523 }
1524
1525 /// The codes and the table, for an FSST vector, and `None` for any other form.
1526 ///
1527 /// What a kernel needs to stay in code space. An equality filter is the case that pays, and it
1528 /// pays completely: the literal is compressed once against the same table and after that a row
1529 /// matches exactly when its code bytes match, because compressing is a function and so is
1530 /// decompressing. No row is decompressed at all. An ordering comparison cannot do that, since a
1531 /// symbol code says nothing about where its symbol sorts, so those decompress and say so.
1532 #[must_use]
1533 pub fn coded_parts(&self) -> Option<Coded<'_>> {
1534 match &self.body {
1535 Body::Coded { codes, spans, table } => Some(Coded { codes, spans, table }),
1536 _ => None,
1537 }
1538 }
1539
1540 /// The start and the step, for a sequence vector, and `None` for any other form.
1541 #[must_use]
1542 pub fn sequence_parts(&self) -> Option<(i64, i64)> {
1543 match self.body {
1544 Body::Sequence { start, step } => Some((start, step)),
1545 _ => None,
1546 }
1547 }
1548
1549 /// The value at `index`, as a single value.
1550 ///
1551 /// This is the slow path on purpose. It is what a result set is read out with and what a test
1552 /// asserts on, and an operator that calls it per row is an operator that has already lost the
1553 /// argument the vector interface exists to win.
1554 #[must_use]
1555 pub fn value_at(&self, index: usize) -> Value {
1556 if index >= self.len || !self.validity.is_valid(index) {
1557 return Value::Null;
1558 }
1559 match &self.body {
1560 Body::Constant(value) => value.as_ref().clone(),
1561 Body::Sequence { start, step } => Value::BigInt(start + step * index as i64),
1562 Body::Dictionary { codes, values, .. } => match codes.get(index) {
1563 Some(&code) => values.value_at(code as usize),
1564 None => Value::Null,
1565 },
1566 Body::Runs { ends, values } => match run_holding(ends, index) {
1567 Some(run) => values.value_at(run),
1568 None => Value::Null,
1569 },
1570 // One value unpacked into a run of one, so that what a packed value means is decided in
1571 // the same place a flat one is rather than in a second copy of the type mapping that
1572 // could drift from it. It allocates, which this path is allowed to do and the typed
1573 // unpack in `copied` is not, and it is the reason anything about to read a packed
1574 // column a row at a time should flatten it once instead.
1575 Body::Packed { words, width, base, offset } => {
1576 unpack(&self.ty, words, *offset, *width, *base, &[index])
1577 .map_or(Value::Null, |data| value_from(&self.ty, &data, 0))
1578 }
1579 // The bytes are where the arena has them, and what they are read as is the logical
1580 // type's business, so this hands the row to the same reader a flat column goes through
1581 // rather than deciding here that a `BLOB` is a string.
1582 Body::Views { views, arena } => {
1583 match views.get(index).and_then(|v| v.bytes_in(arena)) {
1584 Some(bytes) => bytes_as(&self.ty, bytes),
1585 None => Value::Null,
1586 }
1587 }
1588 Body::ExternalText { source } => source
1589 .bytes_at(index)
1590 .ok()
1591 .flatten()
1592 .map_or(Value::Null, |bytes| bytes_as(&self.ty, bytes)),
1593 // One row decompressed on its own, which is the property the form is chosen for. It
1594 // allocates, which this path is allowed to do, and it is the reason anything about to
1595 // read a compressed column a row at a time should flatten it once instead.
1596 Body::Coded { codes, spans, table } => {
1597 match spans.get(index).and_then(|&(from, to)| {
1598 let mut out = Vec::new();
1599 table.decompress(codes.get(from as usize..to as usize)?, &mut out).ok()?;
1600 Some(out)
1601 }) {
1602 Some(bytes) => bytes_as(&self.ty, &bytes),
1603 None => Value::Null,
1604 }
1605 }
1606 // A row's elements are read out of the child one at a time, which is the slow path this
1607 // whole function is and is why a kernel over a list column reads `list_parts` instead.
1608 // The element type comes from the child rather than from this vector's type, so a list
1609 // whose child was built narrower than the column claims still hands back what is in it.
1610 //
1611 // A map is stored in this body too, so which value comes out is decided by the logical
1612 // type rather than by the body. That is the one place the composition shows: the bytes of
1613 // a map really are the bytes of a list of two field structs, and the only thing that
1614 // remembers it is a map is the type.
1615 Body::Nested { entries, child } => match (entries.get(index), &self.ty) {
1616 (Some(&(start, len)), LogicalType::Map(key, value)) => {
1617 let pairs = child.struct_parts().unwrap_or_default();
1618 Value::map(
1619 key.as_ref().clone(),
1620 value.as_ref().clone(),
1621 (start..start + len)
1622 .filter_map(|at| {
1623 let [keys, values] = pairs else { return None };
1624 Some((keys.value_at(at as usize), values.value_at(at as usize)))
1625 })
1626 .collect(),
1627 )
1628 }
1629 (Some(&(start, len)), _) => Value::List {
1630 element: child.ty.clone(),
1631 values: (start..start + len).map(|at| child.value_at(at as usize)).collect(),
1632 },
1633 (None, _) => Value::Null,
1634 },
1635 // One value read out of each child at the same position, which is the slow path this whole
1636 // function is and is why a kernel over a struct column reads `struct_parts` instead. The
1637 // names come from this vector's type rather than from the children, because a child is a
1638 // vector and a vector has no name, and the type is where the field order is written down.
1639 Body::Fields { children } => Value::Struct(
1640 fields_of(&self.ty)
1641 .iter()
1642 .zip(children)
1643 .map(|(field, child)| (field.name.clone(), child.value_at(index)))
1644 .collect(),
1645 ),
1646 Body::Flat(data) => value_from(&self.ty, data, index),
1647 }
1648 }
1649
1650 /// The value at `index`, preserving storage read and validation failures.
1651 pub fn try_value_at(&self, index: usize) -> Result<Value> {
1652 if index >= self.len || !self.validity.is_valid(index) {
1653 return Ok(Value::Null);
1654 }
1655 match &self.body {
1656 Body::ExternalText { source } => {
1657 Ok(source.bytes_at(index)?.map_or(Value::Null, |bytes| bytes_as(&self.ty, bytes)))
1658 }
1659 Body::Dictionary { codes, values, .. } => match codes.get(index) {
1660 Some(&code) => values.try_value_at(code as usize),
1661 None => Ok(Value::Null),
1662 },
1663 Body::Runs { ends, values } => match run_holding(ends, index) {
1664 Some(run) => values.try_value_at(run),
1665 None => Ok(Value::Null),
1666 },
1667 Body::Nested { entries, child } => match (entries.get(index), &self.ty) {
1668 (Some(&(start, len)), LogicalType::Map(key, value)) => {
1669 let pairs = child.struct_parts().unwrap_or_default();
1670 let [keys, values] = pairs else { return Ok(Value::Null) };
1671 let mut entries = Vec::with_capacity(len as usize);
1672 for at in start..start + len {
1673 entries.push((
1674 keys.try_value_at(at as usize)?,
1675 values.try_value_at(at as usize)?,
1676 ));
1677 }
1678 Ok(Value::map(key.as_ref().clone(), value.as_ref().clone(), entries))
1679 }
1680 (Some(&(start, len)), _) => {
1681 let mut values = Vec::with_capacity(len as usize);
1682 for at in start..start + len {
1683 values.push(child.try_value_at(at as usize)?);
1684 }
1685 Ok(Value::List { element: child.ty.clone(), values })
1686 }
1687 (None, _) => Ok(Value::Null),
1688 },
1689 Body::Fields { children } => {
1690 let mut values = Vec::with_capacity(children.len());
1691 for (field, child) in fields_of(&self.ty).iter().zip(children) {
1692 values.push((field.name.clone(), child.try_value_at(index)?));
1693 }
1694 Ok(Value::Struct(values))
1695 }
1696 _ => Ok(self.value_at(index)),
1697 }
1698 }
1699
1700 /// The text at `index`, borrowed rather than copied.
1701 ///
1702 /// [`Self::value_at`] on a `VARCHAR` column allocates a `String` per call, and a group by that
1703 /// reads a string column keys on one string per input row. This hands back the bytes where they
1704 /// already are, so a caller with somewhere to put them does not go to the allocator at all.
1705 ///
1706 /// `None` for a null, for an index past the end, for a column that is not `VARCHAR`, and for the
1707 /// constant and sequence forms, whose values are not stored per position. A caller that gets
1708 /// `None` has to fall back to [`Self::value_at`], which is correct for all of those.
1709 #[must_use]
1710 pub fn text_at(&self, index: usize) -> Option<&str> {
1711 if self.ty != LogicalType::Varchar || index >= self.len || !self.validity.is_valid(index) {
1712 return None;
1713 }
1714 match &self.body {
1715 Body::Flat(data) => data.str_at(index),
1716 Body::Dictionary { codes, values, .. } => {
1717 values.text_at(usize::try_from(*codes.get(index)?).ok()?)
1718 }
1719 Body::Runs { ends, values } => values.text_at(run_holding(ends, index)?),
1720 Body::Views { views, arena } => {
1721 std::str::from_utf8(views.get(index)?.bytes_in(arena)?).ok()
1722 }
1723 Body::ExternalText { source } => {
1724 std::str::from_utf8(source.bytes_at(index).ok().flatten()?).ok()
1725 }
1726 _ => None,
1727 }
1728 }
1729
1730 /// The variable length bytes at `index`, borrowed without validating or copying them.
1731 ///
1732 /// String data is validated when it enters a vector. Hashing and equality only need its bytes,
1733 /// so those kernels should not pay for UTF-8 validation again on every read.
1734 #[must_use]
1735 pub fn bytes_at(&self, index: usize) -> Option<&[u8]> {
1736 if index >= self.len || !self.validity.is_valid(index) {
1737 return None;
1738 }
1739 match &self.body {
1740 Body::Constant(value) => match value.as_ref() {
1741 Value::Varchar(text) => Some(text.as_bytes()),
1742 Value::Blob(bytes) => Some(bytes),
1743 _ => None,
1744 },
1745 Body::Dictionary { codes, values, .. } => {
1746 values.bytes_at(usize::try_from(*codes.get(index)?).ok()?)
1747 }
1748 Body::Runs { ends, values } => values.bytes_at(run_holding(ends, index)?),
1749 Body::Views { views, arena } => views.get(index)?.bytes_in(arena),
1750 Body::ExternalText { source } => source.bytes_at(index).ok().flatten(),
1751 Body::Flat(data) => data.bytes_at(index),
1752 // The same `None` [`Self::text_at`] gives, for the same reason. A compressed row is not
1753 // anywhere in its plain bytes, so there is nothing here to hand back a borrow of, and a
1754 // caller that gets `None` goes to `value_at` and gets the row decompressed into a value.
1755 // A list row is `None` for a nearer reason: it is not bytes at all, and a caller wanting
1756 // its elements wants [`Self::list_parts`] rather than a borrow of one row.
1757 Body::Coded { .. }
1758 | Body::Sequence { .. }
1759 | Body::Packed { .. }
1760 | Body::Nested { .. }
1761 | Body::Fields { .. } => None,
1762 }
1763 }
1764
1765 /// Variable length bytes at `index`, preserving storage read and validation failures.
1766 pub fn try_bytes_at(&self, index: usize) -> Result<Option<&[u8]>> {
1767 if index >= self.len || !self.validity.is_valid(index) {
1768 return Ok(None);
1769 }
1770 match &self.body {
1771 Body::Constant(value) => Ok(match value.as_ref() {
1772 Value::Varchar(text) => Some(text.as_bytes()),
1773 Value::Blob(bytes) => Some(bytes.as_slice()),
1774 _ => None,
1775 }),
1776 Body::Dictionary { codes, values, .. } => match codes.get(index) {
1777 Some(&code) => values.try_bytes_at(code as usize),
1778 None => Ok(None),
1779 },
1780 Body::Runs { ends, values } => match run_holding(ends, index) {
1781 Some(run) => values.try_bytes_at(run),
1782 None => Ok(None),
1783 },
1784 Body::Views { views, arena } => {
1785 Ok(views.get(index).and_then(|view| view.bytes_in(arena)))
1786 }
1787 Body::ExternalText { source } => source.bytes_at(index),
1788 Body::Flat(data) => Ok(data.bytes_at(index)),
1789 Body::Coded { .. }
1790 | Body::Sequence { .. }
1791 | Body::Packed { .. }
1792 | Body::Nested { .. }
1793 | Body::Fields { .. } => Ok(None),
1794 }
1795 }
1796
1797 /// Variable length byte count at `index`, preserving storage failures.
1798 pub fn try_bytes_len_at(&self, index: usize) -> Result<Option<usize>> {
1799 if index >= self.len || !self.validity.is_valid(index) {
1800 return Ok(None);
1801 }
1802 match &self.body {
1803 Body::Dictionary { codes, values, .. } => match codes.get(index) {
1804 Some(&code) => values.try_bytes_len_at(code as usize),
1805 None => Ok(None),
1806 },
1807 Body::Runs { ends, values } => match run_holding(ends, index) {
1808 Some(run) => values.try_bytes_len_at(run),
1809 None => Ok(None),
1810 },
1811 Body::ExternalText { source } => source.bytes_len_at(index),
1812 _ => Ok(self.bytes_at(index).map(<[u8]>::len)),
1813 }
1814 }
1815
1816 /// Text at `index`, preserving storage read, validation and UTF-8 failures.
1817 pub fn try_text_at(&self, index: usize) -> Result<Option<&str>> {
1818 if self.ty != LogicalType::Varchar {
1819 return Ok(None);
1820 }
1821 self.try_bytes_at(index)?
1822 .map(|bytes| {
1823 std::str::from_utf8(bytes).map_err(|error| {
1824 Error::conversion(format!("invalid UTF-8 in VARCHAR: {error}"))
1825 })
1826 })
1827 .transpose()
1828 }
1829
1830 /// Read every storage-backed value reachable through this vector.
1831 pub fn validate_external(&self) -> Result<()> {
1832 match &self.body {
1833 Body::ExternalText { source } => {
1834 for index in 0..source.len() {
1835 source.bytes_at(index)?;
1836 }
1837 }
1838 Body::Dictionary { codes, values, .. } => {
1839 for &code in codes {
1840 values.try_bytes_at(code as usize)?;
1841 }
1842 }
1843 Body::Runs { values, .. } => values.validate_external()?,
1844 Body::Nested { child, .. } => child.validate_external()?,
1845 Body::Fields { children } => {
1846 for child in children {
1847 child.validate_external()?;
1848 }
1849 }
1850 _ => {}
1851 }
1852 Ok(())
1853 }
1854
1855 /// The signed integer at `index`, widened, read without building a [`Value`].
1856 ///
1857 /// The integer sibling of [`Self::bytes_at`], and it is here for the same caller. A group by on
1858 /// an integer column compares one key per input row against the group it probed, and doing that
1859 /// through [`Self::value_at`] built and dropped a sixty four byte value a row at a time for a
1860 /// number that was already sitting in the column.
1861 ///
1862 /// Widened to `i128` because that is what [`Data::signed_at`] hands back underneath, and one
1863 /// method that covers every signed width is worth more than five that do not. A caller that
1864 /// wants a narrower type narrows it, which is a range check against a value in a register.
1865 ///
1866 /// The types this answers for are the ones whose flat data is read through `signed_at`, so the
1867 /// five signed integer widths and the decimal, date, time and timestamp types that are stored
1868 /// in them. A decimal answers with its unscaled value, which is the number the column holds.
1869 ///
1870 /// `None` for a null, for an index past the end, for a column of any other type, and for the
1871 /// compressed form. Packed integers stay in code space and answer `base + code` directly. A
1872 /// caller that gets `None` falls back to [`Self::value_at`], which is correct for the remaining
1873 /// forms.
1874 #[must_use]
1875 pub fn signed_at(&self, index: usize) -> Option<i128> {
1876 if index >= self.len || !self.validity.is_valid(index) {
1877 return None;
1878 }
1879 match &self.body {
1880 Body::Flat(data) => data.signed_at(index),
1881 Body::Constant(value) => match value.as_ref() {
1882 Value::TinyInt(x) => Some(i128::from(*x)),
1883 Value::SmallInt(x) => Some(i128::from(*x)),
1884 Value::Integer(x) | Value::Date(x) => Some(i128::from(*x)),
1885 Value::BigInt(x) | Value::Time(x) | Value::Timestamp(x) => Some(i128::from(*x)),
1886 Value::HugeInt(x) | Value::Decimal { unscaled: x, .. } => Some(*x),
1887 _ => None,
1888 },
1889 // The same arithmetic [`Self::value_at`] does on a sequence, so the two agree about a
1890 // sequence that runs off the end of the width it is stored in.
1891 Body::Sequence { start, step } => {
1892 Some(i128::from(start.wrapping_add(step.wrapping_mul(index as i64))))
1893 }
1894 Body::Dictionary { codes, values, .. } => {
1895 values.signed_at(usize::try_from(*codes.get(index)?).ok()?)
1896 }
1897 Body::Runs { ends, values } => values.signed_at(run_holding(ends, index)?),
1898 Body::Packed { words, width, base, offset } => Some(
1899 *base + i128::from(code_at(words, (*offset + index) * *width as usize, *width)),
1900 ),
1901 // The same `None` [`Self::bytes_at`] gives, for the same reason. A compressed row is not
1902 // an integer anywhere until it has been unpacked, and a caller that gets
1903 // `None` goes to `value_at` and gets the row unpacked into a value. A list row is not an
1904 // integer in any form, however many integers are in it, and a struct row is not one even
1905 // when it has exactly one integer field, since the row is the struct and not the field.
1906 Body::Coded { .. }
1907 | Body::Views { .. }
1908 | Body::ExternalText { .. }
1909 | Body::Nested { .. }
1910 | Body::Fields { .. } => None,
1911 }
1912 }
1913
1914 /// Every value in order, as single values.
1915 pub fn iter(&self) -> impl Iterator<Item = Value> + '_ {
1916 (0..self.len).map(|index| self.value_at(index))
1917 }
1918
1919 /// A contiguous run of the values, in the form they are already in.
1920 ///
1921 /// This is the cut [`Self::gather`] cannot do. A gather walks a dictionary to its leaf and
1922 /// copies, so gathering a piece of a dictionary encoded column hands back a flat one, and a
1923 /// caller that only wanted the first thousand rows of a page has silently paid for a copy and
1924 /// thrown the dictionary away. A group by over a dictionary encoded column is the case that
1925 /// cares, and it is most of ClickBench.
1926 ///
1927 /// So each form is cut as itself. A dictionary keeps its dictionary and slices its codes, a
1928 /// sequence stays arithmetic with its start moved along, a constant stays a shorter constant,
1929 /// and a flat body is the one that genuinely has to copy its range.
1930 ///
1931 /// The dictionary itself is shared rather than copied, so a cut is the codes and nothing else.
1932 /// It used to be copied, and on a read of a ClickBench partition that copy was ten percent of
1933 /// the cycles: a page holds one dictionary and is cut into chunk sized pieces, so the whole
1934 /// dictionary was copied once per chunk to be read the same way each time.
1935 ///
1936 /// # Errors
1937 ///
1938 /// If the range runs past the end of the vector, or if the type has no flat layout and the
1939 /// body is one that has to be copied.
1940 pub fn slice(&self, at: usize, len: usize) -> Result<Self> {
1941 let end = at.checked_add(len).ok_or_else(|| Error::internal("a slice that wraps"))?;
1942 if end > self.len {
1943 return Err(Error::internal(format!("rows {at} to {end} of a vector of {}", self.len)));
1944 }
1945 if at == 0 && len == self.len {
1946 return Ok(self.clone());
1947 }
1948 let validity = self.validity.slice(at, len);
1949 let body = match &self.body {
1950 Body::Constant(value) => Body::Constant(value.clone()),
1951 Body::Sequence { start, step } => {
1952 Body::Sequence { start: start + step * at as i64, step: *step }
1953 }
1954 Body::Dictionary { codes, values, stable } => Body::Dictionary {
1955 codes: codes[at..end].to_vec(),
1956 values: Arc::clone(values),
1957 stable: *stable,
1958 },
1959 // The bits are not byte aligned, so a cut either repacks them or moves the row the
1960 // reading starts at. Moving it is one addition and repacking is a pass, and a page is
1961 // cut into chunk sized pieces often enough that the difference is the form.
1962 Body::Packed { words, width, base, offset } => Body::Packed {
1963 words: Arc::clone(words),
1964 width: *width,
1965 base: *base,
1966 offset: offset + at,
1967 },
1968 // The cut a flat string column cannot do. Sixteen bytes a row move and the payload stays
1969 // where the page put it, so taking a chunk out of a column of long strings costs the
1970 // same as taking one out of a column of integers. A flat varchar body copies every byte
1971 // of every long string in the range instead, which is the measurement written down in
1972 // `Chunk::compact`: compaction loses on a varchar column, and this is the half of the
1973 // reason that is about cutting rather than about selecting.
1974 Body::Views { views, arena } => {
1975 Body::Views { views: views[at..end].to_vec(), arena: Arc::clone(arena) }
1976 }
1977 // The spans are absolute positions in the shared codes, so a cut is a run of them and
1978 // nothing has to be rebased. One page of compressed strings, one table, and as many
1979 // chunks over it as the reader wants.
1980 Body::Coded { codes, spans, table } => Body::Coded {
1981 codes: Arc::clone(codes),
1982 spans: spans[at..end].to_vec(),
1983 table: Arc::clone(table),
1984 },
1985 // Only the runs the range touches survive, the first and last of them cut back to where
1986 // the range starts and stops, and every end moved to be relative to the new row zero. A
1987 // cut of a hundred rows out of a column of a hundred million is a handful of runs, which
1988 // is the reason this form is worth cutting as itself rather than copying out.
1989 Body::Runs { ends, values } if len > 0 => {
1990 let first = run_holding(ends, at).unwrap_or(0);
1991 let last = run_holding(ends, end - 1).unwrap_or(first);
1992 let cut: Vec<u32> = ends[first..=last]
1993 .iter()
1994 .map(|&stop| stop.min(end as u32) - at as u32)
1995 .collect();
1996 let values = values.slice(first, last - first + 1)?;
1997 Body::Runs { ends: cut, values: Arc::new(values) }
1998 }
1999 // An empty cut has no run to point at and an empty run length body would be a vector of
2000 // no runs claiming a length, so it comes back as the empty flat vector instead.
2001 Body::Runs { .. } => return self.gather(&[]),
2002 // The entries are absolute positions in the shared child, so a cut is a run of them and
2003 // nothing has to be rebased, the same as a cut of FSST spans. The elements outside the
2004 // range stay in the child unreferenced, which is the trade this form makes: a chunk cut
2005 // out of a page of lists moves eight bytes a row and copies no elements at all.
2006 Body::Nested { entries, child } => {
2007 Body::Nested { entries: entries[at..end].to_vec(), child: Arc::clone(child) }
2008 }
2009 // Every child cut at the same place, because a struct row is one value per field at the
2010 // same position in each and there is no entry standing between the row and the child to
2011 // rewrite instead. So this is the one nested form whose cut is not free, and what it costs
2012 // is whatever cutting each field costs, which for a field of string views is sixteen bytes
2013 // a row and for a field of packed integers is one addition.
2014 Body::Fields { children } => Body::Fields {
2015 children: children
2016 .iter()
2017 .map(|child| child.slice(at, len).map(Arc::new))
2018 .collect::<Result<Vec<_>>>()?,
2019 },
2020 Body::ExternalText { source } => {
2021 let mut out = StringColumn::with_capacity(len);
2022 for index in at..end {
2023 out.push_bytes(source.bytes_at(index)?.unwrap_or_default());
2024 }
2025 Body::Flat(Data::Varlen(out))
2026 }
2027 // The one form with nowhere to point, so its range is copied out. A run and not a
2028 // gather: this used to build a vector of the positions `at..end` and hand it to
2029 // `gather`, which then built a vector of `usize` from it, a vector of `bool` beside
2030 // that, and read the values back one bounds checked index at a time. That is five
2031 // passes and three allocations to say `memcpy`, and on a scan it was the largest thing
2032 // in the program after the aggregation itself, because every chunk of every column of
2033 // every page comes through here.
2034 Body::Flat(data) => Body::Flat(run_of(data, at, end)),
2035 };
2036 Ok(Self { ty: self.ty.clone(), len, validity, body })
2037 }
2038
2039 /// The same values in flat form.
2040 ///
2041 /// Flattening a vector that is already flat is free. Flattening any other form costs a copy,
2042 /// which is exactly why the other forms exist and why nothing on the hot path should call
2043 /// this. It is here for the operators that genuinely cannot do better and for the tests that
2044 /// check the other forms against it.
2045 ///
2046 /// A call that copies counts itself against [`Cause::Flatten`], because a flatten on a hot path
2047 /// is the most expensive thing in this crate and the only way to find one is to have the number.
2048 /// A call on a vector that is already flat does not count, since it neither copies nor gives
2049 /// anything up.
2050 ///
2051 /// # Errors
2052 ///
2053 /// If the type is one there is no vector for yet, which today means `ARRAY` and `UNION`. A `LIST`
2054 /// and a `MAP` flatten to themselves and a `STRUCT` to a struct of flattened fields, since none of
2055 /// the three has a data slice in any form and there is nothing flatter to become.
2056 pub fn flatten(&self) -> Result<Self> {
2057 if let Body::Flat(_) = self.body {
2058 return Ok(self.clone());
2059 }
2060 slow::took(Cause::Flatten);
2061 self.copied((0..self.len).collect(), false)
2062 }
2063
2064 /// The values at the given positions, copied, in a form that does not point back at this vector.
2065 ///
2066 /// This is the copying counterpart to [`Self::dictionary`], and the two are the two halves of
2067 /// the decision `spec/07-execution.md` section 7.1 describes. Which half is right is measured
2068 /// rather than argued, and [`Chunk::compact`](crate::Chunk::compact) is where the measurement
2069 /// is written down.
2070 ///
2071 /// A dictionary chain is walked to its leaf first and the codes composed on the way down, so the
2072 /// copy runs once over the data rather than once per level, and a position that is null at any
2073 /// level comes out null here. The copy is a typed loop per physical layout rather than a `Value`
2074 /// per row, which is the whole point of it and is what [`Self::flatten`] now goes through too.
2075 ///
2076 /// # Errors
2077 ///
2078 /// If the type is one there is no vector for yet, which today means `ARRAY` and `UNION`. A `LIST`
2079 /// and a `MAP` gather by permuting their entries and a `STRUCT` by gathering every field.
2080 pub fn gather(&self, indices: &[u32]) -> Result<Self> {
2081 self.copied(indices.iter().map(|&index| index as usize).collect(), true)
2082 }
2083
2084 /// The copy both [`Self::gather`] and [`Self::flatten`] are.
2085 ///
2086 /// `forms_stay` is the one thing the two want differently. A gather of a constant is a shorter
2087 /// constant and copying it out would be a thousand writes of the same value for nothing, and a
2088 /// gather of string views is a shorter run of views over the same arena rather than a copy of
2089 /// the bytes. Flattening promises flat form to a caller that is about to read the data slice, so
2090 /// for that one both of them have to be written out.
2091 fn copied(&self, at: Vec<usize>, forms_stay: bool) -> Result<Self> {
2092 let rows = at.len();
2093 if forms_stay {
2094 if let Body::Dictionary { codes, values, stable: true } = &self.body {
2095 let validity = Validity::from_iter(rows, |row| {
2096 at.get(row).is_some_and(|&index| index < self.len && !self.is_null_at(index))
2097 });
2098 let gathered =
2099 at.iter().map(|&index| codes.get(index).copied().unwrap_or(0)).collect();
2100 return Ok(
2101 Self::stable_dictionary(gathered, Arc::clone(values))?.with_validity(validity)
2102 );
2103 }
2104 }
2105 let (at, leaf) = self.resolve(at);
2106 let live: Vec<bool> = at.iter().map(|&index| index != NOWHERE).collect();
2107 let validity = Validity::from_run(&live);
2108 let body = match &leaf.body {
2109 // The same gather the arm below is, for a type that has no flat layout to be written out
2110 // into. It goes through the nested builders rather than through a run of data, because they
2111 // are the one place that knows a row of a list column is a range of a child and a row of a
2112 // struct column is one position in each of several, and a second copy of that here would
2113 // be a second thing to keep in step with them.
2114 Body::Constant(value)
2115 if matches!(
2116 self.ty,
2117 LogicalType::List(_) | LogicalType::Struct(_) | LogicalType::Map(_, _)
2118 ) =>
2119 {
2120 if forms_stay && matches!(validity, Validity::AllValid) {
2121 return Ok(Self::constant(self.ty.clone(), value.as_ref().clone(), rows));
2122 }
2123 let rows: Vec<Value> = at
2124 .iter()
2125 .map(
2126 |&index| {
2127 if index == NOWHERE { Value::Null } else { value.as_ref().clone() }
2128 },
2129 )
2130 .collect();
2131 return Self::from_values(self.ty.clone(), &rows);
2132 }
2133 // Every position holds the same value, so the only thing the gather can change is the
2134 // length and which positions are null. A gather with no null in it is still a constant.
2135 Body::Constant(value) => {
2136 if forms_stay && matches!(validity, Validity::AllValid) {
2137 return Ok(Self::constant(self.ty.clone(), value.as_ref().clone(), rows));
2138 }
2139 let mut data = empty_data_for(&self.ty)?;
2140 for &index in &at {
2141 push_value(&mut data, if index == NOWHERE { &Value::Null } else { value })?;
2142 }
2143 Body::Flat(data)
2144 }
2145 // A sequence is arithmetic rather than storage, so the gather is the arithmetic done at
2146 // the positions asked for, and a null writes the zero every other layout writes.
2147 Body::Sequence { start, step } => Body::Flat(Data::Int64(
2148 at.iter()
2149 .map(|&index| if index == NOWHERE { 0 } else { start + step * index as i64 })
2150 .collect(),
2151 )),
2152 // A flat body with no values is the untyped null, so every position asked for is null
2153 // whatever was asked for. Going through the copy would build a run of no values and
2154 // call it `rows` long, which is a vector whose length and data disagree.
2155 Body::Flat(Data::Empty) => {
2156 return Ok(Self::constant(self.ty.clone(), Value::Null, rows));
2157 }
2158 Body::Flat(data) => Body::Flat(copy_of(data, &at)),
2159 // The one form whose copy is arithmetic rather than a move of bytes. It goes through a
2160 // typed loop per layout the way the flat copy does, because the alternative is a `Value`
2161 // per row and this is the path a flatten of a scanned column takes.
2162 Body::Packed { words, width, base, offset } => {
2163 Body::Flat(unpack(&self.ty, words, *offset, *width, *base, &at)?)
2164 }
2165 // A gather keeps the form, which is what makes selecting rows out of a string column
2166 // cost sixteen bytes a row instead of the bytes of the strings. The arena it shares is
2167 // the whole arena and not the part the kept rows point at, so a selection that throws
2168 // most of a page away goes on holding the page. That is the trade the form is: a cut and
2169 // a filter are cheap and the memory comes back when the last vector over the page goes,
2170 // and a caller that wants the bytes narrowed asks for a flatten.
2171 Body::Views { views, arena } if forms_stay => Body::Views {
2172 views: at
2173 .iter()
2174 .map(|&index| views.get(index).copied().unwrap_or_else(StringView::empty))
2175 .collect(),
2176 arena: Arc::clone(arena),
2177 },
2178 // Flattening promises a data slice, so the bytes are copied out into an arena of their
2179 // own and the shared one is let go of. The total is known before any of it is copied,
2180 // the way the flat copy works it out, so the new arena is one allocation.
2181 Body::Views { views, arena } => {
2182 let mut out = StringColumn::with_capacity(at.len());
2183 out.reserve_bytes(
2184 at.iter()
2185 .filter_map(|&index| views.get(index))
2186 .filter(|view| !view.is_inline())
2187 .map(StringView::len)
2188 .sum(),
2189 );
2190 for &index in &at {
2191 let bytes = views.get(index).and_then(|view| view.bytes_in(arena));
2192 out.push_bytes(bytes.unwrap_or_default());
2193 }
2194 Body::Flat(Data::Varlen(out))
2195 }
2196 Body::ExternalText { source } => {
2197 let mut out = StringColumn::with_capacity(at.len());
2198 for &index in &at {
2199 out.push_bytes(source.bytes_at(index)?.unwrap_or_default());
2200 }
2201 Body::Flat(Data::Varlen(out))
2202 }
2203 // A gather keeps the form, because the codes do not move and a span survives being put
2204 // in an order the codes are not in. A position that resolved to nowhere gets the empty
2205 // span, which decompresses to no bytes, which is the zero every other layout writes.
2206 Body::Coded { codes, spans, table } if forms_stay => Body::Coded {
2207 codes: Arc::clone(codes),
2208 spans: at
2209 .iter()
2210 .map(|&index| spans.get(index).copied().unwrap_or((0, 0)))
2211 .collect(),
2212 table: Arc::clone(table),
2213 },
2214 // Flattening decompresses, which is the price of the data slice it promises. The scratch
2215 // buffer is reused across rows, so this is one allocation for the whole column rather
2216 // than one per row the way reading it a value at a time would be.
2217 Body::Coded { codes, spans, table } => {
2218 let mut out = StringColumn::with_capacity(at.len());
2219 let mut scratch = Vec::new();
2220 for &index in &at {
2221 scratch.clear();
2222 let span = spans
2223 .get(index)
2224 .and_then(|&(from, to)| codes.get(from as usize..to as usize));
2225 if let Some(span) = span {
2226 table.decompress(span, &mut scratch)?;
2227 }
2228 out.push_bytes(&scratch);
2229 }
2230 Body::Flat(Data::Varlen(out))
2231 }
2232 // The entries move and the child does not, which is the same trade the string forms
2233 // make and is why a gather of a list column costs eight bytes a row however long the
2234 // lists are. A position that resolved to nowhere gets a zero length entry, and the mask
2235 // already says it is null, so the entry is never read.
2236 //
2237 // This arm ignores `forms_stay`, unlike every arm above it, because there is nothing
2238 // flatter for a list to become. The other forms are all cheaper ways of writing down a
2239 // column of scalars and flattening gives up the saving to hand back a data slice, and a
2240 // list has no data slice in any form, so a flatten of one is this and a caller reading it
2241 // goes through `list_parts` either way.
2242 Body::Nested { entries, child } => Body::Nested {
2243 entries: at
2244 .iter()
2245 .map(|&index| entries.get(index).copied().unwrap_or((0, 0)))
2246 .collect(),
2247 child: Arc::clone(child),
2248 },
2249 // Every child gathered at the same positions, for the reason the cut cuts every child:
2250 // there are no entries to permute instead, so the permutation happens once per field. The
2251 // positions handed down are the resolved ones, sentinel and all, so a row that resolved to
2252 // nowhere comes back null in each field as well as null here.
2253 //
2254 // `forms_stay` is passed straight through rather than ignored, which is the opposite of
2255 // what the list arm does, and the difference is real. There is nothing flatter for a list
2256 // to become, and a struct is only as flat as its fields are, so a flatten of a struct
2257 // column is a flatten of each field and a caller that asked for data slices gets them.
2258 Body::Fields { children } => Body::Fields {
2259 children: children
2260 .iter()
2261 .map(|child| child.copied(at.clone(), forms_stay).map(Arc::new))
2262 .collect::<Result<Vec<_>>>()?,
2263 },
2264 // Unreachable, because `resolve` walks past both of the forms that point at another
2265 // vector and stops at the first body that does not.
2266 Body::Dictionary { .. } | Body::Runs { .. } => {
2267 return Err(Error::internal(
2268 "a form that points somewhere survived being resolved",
2269 ));
2270 }
2271 };
2272 Ok(Self { ty: self.ty.clone(), len: rows, validity, body })
2273 }
2274
2275 /// Where each wanted position lives in the first body that is not a dictionary, and that body.
2276 ///
2277 /// A position that is null anywhere on the way down, or past the end of anything on the way
2278 /// down, comes back as [`NOWHERE`]. That single sentinel is what keeps the copy loop from
2279 /// carrying a validity mask alongside the positions it is already walking.
2280 fn resolve(&self, mut at: Vec<usize>) -> (Vec<usize>, &Self) {
2281 let mut source = self;
2282 loop {
2283 for slot in &mut at {
2284 if *slot >= source.len || !source.validity.is_valid(*slot) {
2285 *slot = NOWHERE;
2286 }
2287 }
2288 source = match &source.body {
2289 Body::Dictionary { codes, values, .. } => {
2290 for slot in &mut at {
2291 *slot = match codes.get(*slot) {
2292 Some(&code) => code as usize,
2293 None => NOWHERE,
2294 };
2295 }
2296 values.as_ref()
2297 }
2298 // A run length body is a dictionary whose code is worked out from the position
2299 // rather than stored, so the walk down is the same walk with a search where the
2300 // lookup was. `NOWHERE` searches for nothing and stays `NOWHERE`.
2301 Body::Runs { ends, values } => {
2302 for slot in &mut at {
2303 *slot = run_holding(ends, *slot).unwrap_or(NOWHERE);
2304 }
2305 values.as_ref()
2306 }
2307 _ => return (at, source),
2308 };
2309 }
2310 }
2311}
2312
2313/// So that a kernel can take its operands as either a list of vectors or a list of references.
2314///
2315/// A caller that built a `Vec<Vector>` and a caller whose operands are already somewhere else, in a
2316/// chunk or in an evaluator's scratch, want the same kernel. Without this the second kind has to
2317/// clone every operand into a `Vec` to satisfy the signature, and a clone of a vector is a copy of
2318/// the whole column, so the type would be charging real memory traffic for nothing.
2319impl AsRef<Vector> for Vector {
2320 fn as_ref(&self) -> &Vector {
2321 self
2322 }
2323}
2324
2325/// The bits of a packed vector and what they mean, for a kernel that wants to stay in code space.
2326///
2327/// Borrowed from the vector rather than owning anything, so getting one costs nothing and a kernel
2328/// that finds it cannot use them has given up nothing by asking.
2329#[derive(Debug, Clone, Copy)]
2330pub struct Packed<'a> {
2331 words: &'a [u64],
2332 width: u32,
2333 base: i128,
2334 offset: usize,
2335}
2336
2337impl Packed<'_> {
2338 /// Packed words. A persisted vector also records [`Self::offset`].
2339 #[must_use]
2340 pub fn words(&self) -> &[u64] {
2341 self.words
2342 }
2343
2344 /// Bit offset, in rows, of the first value.
2345 #[must_use]
2346 pub fn offset(&self) -> usize {
2347 self.offset
2348 }
2349
2350 /// How many bits one code takes, between one and [`PACKED_WIDTH_MAX`].
2351 #[must_use]
2352 pub fn width(&self) -> u32 {
2353 self.width
2354 }
2355
2356 /// What zero means, so that the value of a row is the base plus its code.
2357 #[must_use]
2358 pub fn base(&self) -> i128 {
2359 self.base
2360 }
2361
2362 /// The largest value this vector can be holding, whatever it is actually holding.
2363 ///
2364 /// With [`Self::base`] this is the pair a comparison kernel wants first. A literal outside the
2365 /// two answers every row of the vector the same way, which is a whole chunk decided without a
2366 /// bit being read, and that is the case a zone map would have caught if there were one here.
2367 #[must_use]
2368 pub fn ceiling(&self) -> i128 {
2369 self.base + i128::from(u64::MAX >> (u64::BITS - self.width))
2370 }
2371
2372 /// The code of row `row`, which is its value minus [`Self::base`].
2373 ///
2374 /// Out of range rows read as zero rather than panicking, the way every other accessor in this
2375 /// file answers for a row that is not there.
2376 #[must_use]
2377 pub fn code(&self, row: usize) -> u64 {
2378 code_at(self.words, (self.offset + row) * self.width as usize, self.width)
2379 }
2380
2381 /// Which code a value would have, and `None` for a value this vector cannot be holding.
2382 ///
2383 /// The translation a comparison does once per vector so that it does not have to unpack once per
2384 /// row. `None` is the useful answer rather than a failure: it says the literal is outside the
2385 /// packed range, so every row compares against it the same way.
2386 #[must_use]
2387 pub fn code_of(&self, value: i128) -> Option<u64> {
2388 u64::try_from(value.checked_sub(self.base)?).ok().filter(|&code| code <= self.mask())
2389 }
2390
2391 /// The largest code the width allows.
2392 fn mask(&self) -> u64 {
2393 u64::MAX >> (u64::BITS - self.width)
2394 }
2395}
2396
2397/// The widest a packed code is allowed to be.
2398///
2399/// Sixty three rather than sixty four so that a mask is `u64::MAX >> (64 - width)` with no shift of
2400/// a whole word in it, and reading a code is one branch on whether it straddles rather than two. A
2401/// sixty four bit code saves nothing anyway, since it is the layout it came from.
2402pub const PACKED_WIDTH_MAX: u32 = 63;
2403
2404/// How much smaller packing has to be before it is worth the shift and the mask on every read.
2405///
2406/// Two, so a column packs when the bits come to half the flat size or less. A column that would save
2407/// a tenth stays flat, because a tenth of a column is not worth turning every read of it into
2408/// arithmetic, and the whole argument for the form is that a narrow column saves most of itself.
2409pub const PACKING_PAYS_AT: usize = 2;
2410
2411/// How much smaller compressing has to be before it is worth a decompression on every read.
2412///
2413/// Two, the same rule packing follows and for the same reason. FSST gets about that on text, so a
2414/// column of English or of URLs compresses and a column of short codes or of random bytes does not,
2415/// which is the right answer for both.
2416pub const FSST_PAYS_AT: usize = 2;
2417
2418/// The codes of a compressed column and the table they are against.
2419///
2420/// Handed out by [`Vector::coded_parts`] so a kernel can work in code space. Nothing here
2421/// decompresses, which is the point: [`Self::encode`] puts the literal into the same space the rows
2422/// are already in, and after that an equality test is a byte slice comparison.
2423#[derive(Debug, Clone, Copy)]
2424pub struct Coded<'a> {
2425 codes: &'a [u8],
2426 spans: &'a [(u32, u32)],
2427 table: &'a SymbolTable,
2428}
2429
2430impl Coded<'_> {
2431 /// The table every row in this vector is compressed against.
2432 #[must_use]
2433 pub fn table(&self) -> &SymbolTable {
2434 self.table
2435 }
2436
2437 /// The code bytes of one row, still compressed.
2438 #[must_use]
2439 pub fn row(&self, row: usize) -> Option<&[u8]> {
2440 let &(from, to) = self.spans.get(row)?;
2441 self.codes.get(from as usize..to as usize)
2442 }
2443
2444 /// Some bytes in the code space this vector is in.
2445 ///
2446 /// The literal side of an equality filter. Compressing is a function of the table and the bytes,
2447 /// so two strings compress to the same codes exactly when they are the same string, and an
2448 /// equality test on the codes is an equality test on the strings with no decompression in it.
2449 #[must_use]
2450 pub fn encode(&self, bytes: &[u8]) -> Vec<u8> {
2451 let mut out = Vec::with_capacity(bytes.len());
2452 self.table.compress(bytes, &mut out);
2453 out
2454 }
2455}
2456
2457/// How many words hold `len` codes of `width` bits.
2458fn words_for(len: usize, width: u32) -> usize {
2459 (len * width as usize).div_ceil(u64::BITS as usize)
2460}
2461
2462/// The lowest and highest value a type's layout can hold, and `None` for a type with no integer one.
2463///
2464/// This is also the test of whether a type can be packed at all, and it is the only one, so the
2465/// layouts listed here and the layouts [`pack`] and [`unpack`] know how to walk are the same list
2466/// from the same macro and cannot drift apart.
2467fn layout_range(ty: &LogicalType) -> Option<(i128, i128)> {
2468 use rudb_common::PhysicalType as P;
2469 macro_rules! ranges {
2470 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2471 match ty.physical() {
2472 $(P::$variant => Some((i128::from(<$native>::MIN), i128::from(<$native>::MAX))),)+
2473 _ => None,
2474 }
2475 };
2476 }
2477 crate::for_each_layout!(exact, ranges)
2478}
2479
2480/// The lowest and highest value in the first `len` slots of a run of integer data.
2481///
2482/// `None` for data that is not integers, which is what says a column cannot be packed. The null
2483/// slots are in the span, holding whatever zero was written into them, which
2484/// [`Vector::bit_packed`] says more about.
2485fn span_of(data: &Data, len: usize) -> Option<(i128, i128)> {
2486 macro_rules! spans {
2487 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2488 match data {
2489 $(Data::$variant(values) => {
2490 let mut low = i128::MAX;
2491 let mut high = i128::MIN;
2492 for &value in values.as_slice().iter().take(len) {
2493 let value = i128::from(value);
2494 low = low.min(value);
2495 high = high.max(value);
2496 }
2497 (low <= high).then_some((low, high))
2498 })+
2499 _ => None,
2500 }
2501 };
2502 }
2503 crate::for_each_layout!(exact, spans)
2504}
2505
2506/// The first `len` values of a run of integer data, written out as codes of `width` bits from `base`.
2507fn pack(data: &Data, len: usize, base: i128, width: u32) -> Vec<u64> {
2508 let mut words = vec![0u64; words_for(len, width)];
2509 macro_rules! packing {
2510 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2511 match data {
2512 $(Data::$variant(values) => {
2513 for (row, &value) in values.as_slice().iter().take(len).enumerate() {
2514 // In range because `base` and `width` came from the span of this same run.
2515 let code = u64::try_from(i128::from(value) - base).unwrap_or(0);
2516 write_code(&mut words, row * width as usize, width, code);
2517 }
2518 })+
2519 _ => {}
2520 }
2521 };
2522 }
2523 crate::for_each_layout!(exact, packing);
2524 words
2525}
2526
2527/// The codes at the given rows, unpacked into the flat layout the type calls for.
2528///
2529/// A row of [`NOWHERE`] writes the layout's zero, which is the rule [`copy_of`] follows for the same
2530/// reason: every layout here is a parallel array to a validity mask, so a null takes a slot.
2531///
2532/// # Errors
2533///
2534/// If the type has no flat layout, which a packed vector cannot have and which is checked when one
2535/// is built, so an error here is a bug rather than a caller mistake.
2536fn unpack(
2537 ty: &LogicalType,
2538 words: &[u64],
2539 offset: usize,
2540 width: u32,
2541 base: i128,
2542 at: &[usize],
2543) -> Result<Data> {
2544 let mut out = empty_data_for(ty)?;
2545 let value_of = |row: usize| {
2546 if row == NOWHERE {
2547 return None;
2548 }
2549 Some(base + i128::from(code_at(words, (offset + row) * width as usize, width)))
2550 };
2551 macro_rules! unpacking {
2552 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2553 match &mut out {
2554 $(Data::$variant(values) => {
2555 values.reserve(at.len());
2556 for &row in at {
2557 // In range because both ends of it were checked when the vector was built.
2558 let value = value_of(row)
2559 .and_then(|value| <$native>::try_from(value).ok())
2560 .unwrap_or($zero);
2561 values.push(value);
2562 }
2563 })+
2564 _ => {
2565 return Err(Error::internal(format!(
2566 "a {ty} vector was packed, which no integer layout allows"
2567 )));
2568 }
2569 }
2570 };
2571 }
2572 crate::for_each_layout!(exact, unpacking);
2573 Ok(out)
2574}
2575
2576/// The `width` bits starting at `bit`, low end first.
2577///
2578/// Zero for bits past the end of the words, which keeps a read of a row that is not there from
2579/// panicking and matches what every other accessor here does with one.
2580fn code_at(words: &[u64], bit: usize, width: u32) -> u64 {
2581 let word = bit / u64::BITS as usize;
2582 let shift = (bit % u64::BITS as usize) as u32;
2583 let mask = u64::MAX >> (u64::BITS - width);
2584 let low = words.get(word).copied().unwrap_or(0) >> shift;
2585 let taken = u64::BITS - shift;
2586 if taken >= width {
2587 return low & mask;
2588 }
2589 // The code straddles two words, and `taken` is under the width here so it is under sixty four,
2590 // which is what makes the shift below one the hardware will do rather than one it refuses.
2591 let high = words.get(word + 1).copied().unwrap_or(0) << taken;
2592 (low | high) & mask
2593}
2594
2595/// Writes `width` bits of `code` starting at `bit`, over words that started out zero.
2596fn write_code(words: &mut [u64], bit: usize, width: u32, code: u64) {
2597 let word = bit / u64::BITS as usize;
2598 let shift = (bit % u64::BITS as usize) as u32;
2599 words[word] |= code << shift;
2600 let taken = u64::BITS - shift;
2601 if taken < width {
2602 words[word + 1] |= code >> taken;
2603 }
2604}
2605
2606/// One level of dictionary out of however many levels were handed to [`Vector::dictionary`].
2607///
2608/// Every dictionary in the system is built through that constructor and every one of them comes
2609/// through here first, so the invariant this maintains is that the vector a dictionary points at is
2610/// never itself a dictionary that could have been composed away. That makes the work a single `if`
2611/// rather than a loop: the inner vector was already composed when it was built, so composing the
2612/// outer codes through it leaves the result no deeper than the inner vector already was.
2613///
2614/// The codes are indexed rather than fetched with `get`, because the caller has already walked the
2615/// whole outer array to check that every code is in range and the inner array is exactly as long as
2616/// the vector those codes were checked against.
2617fn compose(codes: Vec<u32>, values: Vector) -> (Vec<u32>, Vector) {
2618 // A dictionary carrying a validity of its own is one whose nulls live at this level rather than
2619 // in the values, which is the one thing composition cannot carry down with it.
2620 if !matches!(values.validity, Validity::AllValid) {
2621 return (codes, values);
2622 }
2623 let Vector { ty, len, validity, body } = values;
2624 match body {
2625 Body::Dictionary { codes: inner, values: leaf, .. } => {
2626 debug_assert!(
2627 !matches!(leaf.body, Body::Dictionary { .. })
2628 || !matches!(leaf.validity, Validity::AllValid),
2629 "a dictionary was stacked on a dictionary without going through the constructor"
2630 );
2631 // The leaf is shared, so taking it out of the `Arc` copies it when something else is
2632 // still holding the same dictionary. That is the rare path: a dictionary over a
2633 // dictionary only arrives from a caller that built one that way, and the cut that made
2634 // sharing worth doing produces neither.
2635 (codes.iter().map(|&code| inner[code as usize]).collect(), Arc::unwrap_or_clone(leaf))
2636 }
2637 body => (codes, Vector { ty, len, validity, body }),
2638 }
2639}
2640
2641/// How many rows a run has to cover on average before run length encoding is smaller.
2642///
2643/// A run costs its value plus the four bytes of its end, so on a four byte column a run of two rows
2644/// breaks even and a run of three wins. Wider columns win sooner and narrower ones later, and this
2645/// is the one ratio for all of them because a threshold per width is a table that has to be right
2646/// nine times rather than once. It is a constant with a name so that the sweep that eventually moves
2647/// it has something to move.
2648const RUNS_PAY_AT: usize = 2;
2649
2650/// Which run holds `row`, given ends that are exclusive and increasing.
2651///
2652/// A binary search rather than a scan, because the callers that ask this are the ones that are not
2653/// walking the runs in order: a single value read out of a result set, or a gather at scattered
2654/// positions. Anything walking in order should be reading [`Vector::run_parts`] instead, which is
2655/// what the form is for.
2656fn run_holding(ends: &[u32], row: usize) -> Option<usize> {
2657 let row = u32::try_from(row).ok()?;
2658 let run = match ends.binary_search(&row) {
2659 // The ends are exclusive, so landing exactly on one means the row is the first of the next.
2660 Ok(at) => at + 1,
2661 Err(at) => at,
2662 };
2663 (run < ends.len()).then_some(run)
2664}
2665
2666/// The row each run ends at, for a flat body read alongside the validity that goes with it.
2667///
2668/// Two adjacent nulls are one run, because a reader of either gets a null and cannot tell them
2669/// apart. A null between two equal values is three runs for the same reason, since the null is a
2670/// value of the column as far as anything reading it is concerned.
2671///
2672/// The comparison is per layout rather than per `Value`, which is the whole reason this is a macro.
2673/// A `Value` a row would allocate a string per row on a `VARCHAR` column and would be the exact
2674/// defect `cargo xtask rowloop` exists to fail the build on.
2675fn boundaries(data: &Data, validity: &Validity, len: usize) -> Vec<u32> {
2676 if len == 0 {
2677 return Vec::new();
2678 }
2679 let breaks = |ends: &mut Vec<u32>, mut differs: Box<dyn FnMut(usize, usize) -> bool + '_>| {
2680 for row in 1..len {
2681 let same = match (validity.is_valid(row), validity.is_valid(row - 1)) {
2682 (false, false) => true,
2683 (true, true) => !differs(row, row - 1),
2684 _ => false,
2685 };
2686 if !same {
2687 ends.push(u32::try_from(row).unwrap_or(u32::MAX));
2688 }
2689 }
2690 ends.push(u32::try_from(len).unwrap_or(u32::MAX));
2691 };
2692 let mut ends = Vec::new();
2693 macro_rules! walked {
2694 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2695 match data {
2696 // No values at all, so every row is the same null and the column is one run.
2697 Data::Empty => ends.push(u32::try_from(len).unwrap_or(u32::MAX)),
2698 $(Data::$variant(values) => {
2699 breaks(&mut ends, Box::new(|a, b| values.get(a) != values.get(b)));
2700 })+
2701 Data::Varlen(values) => {
2702 breaks(&mut ends, Box::new(|a, b| values.bytes(a) != values.bytes(b)));
2703 }
2704 }
2705 };
2706 }
2707 crate::for_each_layout!(fixed, walked);
2708 ends
2709}
2710
2711/// The position of a value that is not anywhere, because it is null or out of range.
2712///
2713/// `usize::MAX` rather than an `Option<usize>`, because the copy loop's bounds check rejects it for
2714/// free and an `Option` would put a second branch next to the one already there.
2715const NOWHERE: usize = usize::MAX;
2716
2717/// A run of data copied at the given positions, with a zero wherever the position is [`NOWHERE`].
2718///
2719/// A zero and not a skip, because every layout here is a parallel array to a validity mask and a
2720/// short one would put every value after the first null at the wrong index. It is the same rule
2721/// [`push_value`] follows for a null.
2722/// A contiguous run of a flat body, copied out.
2723///
2724/// The counterpart to [`copy_of`] for the one case that is a range rather than a set of positions,
2725/// which is what [`Vector::slice`] asks for. Every fixed width layout is one `memcpy` and the
2726/// string layout is a run of views and their bytes, where `copy_of` is a bounds checked index and a
2727/// null test per row.
2728///
2729/// The caller has already checked that `end` is inside the vector, and a body whose data is shorter
2730/// than its vector claims is a bug elsewhere, so a short run is clamped rather than reported.
2731fn run_of(data: &Data, at: usize, end: usize) -> Data {
2732 macro_rules! run {
2733 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2734 match data {
2735 Data::Empty => Data::Empty,
2736 $(Data::$variant(values) => {
2737 let values = values.as_slice();
2738 let from = at.min(values.len());
2739 let to = end.max(from).min(values.len());
2740 let mut out = Buffer::with_capacity(end - at);
2741 out.extend_from_slice(&values[from..to]);
2742 // A body shorter than the rows asked for pads with the zero every layout uses
2743 // for a null, which is the answer `copy_of` gives for a position past the end.
2744 // row at a time: never runs on a vector whose data matches its length.
2745 for _ in to..end {
2746 out.push($zero);
2747 }
2748 Data::$variant(out)
2749 })+
2750 // A view says where its bytes are, so a run of rows is not a run of bytes and this
2751 // is the one layout whose cut is still a loop. The total is known before any of it
2752 // is copied, so the arena is one allocation.
2753 Data::Varlen(values) => {
2754 let views = values.views();
2755 let mut out = StringColumn::with_capacity(end - at);
2756 out.reserve_bytes(
2757 views
2758 .get(at.min(views.len())..end.min(views.len()))
2759 .unwrap_or(&[])
2760 .iter()
2761 .filter(|view| !view.is_inline())
2762 .map(StringView::len)
2763 .sum(),
2764 );
2765 // row at a time: see above, the bytes of consecutive rows need not be next to
2766 // each other.
2767 for index in at..end {
2768 out.push_from(values, index);
2769 }
2770 Data::Varlen(out)
2771 }
2772 }
2773 };
2774 }
2775 crate::for_each_layout!(fixed, run)
2776}
2777
2778fn copy_of(data: &Data, at: &[usize]) -> Data {
2779 macro_rules! copied {
2780 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2781 match data {
2782 Data::Empty => Data::Empty,
2783 $(Data::$variant(values) => {
2784 let mut out = Buffer::with_capacity(at.len());
2785 for &index in at {
2786 // One bounds check rather than a null test and a bounds check, because
2787 // `NOWHERE` is past the end of every slice there can be.
2788 out.push(values.get(index).copied().unwrap_or($zero));
2789 }
2790 Data::$variant(out)
2791 })+
2792 // The one layout where a gather is a copy of bytes rather than a copy of fixed
2793 // width slots, and the reason compaction is a decision rather than a default on a
2794 // string column.
2795 Data::Varlen(values) => {
2796 let mut out = StringColumn::with_capacity(at.len());
2797 // The bytes are known before any of them are copied, because a view carries its
2798 // length and the wanted positions are already in hand, so the arena is one
2799 // allocation rather than a run of doublings that each copy what the last one
2800 // copied.
2801 let views = values.views();
2802 out.reserve_bytes(
2803 at.iter()
2804 .filter_map(|&index| views.get(index))
2805 .filter(|view| !view.is_inline())
2806 .map(StringView::len)
2807 .sum(),
2808 );
2809 for &index in at {
2810 out.push_from(values, index);
2811 }
2812 Data::Varlen(out)
2813 }
2814 }
2815 };
2816 }
2817 crate::for_each_layout!(fixed, copied)
2818}
2819
2820/// The physical layout a run of data is in, for the check that it matches its type.
2821///
2822/// The two enums name their variants the same way on purpose, so this is one generated arm rather
2823/// than sixteen chances to pair the wrong two up.
2824fn layout_of(data: &Data) -> rudb_common::PhysicalType {
2825 use rudb_common::PhysicalType as P;
2826 macro_rules! layouts {
2827 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2828 match data {
2829 Data::Empty => P::Empty,
2830 $(Data::$variant(_) => P::$variant,)+
2831 }
2832 };
2833 }
2834 crate::for_each_layout!(all, layouts)
2835}
2836
2837/// One value out of a run of data, given what the run means.
2838///
2839/// The match is on the logical type rather than on the data, because the data cannot tell a `DATE`
2840/// from an `INTEGER` and that is the whole reason the two are kept apart.
2841fn value_from(ty: &LogicalType, data: &Data, index: usize) -> Value {
2842 let signed = || data.signed_at(index);
2843 let unsigned = || data.unsigned_at(index);
2844 let value = match ty {
2845 LogicalType::Boolean => match data {
2846 Data::Bool(v) => v.get(index).map(|&x| Value::Boolean(x)),
2847 _ => None,
2848 },
2849 LogicalType::TinyInt => signed().and_then(|x| i8::try_from(x).ok()).map(Value::TinyInt),
2850 LogicalType::SmallInt => signed().and_then(|x| i16::try_from(x).ok()).map(Value::SmallInt),
2851 LogicalType::Integer => signed().and_then(|x| i32::try_from(x).ok()).map(Value::Integer),
2852 LogicalType::BigInt => signed().and_then(|x| i64::try_from(x).ok()).map(Value::BigInt),
2853 LogicalType::HugeInt => signed().map(Value::HugeInt),
2854 LogicalType::UTinyInt => unsigned().and_then(|x| u8::try_from(x).ok()).map(Value::UTinyInt),
2855 LogicalType::USmallInt => {
2856 unsigned().and_then(|x| u16::try_from(x).ok()).map(Value::USmallInt)
2857 }
2858 LogicalType::UInteger => {
2859 unsigned().and_then(|x| u32::try_from(x).ok()).map(Value::UInteger)
2860 }
2861 LogicalType::UBigInt => unsigned().and_then(|x| u64::try_from(x).ok()).map(Value::UBigInt),
2862 LogicalType::UHugeInt => unsigned().map(Value::UHugeInt),
2863 LogicalType::Float => match data {
2864 Data::Float32(v) => v.get(index).map(|&x| Value::Float(x)),
2865 _ => None,
2866 },
2867 LogicalType::Double => match data {
2868 Data::Float64(v) => v.get(index).map(|&x| Value::Double(x)),
2869 _ => None,
2870 },
2871 LogicalType::Decimal { width, scale } => {
2872 signed().map(|unscaled| Value::Decimal { unscaled, width: *width, scale: *scale })
2873 }
2874 LogicalType::Varchar | LogicalType::Blob | LogicalType::Bit => {
2875 data.bytes_at(index).map(|bytes| bytes_as(ty, bytes))
2876 }
2877 LogicalType::Date => signed().and_then(|x| i32::try_from(x).ok()).map(Value::Date),
2878 LogicalType::Time => signed().and_then(|x| i64::try_from(x).ok()).map(Value::Time),
2879 LogicalType::TimeTz => signed().and_then(|x| i64::try_from(x).ok()).map(Value::TimeTz),
2880 LogicalType::Timestamp
2881 | LogicalType::TimestampS
2882 | LogicalType::TimestampMs
2883 | LogicalType::TimestampNs => {
2884 signed().and_then(|x| i64::try_from(x).ok()).map(Value::Timestamp)
2885 }
2886 LogicalType::TimestampTz => {
2887 signed().and_then(|x| i64::try_from(x).ok()).map(Value::TimestampTz)
2888 }
2889 LogicalType::Interval => match data {
2890 Data::Interval(v) => {
2891 v.get(index).map(|&(months, days, micros)| Value::Interval { months, days, micros })
2892 }
2893 _ => None,
2894 },
2895 _ => None,
2896 };
2897 value.unwrap_or(Value::Null)
2898}
2899
2900/// The fields a struct type names, and nothing for any other type.
2901///
2902/// Only a `STRUCT` vector has a [`Body::Fields`] body, and the two are built together, so in practice
2903/// the empty slice is unreachable and is here so that reading a field name is not a panic if that ever
2904/// stops being true. A struct vector whose type has fewer fields than it has children answers about
2905/// the fields it can name, because the zip stops at the shorter of the two.
2906fn fields_of(ty: &LogicalType) -> &[Field] {
2907 match ty {
2908 LogicalType::Struct(fields) => fields,
2909 _ => &[],
2910 }
2911}
2912
2913/// One row of a string column as a value, given what its bytes are meant to be read as.
2914///
2915/// Both forms that hold strings come through here, so a row that is a `BLOB` in a flat column is a
2916/// `BLOB` in a string view column too. Bytes that are not text in a `VARCHAR` column are a null
2917/// rather than a panic, since everything that got in went in as a string and a column that has
2918/// something else in it is a bug somewhere earlier that a read should not turn into a crash.
2919fn bytes_as(ty: &LogicalType, bytes: &[u8]) -> Value {
2920 match ty {
2921 LogicalType::Varchar => {
2922 std::str::from_utf8(bytes).map_or(Value::Null, |text| Value::Varchar(text.to_owned()))
2923 }
2924 LogicalType::Blob | LogicalType::Bit => Value::Blob(bytes.to_vec()),
2925 _ => Value::Null,
2926 }
2927}
2928
2929/// An empty run of data of the right layout for a type.
2930fn empty_data_for(ty: &LogicalType) -> Result<Data> {
2931 use rudb_common::PhysicalType as P;
2932 macro_rules! empties {
2933 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
2934 match ty.physical() {
2935 P::Empty => Data::Empty,
2936 $(P::$variant => Data::$variant(Buffer::new()),)+
2937 P::Varlen => Data::Varlen(StringColumn::new()),
2938 other => {
2939 return Err(Error::not_implemented(format!(
2940 "a flat vector of {other:?} data, which arrives with the storage layer"
2941 )));
2942 }
2943 }
2944 };
2945 }
2946 Ok(crate::for_each_layout!(fixed, empties))
2947}
2948
2949/// Appends one value to a run of data, or a zero of the right shape when it is null.
2950///
2951/// The zero matters. A null still occupies a position, the validity mask is what says it is null,
2952/// and a run of data with a hole in it would put every value after the hole in the wrong place.
2953fn push_value(data: &mut Data, value: &Value) -> Result<()> {
2954 macro_rules! push {
2955 ($vec:expr, $variant:path, $zero:expr) => {
2956 match value {
2957 Value::Null => $vec.push($zero),
2958 $variant(x) => $vec.push(*x),
2959 other => {
2960 return Err(Error::internal(format!(
2961 "{other:?} does not belong in this vector"
2962 )));
2963 }
2964 }
2965 };
2966 }
2967 // A decimal is stored as its unscaled integer in whatever width its precision needs, which
2968 // `LogicalType::physical` decides and which is why the same `Value::Decimal` is at home in four
2969 // different runs. The narrowing cannot fail for a value the binder produced, because the width
2970 // that chose the run is the width in the value, but it is checked rather than assumed because
2971 // an unchecked cast here would silently store a different number.
2972 macro_rules! decimal {
2973 ($vec:expr, $ty:ty, $unscaled:expr) => {
2974 match <$ty>::try_from(*$unscaled) {
2975 Ok(x) => $vec.push(x),
2976 Err(_) => {
2977 return Err(Error::internal(format!(
2978 "an unscaled decimal of {} does not fit the run its precision chose",
2979 $unscaled
2980 )));
2981 }
2982 }
2983 };
2984 }
2985 match data {
2986 Data::Empty => {}
2987 Data::Bool(v) => push!(v, Value::Boolean, false),
2988 Data::Int8(v) => push!(v, Value::TinyInt, 0),
2989 Data::Int16(v) => match value {
2990 Value::Null => v.push(0),
2991 Value::SmallInt(x) => v.push(*x),
2992 Value::Decimal { unscaled, .. } => decimal!(v, i16, unscaled),
2993 other => return Err(Error::internal(format!("{other:?} is not a 16 bit value"))),
2994 },
2995 Data::Int32(v) => match value {
2996 Value::Null => v.push(0),
2997 Value::Integer(x) | Value::Date(x) => v.push(*x),
2998 Value::Decimal { unscaled, .. } => decimal!(v, i32, unscaled),
2999 other => return Err(Error::internal(format!("{other:?} is not a 32 bit value"))),
3000 },
3001 Data::Int64(v) => match value {
3002 Value::Null => v.push(0),
3003 Value::BigInt(x)
3004 | Value::Time(x)
3005 | Value::TimeTz(x)
3006 | Value::Timestamp(x)
3007 | Value::TimestampTz(x) => v.push(*x),
3008 Value::Decimal { unscaled, .. } => decimal!(v, i64, unscaled),
3009 other => return Err(Error::internal(format!("{other:?} is not a 64 bit value"))),
3010 },
3011 Data::Int128(v) => match value {
3012 Value::Null => v.push(0),
3013 Value::HugeInt(x) => v.push(*x),
3014 Value::Decimal { unscaled, .. } => v.push(*unscaled),
3015 other => return Err(Error::internal(format!("{other:?} is not a 128 bit value"))),
3016 },
3017 Data::UInt8(v) => push!(v, Value::UTinyInt, 0),
3018 Data::UInt16(v) => push!(v, Value::USmallInt, 0),
3019 Data::UInt32(v) => push!(v, Value::UInteger, 0),
3020 Data::UInt64(v) => push!(v, Value::UBigInt, 0),
3021 Data::UInt128(v) => push!(v, Value::UHugeInt, 0),
3022 Data::Float32(v) => push!(v, Value::Float, 0.0),
3023 Data::Float64(v) => push!(v, Value::Double, 0.0),
3024 Data::Interval(v) => match value {
3025 Value::Null => v.push((0, 0, 0)),
3026 Value::Interval { months, days, micros } => v.push((*months, *days, *micros)),
3027 other => return Err(Error::internal(format!("{other:?} is not an interval"))),
3028 },
3029 Data::Varlen(column) => match value {
3030 Value::Null => {
3031 column.push("");
3032 }
3033 Value::Varchar(text) => {
3034 column.push(text);
3035 }
3036 // A blob goes in as the bytes it is. The column stores a length and some bytes either
3037 // way, so text is the reading of one rather than a different column, and a blob that
3038 // is not UTF-8 is stored exactly like one that happens to be.
3039 Value::Blob(bytes) => {
3040 column.push_bytes(bytes);
3041 }
3042 other => return Err(Error::internal(format!("{other:?} is not a string"))),
3043 },
3044 }
3045 Ok(())
3046}
3047
3048#[cfg(test)]
3049mod tests {
3050 use std::sync::Arc;
3051
3052 use rudb_common::{Field, LogicalType, Value};
3053
3054 use super::{Body, Data, FSST_PAYS_AT, Form, MAP_KEY, MAP_VALUE, VECTOR_SIZE, Vector};
3055 use crate::buffer::Buffer;
3056 use crate::fsst::SymbolTable;
3057 use crate::string::{StringColumn, StringView};
3058 use crate::validity::Validity;
3059
3060 fn integers(values: &[i32]) -> Vector {
3061 Vector::flat(LogicalType::Integer, Data::Int32(values.to_vec().into())).unwrap()
3062 }
3063
3064 /// A `Value::List` of integers, which is what a row of a list column arrives as.
3065 fn list(values: &[i32]) -> Value {
3066 Value::List {
3067 element: LogicalType::Integer,
3068 values: values.iter().map(|&v| Value::Integer(v)).collect(),
3069 }
3070 }
3071
3072 fn list_column(rows: &[Value]) -> Vector {
3073 Vector::from_values(LogicalType::list(LogicalType::Integer), rows).unwrap()
3074 }
3075
3076 #[test]
3077 fn a_list_column_is_one_child_and_a_range_per_row() {
3078 let rows = vec![list(&[1, 2, 3]), list(&[]), Value::Null, list(&[4])];
3079 let column = list_column(&rows);
3080 assert_eq!(column.form(), Form::List);
3081 assert_eq!(column.len(), 4);
3082 assert_eq!(column.logical_type(), &LogicalType::list(LogicalType::Integer));
3083 // Four rows and four elements, because a null and an empty list both contribute none.
3084 let (entries, child) = column.list_parts().expect("a list");
3085 assert_eq!(entries, [(0, 3), (3, 0), (3, 0), (3, 1)]);
3086 assert_eq!(child.len(), 4);
3087 assert_eq!(column.iter().collect::<Vec<_>>(), rows);
3088 }
3089
3090 /// The one thing the entries cannot say on their own, so it has to be checked that the mask says
3091 /// it. An empty list is a row that is there and holds nothing, a null is a row that is not there,
3092 /// and both of them have an entry of length zero.
3093 #[test]
3094 fn an_empty_list_and_a_null_list_have_the_same_entry_and_are_different_rows() {
3095 let column = list_column(&[list(&[]), Value::Null]);
3096 let (entries, _) = column.list_parts().expect("a list");
3097 assert_eq!(entries[0].1, entries[1].1, "both entries are empty");
3098 assert!(!column.is_null_at(0), "an empty list is not null");
3099 assert!(column.is_null_at(1), "a null list is null");
3100 assert_eq!(column.value_at(0), list(&[]));
3101 assert_eq!(column.value_at(1), Value::Null);
3102 }
3103
3104 #[test]
3105 fn slicing_a_list_column_shares_the_child_rather_than_copying_it() {
3106 let rows: Vec<Value> = (0..64).map(|row| list(&[row, row + 1, row + 2])).collect();
3107 let column = list_column(&rows);
3108 let cut = column.slice(8, 4).unwrap();
3109 assert_eq!(cut.form(), Form::List);
3110 assert_eq!(cut.iter().collect::<Vec<_>>(), rows[8..12]);
3111 // The entries are absolute positions in a child that was not cut, which is what makes the
3112 // cut eight bytes a row however long the lists are. The elements outside the range are still
3113 // there and nothing points at them.
3114 let (entries, child) = cut.list_parts().expect("a list");
3115 assert_eq!(entries[0], (24, 3));
3116 assert_eq!(child.len(), 192);
3117 }
3118
3119 #[test]
3120 fn gathering_a_list_column_permutes_the_entries_and_leaves_the_child_alone() {
3121 let rows = vec![list(&[1]), list(&[2, 2]), list(&[3, 3, 3])];
3122 let column = list_column(&rows);
3123 let picked = column.gather(&[2, 0, 2]).unwrap();
3124 assert_eq!(
3125 picked.iter().collect::<Vec<_>>(),
3126 [list(&[3, 3, 3]), list(&[1]), list(&[3, 3, 3])]
3127 );
3128 // Two of the three rows are the same row, which is the case a run of offsets cannot write
3129 // down and a start and a length can. That is the whole reason this form carries both.
3130 assert_eq!(picked.list_parts().expect("a list").1.len(), 6);
3131 }
3132
3133 #[test]
3134 fn a_gather_past_the_end_of_a_list_column_is_null_rather_than_somebody_elses_elements() {
3135 let column = list_column(&[list(&[1, 2]), list(&[3])]);
3136 let picked = column.gather(&[1, 9]).unwrap();
3137 assert_eq!(picked.value_at(0), list(&[3]));
3138 assert_eq!(picked.value_at(1), Value::Null);
3139 }
3140
3141 #[test]
3142 fn a_list_of_lists_nests_as_far_as_it_is_written() {
3143 let outer = Value::List {
3144 element: LogicalType::list(LogicalType::Integer),
3145 values: vec![list(&[1, 2]), list(&[3])],
3146 };
3147 let column = Vector::from_values(
3148 LogicalType::list(LogicalType::list(LogicalType::Integer)),
3149 std::slice::from_ref(&outer),
3150 )
3151 .unwrap();
3152 assert_eq!(column.value_at(0), outer);
3153 assert_eq!(column.list_parts().expect("a list").1.form(), Form::List);
3154 }
3155
3156 /// A list row is not bytes and not an integer, and a caller that asks for either gets nothing
3157 /// rather than the first element or a length. Both of those would be a wrong answer that a
3158 /// group by or a hash would read without complaining.
3159 #[test]
3160 fn the_scalar_readers_decline_a_list_instead_of_answering_about_its_elements() {
3161 let column = list_column(&[list(&[7])]);
3162 assert_eq!(column.signed_at(0), None);
3163 assert_eq!(column.bytes_at(0), None);
3164 assert_eq!(column.data(), None);
3165 }
3166
3167 fn pair(a: i32, b: &str) -> Value {
3168 Value::Struct(vec![
3169 ("a".to_string(), Value::Integer(a)),
3170 ("b".to_string(), Value::Varchar(b.to_string())),
3171 ])
3172 }
3173
3174 fn pair_type() -> LogicalType {
3175 LogicalType::Struct(vec![
3176 Field::new("a", LogicalType::Integer),
3177 Field::new("b", LogicalType::Varchar),
3178 ])
3179 }
3180
3181 fn pair_column(rows: &[Value]) -> Vector {
3182 Vector::from_values(pair_type(), rows).unwrap()
3183 }
3184
3185 #[test]
3186 fn a_struct_column_is_one_child_per_field_as_long_as_the_column() {
3187 let rows = vec![pair(1, "x"), pair(2, "y"), pair(3, "z")];
3188 let column = pair_column(&rows);
3189 assert_eq!(column.form(), Form::Struct);
3190 assert_eq!(column.len(), 3);
3191 assert_eq!(column.logical_type(), &pair_type());
3192 // Two children rather than two entries and a child, and both of them as long as the column,
3193 // which is the whole difference between this form and the list one.
3194 let children = column.struct_parts().expect("a struct");
3195 assert_eq!(children.len(), 2);
3196 assert_eq!(children[0].len(), 3);
3197 assert_eq!(children[1].len(), 3);
3198 assert_eq!(children[0].logical_type(), &LogicalType::Integer);
3199 assert_eq!(children[1].logical_type(), &LogicalType::Varchar);
3200 assert_eq!(column.iter().collect::<Vec<_>>(), rows);
3201 }
3202
3203 /// Picking one field out of a struct is picking one child, which is the reason this accessor is
3204 /// public. A projection of `s.a` hands back a vector that already exists, so it costs a pointer
3205 /// rather than a pass over the rows, and that is only true while the children are full length.
3206 #[test]
3207 fn one_field_of_a_struct_column_is_a_column_that_is_already_there() {
3208 let column = pair_column(&[pair(10, "x"), pair(20, "y")]);
3209 let field = &column.struct_parts().expect("a struct")[0];
3210 assert_eq!(field.iter().collect::<Vec<_>>(), [Value::Integer(10), Value::Integer(20)]);
3211 assert_eq!(field.signed_at(1), Some(20), "the field is a scalar column and reads like one");
3212 }
3213
3214 /// A null struct is a bit in the mask at the top and nothing deeper, which is how every other type
3215 /// records a null and is what DuckDB does. The row reads as a single null rather than as a struct of
3216 /// nulls, and the fields underneath are still their own columns.
3217 #[test]
3218 fn a_null_struct_is_the_mask_at_the_top_and_not_a_struct_full_of_nulls() {
3219 let column = pair_column(&[pair(1, "x"), Value::Null]);
3220 assert!(!column.is_null_at(0));
3221 assert!(column.is_null_at(1));
3222 assert_eq!(column.value_at(1), Value::Null);
3223 // A struct row whose every field happens to be null is a different row, and it is not null.
3224 let all_null = pair_column(&[Value::Struct(vec![
3225 ("a".to_string(), Value::Null),
3226 ("b".to_string(), Value::Null),
3227 ])]);
3228 assert!(!all_null.is_null_at(0), "a struct of nulls is a row that is there");
3229 assert_ne!(all_null.value_at(0), Value::Null);
3230 }
3231
3232 #[test]
3233 fn slicing_a_struct_column_cuts_every_field_at_the_same_place() {
3234 let rows: Vec<Value> = (0..64).map(|row| pair(row, "s")).collect();
3235 let column = pair_column(&rows);
3236 let cut = column.slice(8, 4).unwrap();
3237 assert_eq!(cut.form(), Form::Struct);
3238 assert_eq!(cut.iter().collect::<Vec<_>>(), rows[8..12]);
3239 // The cut a list column does not have to do. A list shares its child untouched because the
3240 // entries carry the range, and a struct has no entry standing between the row and the child,
3241 // so every child is four rows long here rather than sixty four.
3242 for child in cut.struct_parts().expect("a struct") {
3243 assert_eq!(child.len(), 4);
3244 }
3245 }
3246
3247 #[test]
3248 fn gathering_a_struct_column_gathers_every_field_at_the_same_positions() {
3249 let column = pair_column(&[pair(1, "x"), pair(2, "y"), pair(3, "z")]);
3250 let picked = column.gather(&[2, 0, 2]).unwrap();
3251 assert_eq!(picked.iter().collect::<Vec<_>>(), [pair(3, "z"), pair(1, "x"), pair(3, "z")]);
3252 for child in picked.struct_parts().expect("a struct") {
3253 assert_eq!(child.len(), 3, "a field is as long as the gather, not as the source");
3254 }
3255 }
3256
3257 #[test]
3258 fn a_gather_past_the_end_of_a_struct_column_is_null_in_every_field_and_at_the_top() {
3259 let column = pair_column(&[pair(1, "x"), pair(2, "y")]);
3260 let picked = column.gather(&[1, 9]).unwrap();
3261 assert_eq!(picked.value_at(0), pair(2, "y"));
3262 assert_eq!(picked.value_at(1), Value::Null);
3263 for child in picked.struct_parts().expect("a struct") {
3264 assert!(child.is_null_at(1), "a row that came from nowhere has no field value either");
3265 }
3266 }
3267
3268 /// The names are matched and not counted, because a caller holding a struct value built in a
3269 /// different order from the type's would otherwise get its columns transposed, and that is a wrong
3270 /// answer that reads as a right one.
3271 #[test]
3272 fn the_fields_of_a_struct_value_go_in_by_name_rather_than_by_position() {
3273 let swapped = Value::Struct(vec![
3274 ("b".to_string(), Value::Varchar("x".to_string())),
3275 ("a".to_string(), Value::Integer(1)),
3276 ]);
3277 let column = pair_column(&[swapped]);
3278 assert_eq!(column.value_at(0), pair(1, "x"));
3279 let wrong = Value::Struct(vec![
3280 ("a".to_string(), Value::Integer(1)),
3281 ("c".to_string(), Value::Varchar("x".to_string())),
3282 ]);
3283 let failed = Vector::from_values(pair_type(), &[wrong]);
3284 assert!(failed.is_err(), "a row with no b field is an error rather than a null b");
3285 }
3286
3287 #[test]
3288 fn a_struct_built_from_children_takes_its_field_names_from_the_caller() {
3289 let column = Vector::structure(vec![
3290 ("a".to_string(), integers(&[1, 2, 3])),
3291 ("b".to_string(), integers(&[4, 5, 6])),
3292 ])
3293 .expect("two columns of three");
3294 assert_eq!(column.len(), 3);
3295 assert_eq!(
3296 column.logical_type(),
3297 &LogicalType::Struct(vec![
3298 Field::new("a", LogicalType::Integer),
3299 Field::new("b", LogicalType::Integer),
3300 ])
3301 );
3302 assert_eq!(
3303 column.value_at(1),
3304 Value::Struct(vec![
3305 ("a".to_string(), Value::Integer(2)),
3306 ("b".to_string(), Value::Integer(5)),
3307 ])
3308 );
3309 }
3310
3311 /// The two mistakes this constructor makes easy, both refused rather than stored. A short field is
3312 /// the one that matters: it would be a struct that reads past the end of one of its own children,
3313 /// which is the same mistake `Vector::list` checks for at the other end.
3314 #[test]
3315 fn a_struct_of_uneven_children_or_of_no_children_is_refused() {
3316 let uneven = Vector::structure(vec![
3317 ("a".to_string(), integers(&[1, 2, 3])),
3318 ("b".to_string(), integers(&[4, 5])),
3319 ]);
3320 assert!(uneven.is_err(), "a field shorter than the struct");
3321 assert!(Vector::structure(vec![]).is_err(), "no field to take a length from");
3322 }
3323
3324 #[test]
3325 fn a_struct_of_lists_and_a_list_of_structs_both_nest() {
3326 let ty =
3327 LogicalType::Struct(vec![Field::new("a", LogicalType::list(LogicalType::Integer))]);
3328 let row = Value::Struct(vec![("a".to_string(), list(&[1, 2]))]);
3329 let column = Vector::from_values(ty, std::slice::from_ref(&row)).unwrap();
3330 assert_eq!(column.value_at(0), row);
3331 assert_eq!(column.struct_parts().expect("a struct")[0].form(), Form::List);
3332
3333 let outer = Value::List { element: pair_type(), values: vec![pair(1, "x"), pair(2, "y")] };
3334 let lists =
3335 Vector::from_values(LogicalType::list(pair_type()), std::slice::from_ref(&outer))
3336 .unwrap();
3337 assert_eq!(lists.value_at(0), outer);
3338 assert_eq!(lists.list_parts().expect("a list").1.form(), Form::Struct);
3339 }
3340
3341 fn tags(pairs: &[(&str, &str)]) -> Value {
3342 Value::map(
3343 LogicalType::Varchar,
3344 LogicalType::Varchar,
3345 pairs
3346 .iter()
3347 .map(|&(key, value)| {
3348 (Value::Varchar(key.to_string()), Value::Varchar(value.to_string()))
3349 })
3350 .collect(),
3351 )
3352 }
3353
3354 fn tag_column(rows: &[Value]) -> Vector {
3355 Vector::from_values(LogicalType::map(LogicalType::Varchar, LogicalType::Varchar), rows)
3356 .unwrap()
3357 }
3358
3359 /// A map is a list of two field structs, which is the whole design, so the test that says so is
3360 /// the one that reaches through both layers and finds the pieces where each of them puts them.
3361 #[test]
3362 fn a_map_column_is_a_list_whose_child_is_a_struct_of_keys_and_values() {
3363 let rows =
3364 vec![tags(&[("a", "b"), ("c", "d")]), tags(&[]), Value::Null, tags(&[("e", "f")])];
3365 let column = tag_column(&rows);
3366 assert_eq!(column.len(), 4);
3367 assert_eq!(
3368 column.logical_type(),
3369 &LogicalType::map(LogicalType::Varchar, LogicalType::Varchar)
3370 );
3371 // The physical form is a list's, because the bytes are a list's. The logical type is what
3372 // remembers it is a map, which is the same split `LogicalType::physical` already makes.
3373 assert_eq!(column.form(), Form::List);
3374 let (entries, child) = column.list_parts().expect("the layout of a list");
3375 assert_eq!(entries, [(0, 2), (2, 0), (2, 0), (2, 1)]);
3376 assert_eq!(child.form(), Form::Struct);
3377 assert_eq!(
3378 child.logical_type(),
3379 &LogicalType::Struct(vec![
3380 Field::new(MAP_KEY, LogicalType::Varchar),
3381 Field::new(MAP_VALUE, LogicalType::Varchar),
3382 ])
3383 );
3384 // And the accessor that reaches through it hands back the two columns rather than the struct.
3385 let (entries, keys, values) = column.map_parts().expect("a map");
3386 assert_eq!(entries.len(), 4);
3387 assert_eq!(keys.text_at(0), Some("a"));
3388 assert_eq!(values.text_at(0), Some("b"));
3389 assert_eq!(column.iter().collect::<Vec<_>>(), rows);
3390 }
3391
3392 /// The same distinction a list has, checked again here rather than assumed from the composition,
3393 /// because the empty map is the one every catalog table in D2 is full of and a null map is what a
3394 /// column with no tags at all would be.
3395 #[test]
3396 fn an_empty_map_and_a_null_map_are_different_rows() {
3397 let column = tag_column(&[tags(&[]), Value::Null]);
3398 assert!(!column.is_null_at(0), "an empty map is a row that is there");
3399 assert!(column.is_null_at(1));
3400 assert_eq!(column.value_at(0), tags(&[]));
3401 assert_eq!(column.value_at(1), Value::Null);
3402 assert_eq!(column.value_at(0).to_string(), "{}");
3403 assert_eq!(column.value_at(1).to_string(), "NULL");
3404 }
3405
3406 /// A map prints `{a=b}` and a struct prints `{'a': b}`, both measured off the pin. They share a
3407 /// layout and they cannot share a printer, which is the one thing about this composition that does
3408 /// not fall out of it.
3409 #[test]
3410 fn a_map_prints_with_equals_signs_and_a_struct_prints_with_quoted_names() {
3411 assert_eq!(tags(&[("a", "b"), ("c", "d")]).to_string(), "{a=b, c=d}");
3412 assert_eq!(pair(1, "x").to_string(), "{'a': 1, 'b': x}");
3413 let numbers = Value::map(
3414 LogicalType::Integer,
3415 LogicalType::Integer,
3416 vec![(Value::Integer(1), Value::Integer(3)), (Value::Integer(2), Value::Integer(4))],
3417 );
3418 assert_eq!(numbers.to_string(), "{1=3, 2=4}");
3419 let null_value = Value::map(
3420 LogicalType::Varchar,
3421 LogicalType::Varchar,
3422 vec![(Value::Varchar("x".to_string()), Value::Null)],
3423 );
3424 assert_eq!(null_value.to_string(), "{x=NULL}");
3425 }
3426
3427 /// A map inherits the list's cut and the list's gather, which is the payoff for storing it as one.
3428 /// Neither of these is code written for maps and both of them are worth a test that says the
3429 /// inheritance works, since the type is rewritten on the way through and a form that came back as a
3430 /// list would still read.
3431 #[test]
3432 fn cutting_and_gathering_a_map_keeps_it_a_map() {
3433 let rows: Vec<Value> =
3434 (0..16).map(|row| tags(&[("k", if row % 2 == 0 { "e" } else { "o" })])).collect();
3435 let column = tag_column(&rows);
3436
3437 let cut = column.slice(4, 3).unwrap();
3438 assert!(matches!(cut.logical_type(), LogicalType::Map(_, _)), "still a map after a cut");
3439 assert_eq!(cut.iter().collect::<Vec<_>>(), rows[4..7]);
3440 // The child was not cut, the same as for a list, which is what makes the cut eight bytes a row.
3441 assert_eq!(cut.map_parts().expect("a map").1.len(), 16);
3442
3443 let picked = column.gather(&[3, 0, 3]).unwrap();
3444 assert!(matches!(picked.logical_type(), LogicalType::Map(_, _)));
3445 assert_eq!(
3446 picked.iter().collect::<Vec<_>>(),
3447 [rows[3].clone(), rows[0].clone(), rows[3].clone()]
3448 );
3449 let past = column.gather(&[0, 99]).unwrap();
3450 assert_eq!(past.value_at(1), Value::Null);
3451 }
3452
3453 #[test]
3454 fn a_map_built_from_two_columns_pairs_them_by_position() {
3455 let keys = Vector::from_values(
3456 LogicalType::Varchar,
3457 &[Value::Varchar("a".to_string()), Value::Varchar("c".to_string())],
3458 )
3459 .unwrap();
3460 let values = Vector::from_values(
3461 LogicalType::Varchar,
3462 &[Value::Varchar("b".to_string()), Value::Varchar("d".to_string())],
3463 )
3464 .unwrap();
3465 let column = Vector::map(vec![(0, 2), (2, 0)], keys, values).expect("two rows");
3466 assert_eq!(column.len(), 2);
3467 assert_eq!(
3468 column.logical_type(),
3469 &LogicalType::map(LogicalType::Varchar, LogicalType::Varchar)
3470 );
3471 assert_eq!(column.value_at(0), tags(&[("a", "b"), ("c", "d")]));
3472 assert_eq!(column.value_at(1), tags(&[]));
3473 // The entry check the list constructor does is the one a map gets, so an entry past the end of
3474 // the pair of columns is refused here too rather than read as somebody else's keys.
3475 let short =
3476 Vector::from_values(LogicalType::Varchar, &[Value::Varchar("a".to_string())]).unwrap();
3477 let other =
3478 Vector::from_values(LogicalType::Varchar, &[Value::Varchar("b".to_string())]).unwrap();
3479 assert!(Vector::map(vec![(0, 9)], short, other).is_err(), "an entry past the end");
3480 }
3481
3482 /// `map_parts` is about the logical type and `list_parts` is about the layout, so a list has to
3483 /// decline the first and a map has to answer the second. Getting that backwards would let a kernel
3484 /// written for maps read a list of two field structs as if it were one.
3485 #[test]
3486 fn a_list_is_not_a_map_however_much_its_child_looks_like_one() {
3487 let pairs = Value::List { element: pair_type(), values: vec![pair(1, "x")] };
3488 let column =
3489 Vector::from_values(LogicalType::list(pair_type()), std::slice::from_ref(&pairs))
3490 .unwrap();
3491 assert!(column.map_parts().is_none(), "a list of structs is a list");
3492 assert!(column.list_parts().is_some());
3493 let map = tag_column(&[tags(&[("a", "b")])]);
3494 assert!(map.map_parts().is_some());
3495 assert!(map.list_parts().is_some(), "a map has a list's layout and says so");
3496 }
3497
3498 /// A struct row is not bytes and not an integer, and it stays that way when it has exactly one
3499 /// integer field, which is the case where answering about the field would look reasonable and would
3500 /// be a hash keyed on the wrong thing.
3501 #[test]
3502 fn the_scalar_readers_decline_a_struct_of_one_integer_field() {
3503 let ty = LogicalType::Struct(vec![Field::new("a", LogicalType::Integer)]);
3504 let row = Value::Struct(vec![("a".to_string(), Value::Integer(7))]);
3505 let column = Vector::from_values(ty, &[row]).unwrap();
3506 assert_eq!(column.signed_at(0), None);
3507 assert_eq!(column.bytes_at(0), None);
3508 assert_eq!(column.data(), None);
3509 }
3510
3511 #[test]
3512 fn a_clustered_column_becomes_runs_and_reads_back_the_same() {
3513 let mut values = Vec::new();
3514 for (value, times) in [(7, 400), (8, 300), (7, 324)] {
3515 values.extend(std::iter::repeat_n(value, times));
3516 }
3517 let flat = integers(&values);
3518 let runs = flat.run_encoded().unwrap();
3519 assert_eq!(runs.form(), Form::Rle);
3520 assert_eq!(runs.run_parts().expect("runs").0, [400, 700, 1024]);
3521 assert_eq!(runs.len(), flat.len());
3522 assert_eq!(runs.iter().collect::<Vec<_>>(), flat.iter().collect::<Vec<_>>());
3523 assert!(
3524 runs.footprint() * 10 < flat.footprint(),
3525 "three runs against a thousand rows: {} against {}",
3526 runs.footprint(),
3527 flat.footprint()
3528 );
3529 }
3530
3531 /// The check is worth having in both directions. A form that is only ever bigger than what it
3532 /// replaced is a form that costs a pass over the column to decide not to use.
3533 #[test]
3534 fn a_column_that_does_not_repeat_is_left_flat() {
3535 let flat = integers(&(0..1024).collect::<Vec<i32>>());
3536 assert_eq!(flat.run_encoded().unwrap().form(), Form::Flat);
3537 // Two runs over four rows is exactly break even on a four byte column, and break even is
3538 // not a reason to change form.
3539 assert_eq!(integers(&[1, 1, 2, 2]).run_encoded().unwrap().form(), Form::Flat);
3540 assert_eq!(integers(&[1, 1, 1, 2, 2]).run_encoded().unwrap().form(), Form::Rle);
3541 }
3542
3543 #[test]
3544 fn two_nulls_beside_each_other_are_one_run_and_a_null_between_two_equals_is_a_break() {
3545 let mut values = vec![Value::Integer(4), Value::Integer(4)];
3546 values.extend([Value::Null, Value::Null, Value::Null]);
3547 values.extend(std::iter::repeat_n(Value::Integer(4), 5));
3548 let flat = Vector::from_values(LogicalType::Integer, &values).unwrap();
3549 let runs = flat.run_encoded().unwrap();
3550 assert_eq!(runs.run_parts().expect("runs").0, [2, 5, 10]);
3551 assert_eq!(runs.iter().collect::<Vec<_>>(), values);
3552 }
3553
3554 #[test]
3555 fn slicing_runs_keeps_them_runs_and_cuts_the_first_and_last_one_back() {
3556 let flat = integers(&[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]);
3557 let runs = flat.run_encoded().unwrap();
3558 let piece = runs.slice(3, 6).unwrap();
3559 assert_eq!(piece.form(), Form::Rle, "the form is the whole point");
3560 assert_eq!(piece.run_parts().expect("runs").0, [1, 5, 6]);
3561 assert_eq!(
3562 piece.iter().collect::<Vec<_>>(),
3563 flat.slice(3, 6).unwrap().iter().collect::<Vec<_>>()
3564 );
3565 assert_eq!(runs.slice(0, 0).unwrap().len(), 0);
3566 assert_eq!(runs.slice(0, 12).unwrap().form(), Form::Rle);
3567 }
3568
3569 #[test]
3570 fn gathering_out_of_runs_walks_to_the_values_the_way_it_walks_a_dictionary() {
3571 let mut values = vec![Value::Varchar("red".into()); 4];
3572 values.extend([Value::Null, Value::Null, Value::Null]);
3573 values.extend(vec![Value::Varchar("blue".into()); 4]);
3574 let runs =
3575 Vector::from_values(LogicalType::Varchar, &values).unwrap().run_encoded().unwrap();
3576 assert_eq!(runs.form(), Form::Rle);
3577 let picked = runs.gather(&[8, 0, 5, 2]).unwrap();
3578 assert_eq!(picked.form(), Form::Flat, "a gather copies, whatever it gathered from");
3579 assert_eq!(
3580 picked.iter().collect::<Vec<_>>(),
3581 [values[8].clone(), values[0].clone(), Value::Null, values[2].clone()]
3582 );
3583 assert_eq!(runs.text_at(1), Some("red"));
3584 assert_eq!(runs.text_at(5), None, "a null has no text");
3585 assert_eq!(runs.flatten().unwrap().iter().collect::<Vec<_>>(), values);
3586 }
3587
3588 /// A run length vector over a run length vector turns one search per row into two, and there is
3589 /// nothing in the engine that builds one, so it is refused rather than composed.
3590 #[test]
3591 fn runs_of_runs_are_refused_and_runs_of_a_dictionary_are_not() {
3592 let inner = integers(&[1, 1, 1, 1, 2]).run_encoded().unwrap();
3593 assert_eq!(inner.form(), Form::Rle);
3594 let error = Vector::runs(vec![2, 8], inner).unwrap_err();
3595 assert!(error.to_string().contains("runs of runs"), "{error}");
3596
3597 let words = Vector::from_values(
3598 LogicalType::Varchar,
3599 &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
3600 )
3601 .unwrap();
3602 let dictionary = Vector::dictionary(vec![1, 0], words).unwrap();
3603 let stacked = Vector::runs(vec![4, 9], dictionary).unwrap();
3604 assert_eq!(stacked.len(), 9);
3605 assert_eq!(stacked.value_at(3), Value::Varchar("blue".into()));
3606 assert_eq!(stacked.value_at(4), Value::Varchar("red".into()));
3607 }
3608
3609 #[test]
3610 fn run_ends_have_to_increase_and_there_is_one_value_for_each_of_them() {
3611 let values = integers(&[1, 2]);
3612 assert!(Vector::runs(vec![4], values.clone()).is_err(), "two values and one run");
3613 assert!(Vector::runs(vec![4, 4], values.clone()).is_err(), "an end that repeats");
3614 assert!(Vector::runs(vec![4, 2], values.clone()).is_err(), "an end that goes backwards");
3615 assert!(Vector::runs(vec![0, 2], values.clone()).is_err(), "a first run holding no rows");
3616 assert_eq!(Vector::runs(vec![4, 9], values).unwrap().len(), 9);
3617 }
3618
3619 #[test]
3620 fn a_form_that_is_already_compact_is_left_where_it_is() {
3621 let constant = Vector::constant(LogicalType::Integer, Value::Integer(1), 1000);
3622 assert_eq!(constant.run_encoded().unwrap().form(), Form::Constant);
3623 assert_eq!(Vector::sequence(0, 1, 1000).run_encoded().unwrap().form(), Form::Sequence);
3624 }
3625
3626 /// What makes one accessor cover both forms. A dictionary hands back the codes it stores and a
3627 /// run length vector works the same numbers out, and a kernel writing `values[at[row]]` reads
3628 /// the same rows out of either.
3629 #[test]
3630 fn both_forms_that_point_somewhere_hand_back_a_position_per_row() {
3631 let words = Vector::from_values(
3632 LogicalType::Varchar,
3633 &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
3634 )
3635 .unwrap();
3636 let runs = Vector::runs(vec![3, 5], words.clone()).unwrap();
3637 let (at, values) = runs.positions().expect("runs point somewhere");
3638 assert_eq!(at.as_ref(), [0, 0, 0, 1, 1]);
3639 assert_eq!(values.value_at(at[3] as usize), runs.value_at(3));
3640
3641 let dictionary = Vector::dictionary(vec![1, 0, 1], words).unwrap();
3642 let (at, values) = dictionary.positions().expect("a dictionary points somewhere");
3643 assert_eq!(at.as_ref(), [1, 0, 1]);
3644 assert_eq!(values.value_at(at[0] as usize), dictionary.value_at(0));
3645
3646 assert!(integers(&[1, 2, 3]).positions().is_none(), "a flat vector points at itself");
3647 assert!(Vector::sequence(0, 1, 4).positions().is_none(), "a sequence stores nothing");
3648 }
3649
3650 #[test]
3651 fn slicing_a_dictionary_keeps_it_a_dictionary_where_gathering_would_not() {
3652 let values = Vector::from_values(
3653 LogicalType::Varchar,
3654 &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
3655 )
3656 .unwrap();
3657 let vector = Vector::dictionary(vec![0, 1, 1, 0, 1], values).unwrap();
3658
3659 let piece = vector.slice(1, 3).unwrap();
3660 assert_eq!(piece.form(), Form::Dictionary, "the form is the whole point");
3661 assert_eq!(piece.len(), 3);
3662 assert_eq!(
3663 piece.iter().collect::<Vec<_>>(),
3664 [
3665 Value::Varchar("blue".into()),
3666 Value::Varchar("blue".into()),
3667 Value::Varchar("red".into())
3668 ]
3669 );
3670 assert_eq!(vector.gather(&[1, 2, 3]).unwrap().form(), Form::Flat, "which a gather loses");
3671 }
3672
3673 #[test]
3674 fn slicing_a_dictionary_shares_the_dictionary_rather_than_copying_it() {
3675 // The assertion is about the address and not about the values, because the values were
3676 // right when the dictionary was copied too. A page holds one dictionary and is cut into a
3677 // chunk of codes at a time, so copying the dictionary here is a copy of every string in it
3678 // per chunk, and on a read of a ClickBench partition it was ten percent of the cycles.
3679 let values = Vector::from_values(
3680 LogicalType::Varchar,
3681 &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
3682 )
3683 .unwrap();
3684 let vector = Vector::dictionary(vec![0, 1, 1, 0, 1], values).unwrap();
3685 let Body::Dictionary { values: whole, .. } = &vector.body else {
3686 panic!("a dictionary vector holds a dictionary");
3687 };
3688
3689 let piece = vector.slice(1, 3).unwrap();
3690 let Body::Dictionary { codes, values: cut, .. } = &piece.body else {
3691 panic!("a slice of a dictionary is a dictionary");
3692 };
3693 assert!(Arc::ptr_eq(whole, cut), "the cut copied the dictionary");
3694 assert_eq!(codes, &[1, 1, 0], "the codes are the part that is cut");
3695
3696 // And a cut of a cut shares it too, since that is what a scan does to a page it reads twice.
3697 let again = piece.slice(1, 2).unwrap();
3698 let Body::Dictionary { values: cut, .. } = &again.body else {
3699 panic!("a slice of a slice of a dictionary is a dictionary");
3700 };
3701 assert!(Arc::ptr_eq(whole, cut), "the second cut copied the dictionary");
3702 assert_eq!(
3703 again.iter().collect::<Vec<_>>(),
3704 [Value::Varchar("blue".into()), Value::Varchar("red".into())]
3705 );
3706 }
3707
3708 #[test]
3709 fn a_slice_carries_the_nulls_that_were_in_its_range_and_not_the_others() {
3710 let vector =
3711 integers(&[1, 2, 3, 4]).with_validity(Validity::from_run(&[false, true, false, true]));
3712 let piece = vector.slice(1, 2).unwrap();
3713 assert!(piece.validity().is_valid(0));
3714 assert!(!piece.validity().is_valid(1));
3715 assert_eq!(piece.value_at(1), Value::Null);
3716 }
3717
3718 #[test]
3719 fn slicing_a_sequence_moves_its_start_rather_than_writing_the_values_out() {
3720 let vector = Vector::sequence(100, 5, 10);
3721 let piece = vector.slice(3, 4).unwrap();
3722 assert_eq!(piece.form(), Form::Sequence);
3723 assert_eq!(
3724 piece.iter().collect::<Vec<_>>(),
3725 [Value::BigInt(115), Value::BigInt(120), Value::BigInt(125), Value::BigInt(130)]
3726 );
3727 }
3728
3729 #[test]
3730 fn slicing_a_constant_is_a_shorter_constant() {
3731 let vector = Vector::constant(LogicalType::Integer, Value::Integer(9), 8);
3732 let piece = vector.slice(2, 3).unwrap();
3733 assert_eq!(piece.form(), Form::Constant);
3734 assert_eq!(piece.len(), 3);
3735 assert_eq!(piece.value_at(2), Value::Integer(9));
3736 }
3737
3738 #[test]
3739 fn slicing_the_whole_vector_hands_it_back_as_it_was() {
3740 let vector = integers(&[1, 2, 3]);
3741 assert_eq!(
3742 vector.slice(0, 3).unwrap().iter().collect::<Vec<_>>(),
3743 [Value::Integer(1), Value::Integer(2), Value::Integer(3)]
3744 );
3745 }
3746
3747 #[test]
3748 fn cutting_a_flat_body_answers_what_gathering_the_same_rows_answers() {
3749 // The cut of a flat body used to be written as a gather over the positions in the range,
3750 // and it is now a run copied out, so the two have to keep saying the same thing. Every
3751 // start and every length, with nulls in the range and out of it, since the validity is the
3752 // half of this that changed shape.
3753 let rows: Vec<i32> = (0..70).collect();
3754 let valid: Vec<bool> = (0..70).map(|row| row % 7 != 0 && row % 11 != 3).collect();
3755 let vector = integers(&rows).with_validity(Validity::from_run(&valid));
3756 for at in 0..70usize {
3757 for len in 0..=(70 - at) {
3758 let cut = vector.slice(at, len).unwrap();
3759 let positions: Vec<u32> = (at..at + len).map(|row| row as u32).collect();
3760 let gathered = vector.gather(&positions).unwrap();
3761 assert_eq!(cut.len(), len, "rows {at} to {}", at + len);
3762 assert_eq!(
3763 cut.iter().collect::<Vec<_>>(),
3764 gathered.iter().collect::<Vec<_>>(),
3765 "rows {at} to {}",
3766 at + len
3767 );
3768 }
3769 }
3770 }
3771
3772 #[test]
3773 fn cutting_a_flat_string_column_answers_what_gathering_it_answers() {
3774 // The string layout is the one whose cut is still a loop, and it is also the one where a
3775 // row is a view into an arena rather than a slot, so it gets the same treatment separately.
3776 // Both inline and out of line strings, since they are copied by different paths.
3777 let rows: Vec<String> =
3778 (0..40).map(|row| "x".repeat(row % 30) + &row.to_string()).collect();
3779 let values: Vec<Value> = rows.iter().map(|row| Value::Varchar(row.clone())).collect();
3780 let vector = Vector::from_values(LogicalType::Varchar, &values).unwrap().flatten().unwrap();
3781 assert_eq!(vector.form(), Form::Flat, "the cut under test is the flat one");
3782 for at in 0..40usize {
3783 for len in 0..=(40 - at) {
3784 let cut = vector.slice(at, len).unwrap();
3785 let positions: Vec<u32> = (at..at + len).map(|row| row as u32).collect();
3786 let gathered = vector.gather(&positions).unwrap();
3787 assert_eq!(
3788 cut.iter().collect::<Vec<_>>(),
3789 gathered.iter().collect::<Vec<_>>(),
3790 "rows {at} to {}",
3791 at + len
3792 );
3793 }
3794 }
3795 }
3796
3797 #[test]
3798 fn a_slice_past_the_end_is_an_error_rather_than_a_short_vector() {
3799 let error = integers(&[1, 2, 3]).slice(2, 2).unwrap_err();
3800 assert!(error.to_string().contains("of a vector of 3"), "{error}");
3801 }
3802
3803 #[test]
3804 fn the_vector_size_is_the_one_the_design_is_built_around() {
3805 // 1024 and not DuckDB's 2048. A validity mask is 16 u64 words and a vector of string views
3806 // is 16 KiB, both of which are consequences of this number rather than coincidences.
3807 assert_eq!(VECTOR_SIZE, 1024);
3808 assert_eq!(VECTOR_SIZE / 64, 16);
3809 }
3810
3811 #[test]
3812 fn a_flat_vector_reads_back_what_was_put_in_it() {
3813 let vector = integers(&[1, 2, 3]);
3814 assert_eq!(vector.form(), Form::Flat);
3815 assert_eq!(vector.len(), 3);
3816 assert_eq!(vector.value_at(1), Value::Integer(2));
3817 assert_eq!(
3818 vector.iter().collect::<Vec<_>>(),
3819 vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)]
3820 );
3821 }
3822
3823 #[test]
3824 fn a_vector_built_from_values_reads_the_same_values_back() {
3825 let vector = Vector::from_values(
3826 LogicalType::Varchar,
3827 &[
3828 Value::Varchar("a".to_string()),
3829 Value::Null,
3830 Value::Varchar("a string too long to sit inside a view".to_string()),
3831 ],
3832 )
3833 .expect("strings and a null");
3834 assert_eq!(vector.len(), 3);
3835 assert_eq!(vector.value_at(0), Value::Varchar("a".to_string()));
3836 assert_eq!(vector.value_at(1), Value::Null);
3837 assert_eq!(
3838 vector.value_at(2),
3839 Value::Varchar("a string too long to sit inside a view".to_string())
3840 );
3841 }
3842
3843 /// A null still occupies a position. If it did not then every value after it would read back
3844 /// one place to the left, which is the kind of bug that looks like a storage bug for a week.
3845 #[test]
3846 fn a_null_in_the_middle_does_not_move_the_values_after_it() {
3847 let vector = Vector::from_values(
3848 LogicalType::Integer,
3849 &[Value::Integer(1), Value::Null, Value::Integer(3)],
3850 )
3851 .expect("integers and a null");
3852 assert_eq!(vector.value_at(2), Value::Integer(3));
3853 assert!(vector.validity().has_nulls(3), "the middle one is null");
3854 }
3855
3856 #[test]
3857 fn a_value_the_type_cannot_hold_is_refused() {
3858 let wrong = Vector::from_values(LogicalType::Integer, &[Value::Varchar("x".to_string())]);
3859 assert!(wrong.is_err(), "a string is not an integer");
3860 }
3861
3862 #[test]
3863 fn a_type_that_does_not_match_its_layout_is_refused_at_construction() {
3864 // One comparison here against a wrong answer read out three layers later.
3865 let wrong = Vector::flat(LogicalType::Varchar, Data::Int32(vec![1].into()));
3866 assert!(wrong.is_err());
3867 let right = Vector::flat(LogicalType::Date, Data::Int32(vec![1].into()));
3868 assert!(right.is_ok(), "a date is stored in an i32 and that has to be allowed");
3869 }
3870
3871 #[test]
3872 fn a_constant_vector_costs_one_value_whatever_its_length() {
3873 let vector = Vector::constant(LogicalType::Integer, Value::Integer(7), VECTOR_SIZE);
3874 assert_eq!(vector.form(), Form::Constant);
3875 assert_eq!(vector.len(), VECTOR_SIZE);
3876 assert_eq!(vector.value_at(0), Value::Integer(7));
3877 assert_eq!(vector.value_at(VECTOR_SIZE - 1), Value::Integer(7));
3878 assert_eq!(vector.value_at(VECTOR_SIZE), Value::Null, "past the end is null, not a panic");
3879 }
3880
3881 #[test]
3882 fn a_constant_null_is_all_invalid_without_being_told() {
3883 let vector = Vector::constant(LogicalType::Integer, Value::Null, 8);
3884 assert_eq!(vector.validity(), &Validity::AllInvalid);
3885 assert_eq!(vector.value_at(3), Value::Null);
3886 }
3887
3888 #[test]
3889 fn a_sequence_vector_is_sixteen_bytes_of_row_identifiers() {
3890 let vector = Vector::sequence(100, 1, VECTOR_SIZE);
3891 assert_eq!(vector.form(), Form::Sequence);
3892 assert_eq!(vector.value_at(0), Value::BigInt(100));
3893 assert_eq!(vector.value_at(923), Value::BigInt(1023));
3894 let stepped = Vector::sequence(0, 5, 4);
3895 assert_eq!(
3896 stepped.iter().collect::<Vec<_>>(),
3897 vec![Value::BigInt(0), Value::BigInt(5), Value::BigInt(10), Value::BigInt(15)]
3898 );
3899 }
3900
3901 #[test]
3902 fn a_dictionary_vector_reads_through_its_codes() {
3903 let mut column = StringColumn::new();
3904 column.push("red");
3905 column.push("green");
3906 let values = Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap();
3907 let vector = Vector::dictionary(vec![0, 1, 1, 0], values).unwrap();
3908 assert_eq!(vector.form(), Form::Dictionary);
3909 assert_eq!(vector.logical_type(), &LogicalType::Varchar);
3910 assert_eq!(vector.value_at(2), Value::Varchar("green".into()));
3911 assert_eq!(vector.len(), 4);
3912 }
3913
3914 /// The accessor a group by keys a string column through, which has to agree with `value_at` on
3915 /// every position or two rows holding one string end up in two groups.
3916 #[test]
3917 fn text_is_read_where_it_already_is_for_the_forms_that_store_it() {
3918 let mut column = StringColumn::new();
3919 column.push("red");
3920 column.push("green");
3921 column.push("");
3922 let flat = Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap();
3923 for index in 0..flat.len() {
3924 assert_eq!(flat.text_at(index).map(str::to_string), text_of(&flat.value_at(index)));
3925 }
3926 let dictionary = Vector::dictionary(vec![1, 0, 1, 2], flat).unwrap();
3927 for index in 0..dictionary.len() {
3928 assert_eq!(
3929 dictionary.text_at(index).map(str::to_string),
3930 text_of(&dictionary.value_at(index))
3931 );
3932 }
3933 assert_eq!(dictionary.text_at(4), None, "past the end");
3934 }
3935
3936 /// The forms and types that have no text to hand back, which a caller answers by falling back
3937 /// to `value_at`. A blob is the one that would be a correctness bug rather than a slow path,
3938 /// since its bytes are not required to be text and it is not a `VARCHAR` either way.
3939 #[test]
3940 fn text_is_refused_where_it_is_not_stored_as_itself() {
3941 let nulls =
3942 Vector::from_values(LogicalType::Varchar, &[Value::Varchar("red".into()), Value::Null])
3943 .unwrap();
3944 assert_eq!(nulls.text_at(0), Some("red"));
3945 assert_eq!(nulls.text_at(1), None, "a null has no text");
3946 let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("red".into()), 3);
3947 assert_eq!(constant.text_at(0), None, "a constant is not stored per position");
3948 assert_eq!(integers(&[1, 2]).text_at(0), None, "an integer is not text");
3949 let mut bytes = StringColumn::new();
3950 bytes.push("red");
3951 let blob = Vector::flat(LogicalType::Blob, Data::Varlen(bytes)).unwrap();
3952 assert_eq!(blob.text_at(0), None, "a blob is not a varchar");
3953 }
3954
3955 /// The accessor a group by keys an integer column through, which has to agree with `value_at`
3956 /// on every position or two rows holding one number end up in two groups.
3957 #[test]
3958 fn a_signed_integer_is_read_where_it_already_is_for_the_forms_that_store_it() {
3959 let flat = integers(&[7, -3, 0, 2]);
3960 for index in 0..flat.len() {
3961 assert_eq!(flat.signed_at(index), signed_of(&flat.value_at(index)), "flat {index}");
3962 }
3963 let dictionary = Vector::dictionary(vec![1, 0, 3, 2], flat).unwrap();
3964 for index in 0..dictionary.len() {
3965 assert_eq!(
3966 dictionary.signed_at(index),
3967 signed_of(&dictionary.value_at(index)),
3968 "dictionary {index}"
3969 );
3970 }
3971 assert_eq!(dictionary.signed_at(4), None, "past the end");
3972
3973 let runs = Vector::runs(vec![2, 5], integers(&[4, 9])).unwrap();
3974 for index in 0..runs.len() {
3975 assert_eq!(runs.signed_at(index), signed_of(&runs.value_at(index)), "run {index}");
3976 }
3977 let constant = Vector::constant(LogicalType::BigInt, Value::BigInt(11), 3);
3978 assert_eq!(constant.signed_at(2), Some(11));
3979 let sequence = Vector::sequence(100, 5, 4);
3980 for index in 0..sequence.len() {
3981 assert_eq!(
3982 sequence.signed_at(index),
3983 signed_of(&sequence.value_at(index)),
3984 "sequence {index}"
3985 );
3986 }
3987 }
3988
3989 /// The forms and types that have no integer to hand back, which a caller answers by falling
3990 /// back to `value_at`.
3991 #[test]
3992 fn a_signed_integer_is_refused_where_it_is_not_stored_as_itself() {
3993 let nulls =
3994 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(4), Value::Null]).unwrap();
3995 assert_eq!(nulls.signed_at(0), Some(4));
3996 assert_eq!(nulls.signed_at(1), None, "a null is not a number");
3997 let packed = integers(&[1, 2, 3, 1]).bit_packed().unwrap();
3998 assert_eq!(packed.signed_at(0), Some(1), "a packed integer is read in code space");
3999 let mut bytes = StringColumn::new();
4000 bytes.push("red");
4001 let text = Vector::flat(LogicalType::Varchar, Data::Varlen(bytes)).unwrap();
4002 assert_eq!(text.signed_at(0), None, "a string is not a number");
4003 let double = Vector::flat(LogicalType::Double, Data::Float64(vec![1.5].into())).unwrap();
4004 assert_eq!(double.signed_at(0), None, "a double is not a signed integer");
4005 }
4006
4007 /// The integer of a value, for comparing `signed_at` against `value_at` position by position.
4008 fn signed_of(value: &Value) -> Option<i128> {
4009 match value {
4010 Value::TinyInt(x) => Some(i128::from(*x)),
4011 Value::SmallInt(x) => Some(i128::from(*x)),
4012 Value::Integer(x) | Value::Date(x) => Some(i128::from(*x)),
4013 Value::BigInt(x) | Value::Time(x) | Value::Timestamp(x) => Some(i128::from(*x)),
4014 Value::HugeInt(x) | Value::Decimal { unscaled: x, .. } => Some(*x),
4015 _ => None,
4016 }
4017 }
4018
4019 /// The text of a value, for comparing `text_at` against `value_at` position by position.
4020 fn text_of(value: &Value) -> Option<String> {
4021 match value {
4022 Value::Varchar(text) => Some(text.clone()),
4023 _ => None,
4024 }
4025 }
4026
4027 #[test]
4028 fn a_dictionary_code_past_the_end_is_refused() {
4029 // The alternative is a silent read of the wrong value, which is the failure mode the
4030 // entire M3 design has to be careful about.
4031 let values = integers(&[1, 2]);
4032 assert!(Vector::dictionary(vec![0, 2], values).is_err());
4033 // The check runs on the highest code rather than the first bad one, so it has to say that
4034 // no codes at all is fine even when there are no values for them to point at either.
4035 let empty = Vector::dictionary(Vec::new(), integers(&[])).expect("no codes, no values");
4036 assert_eq!(empty.len(), 0);
4037 // And a code of zero against an empty dictionary is still past the end.
4038 assert!(Vector::dictionary(vec![0], integers(&[])).is_err());
4039 }
4040
4041 #[test]
4042 fn every_form_flattens_to_the_same_values_it_reads_out() {
4043 // This is the shape of the equivalence testing in spec/16-testing.md section 16.2, in
4044 // miniature and long before there is an encoded kernel to point it at. A form that reads
4045 // out one way and flattens another is the exact bug that testing exists to catch.
4046 let mut column = StringColumn::new();
4047 column.push("alpha");
4048 column.push("beta");
4049 let dictionary = Vector::dictionary(
4050 vec![1, 0, 1],
4051 Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap(),
4052 )
4053 .unwrap();
4054 let cases = [
4055 Vector::constant(LogicalType::Integer, Value::Integer(3), 5),
4056 Vector::sequence(7, -2, 5),
4057 dictionary,
4058 ];
4059 for vector in cases {
4060 let flat = vector.flatten().unwrap();
4061 assert_eq!(flat.form(), Form::Flat);
4062 assert_eq!(flat.len(), vector.len());
4063 for index in 0..vector.len() {
4064 assert_eq!(flat.value_at(index), vector.value_at(index), "at {index}");
4065 }
4066 }
4067 }
4068
4069 #[test]
4070 fn a_null_still_occupies_a_position_after_flattening() {
4071 // The reason push_value writes a zero for a null rather than skipping it. A run of data
4072 // with a hole in it puts every value after the hole in the wrong place, and the validity
4073 // mask is what says the position is null.
4074 let vector = Vector::sequence(0, 1, 4).with_validity(Validity::from_iter(4, |i| i != 1));
4075 let flat = vector.flatten().unwrap();
4076 assert_eq!(flat.value_at(0), Value::BigInt(0));
4077 assert_eq!(flat.value_at(1), Value::Null);
4078 assert_eq!(flat.value_at(2), Value::BigInt(2));
4079 assert_eq!(flat.value_at(3), Value::BigInt(3));
4080 }
4081
4082 /// A dictionary holds its nulls in the vector it points at, so its own validity is all valid
4083 /// and reading that instead of the values turns a null into whatever zero means for the type.
4084 /// A filter over a nullable column produces exactly this vector, so the bug reaches a result
4085 /// set as `LEFT JOIN` padding that comes back as zeros.
4086 #[test]
4087 fn a_null_behind_a_dictionary_survives_flattening() {
4088 let values =
4089 Vector::from_values(LogicalType::Integer, &[Value::Integer(3), Value::Null]).unwrap();
4090 let dictionary = Vector::dictionary(vec![1, 0, 1], values).unwrap();
4091 let flat = dictionary.flatten().unwrap();
4092 assert_eq!(flat.value_at(0), Value::Null);
4093 assert_eq!(flat.value_at(1), Value::Integer(3));
4094 assert_eq!(flat.value_at(2), Value::Null);
4095 }
4096
4097 /// The property that makes `gather` usable at all: it has to be the same function as reading the
4098 /// wanted positions one at a time, over every form, or compaction changes answers.
4099 #[test]
4100 fn gathering_reads_what_reading_one_position_at_a_time_reads() {
4101 let mut column = StringColumn::new();
4102 column.push("alpha");
4103 column.push("beta");
4104 column.push("gamma");
4105 let cases = [
4106 integers(&[10, 20, 30, 40]),
4107 integers(&[10, 20, 30, 40]).with_validity(Validity::from_iter(4, |i| i != 2)),
4108 Vector::constant(LogicalType::Integer, Value::Integer(9), 4),
4109 Vector::sequence(100, -7, 4),
4110 Vector::sequence(100, -7, 4).with_validity(Validity::from_iter(4, |i| i % 2 == 0)),
4111 Vector::dictionary(
4112 vec![2, 0, 1, 2],
4113 Vector::flat(LogicalType::Varchar, Data::Varlen(column)).unwrap(),
4114 )
4115 .unwrap(),
4116 Vector::dictionary(
4117 vec![1, 0, 1, 0],
4118 Vector::from_values(LogicalType::Integer, &[Value::Integer(5), Value::Null])
4119 .unwrap(),
4120 )
4121 .unwrap(),
4122 ];
4123 let wanted = [3_u32, 0, 2, 2, 1];
4124 for vector in cases {
4125 let gathered = vector.gather(&wanted).unwrap();
4126 assert_eq!(gathered.len(), wanted.len());
4127 assert_eq!(gathered.logical_type(), vector.logical_type());
4128 for (slot, &index) in wanted.iter().enumerate() {
4129 assert_eq!(
4130 gathered.value_at(slot),
4131 vector.value_at(index as usize),
4132 "slot {slot} of {:?}",
4133 vector.form()
4134 );
4135 }
4136 }
4137 }
4138
4139 /// A gather past the end is not an error, because the selection that produced the indices is
4140 /// checked by its caller and the one thing that must not happen here is a read of the wrong
4141 /// value. An index nothing answers is null, which is what an outer join pad needs anyway.
4142 #[test]
4143 fn gathering_a_position_that_is_not_there_is_a_null_and_not_a_wrong_value() {
4144 let vector = integers(&[1, 2, 3]);
4145 let gathered = vector.gather(&[2, 9]).unwrap();
4146 assert_eq!(gathered.value_at(0), Value::Integer(3));
4147 assert_eq!(gathered.value_at(1), Value::Null);
4148 }
4149
4150 /// The vector with nothing in it at all, which is what an untyped `NULL` is stored as. Every
4151 /// position asked for is past its end, so the answer is nulls and the length has to be the
4152 /// length that was asked for rather than the length that was there.
4153 #[test]
4154 fn gathering_from_a_vector_of_no_values_is_that_many_nulls() {
4155 let vector = Vector::flat(LogicalType::Null, Data::Empty).unwrap();
4156 let gathered = vector.gather(&[0, 1, 2]).unwrap();
4157 assert_eq!(gathered.len(), 3);
4158 assert_eq!(gathered.value_at(0), Value::Null);
4159 assert_eq!(gathered.value_at(2), Value::Null);
4160 }
4161
4162 /// Every position holds the same value, so a gather with no hole in it has nothing to copy and
4163 /// the result is the constant again rather than a run of a thousand copies of it.
4164 #[test]
4165 fn gathering_a_constant_stays_a_constant() {
4166 let vector = Vector::constant(LogicalType::Integer, Value::Integer(4), 100);
4167 let gathered = vector.gather(&[7, 7, 99]).unwrap();
4168 assert_eq!(gathered.form(), Form::Constant);
4169 assert_eq!(gathered.len(), 3);
4170 assert_eq!(gathered.value_at(2), Value::Integer(4));
4171 }
4172
4173 /// A dictionary over a dictionary is what a second filter over an already filtered chunk builds,
4174 /// and the gather has to walk to the bottom of that chain rather than one step down it. The
4175 /// constructor composes the ordinary chain away, so the one built here is the kind it cannot,
4176 /// which is a level holding nulls of its own.
4177 #[test]
4178 fn gathering_walks_a_dictionary_over_a_dictionary_to_the_values() {
4179 let inner = Vector::dictionary(vec![2, 1, 0], integers(&[7, 8, 9]))
4180 .unwrap()
4181 .with_validity(Validity::from_iter(3, |index| index != 2));
4182 let outer = Vector::dictionary(vec![1, 2], inner).unwrap();
4183 let gathered = outer.gather(&[0, 1]).unwrap();
4184 assert_eq!(gathered.form(), Form::Flat);
4185 assert_eq!(gathered.value_at(0), Value::Integer(8));
4186 assert_eq!(gathered.value_at(1), Value::Null);
4187 }
4188
4189 /// Two filters over one chunk build a dictionary over a dictionary, four conjuncts pushed down
4190 /// separately build four levels of it, and every level is a dependent load on every later read
4191 /// of every row plus a code array that cannot be freed. Composing at construction is one pass
4192 /// over the codes the range check was walking anyway.
4193 #[test]
4194 fn a_dictionary_over_a_dictionary_is_composed_into_one_level() {
4195 let inner = Vector::dictionary(vec![2, 1, 0], integers(&[7, 8, 9])).unwrap();
4196 let outer = Vector::dictionary(vec![1, 2], inner).unwrap();
4197 let (codes, values) = outer.dictionary_parts().unwrap();
4198 assert_eq!(codes, [1, 0]);
4199 assert_eq!(values.form(), Form::Flat);
4200 assert_eq!(outer.value_at(0), Value::Integer(8));
4201 assert_eq!(outer.value_at(1), Value::Integer(7));
4202 }
4203
4204 /// The invariant stated as the thing it is there for, which is that the depth does not grow with
4205 /// the number of filters. Four levels stacked one at a time are one level at the end of it.
4206 #[test]
4207 fn stacking_dictionaries_does_not_make_them_deeper() {
4208 let mut vector = integers(&[10, 20, 30, 40]);
4209 for _ in 0..4 {
4210 vector = Vector::dictionary(vec![3, 2, 1, 0], vector).unwrap();
4211 }
4212 let (codes, values) = vector.dictionary_parts().unwrap();
4213 assert_eq!(values.form(), Form::Flat);
4214 assert_eq!(codes, [0, 1, 2, 3]);
4215 assert_eq!(
4216 vector.iter().collect::<Vec<_>>(),
4217 integers(&[10, 20, 30, 40]).iter().collect::<Vec<_>>()
4218 );
4219 }
4220
4221 /// Composing has to carry the nulls down with it. The values hold them, the codes point at them,
4222 /// and a composed code that lands on a null position is still a null.
4223 #[test]
4224 fn composing_a_dictionary_keeps_the_nulls_its_values_hold() {
4225 let values =
4226 Vector::from_values(LogicalType::Integer, &[Value::Integer(3), Value::Null]).unwrap();
4227 let inner = Vector::dictionary(vec![1, 0, 1], values).unwrap();
4228 let outer = Vector::dictionary(vec![0, 1], inner).unwrap();
4229 assert_eq!(outer.dictionary_parts().unwrap().1.form(), Form::Flat);
4230 assert_eq!(outer.value_at(0), Value::Null);
4231 assert_eq!(outer.value_at(1), Value::Integer(3));
4232 }
4233
4234 /// The one level composition cannot go past. A dictionary that was given a validity of its own is
4235 /// saying its nulls are at that level rather than in the values, and pointing the outer codes
4236 /// straight at the values would read through the holes instead of stopping at them.
4237 #[test]
4238 fn a_dictionary_holding_its_own_nulls_is_not_composed_past() {
4239 let inner = Vector::dictionary(vec![0, 1, 2], integers(&[1, 2, 3]))
4240 .unwrap()
4241 .with_validity(Validity::from_iter(3, |index| index != 1));
4242 let outer = Vector::dictionary(vec![1, 2, 0], inner).unwrap();
4243 assert_eq!(outer.dictionary_parts().unwrap().1.form(), Form::Dictionary);
4244 assert_eq!(outer.value_at(0), Value::Null);
4245 assert_eq!(outer.value_at(1), Value::Integer(3));
4246 assert_eq!(outer.value_at(2), Value::Integer(1));
4247 }
4248
4249 /// The difference between the two questions about nulls, which a group by got wrong. A filtered
4250 /// chunk is dictionary vectors, those are built with every row marked present at their own
4251 /// level, and the nulls are down in the values. So the mask says the row has a value and the
4252 /// row does not.
4253 #[test]
4254 fn a_null_behind_a_dictionary_reads_as_null_even_though_the_mask_says_otherwise() {
4255 let values = Vector::flat(LogicalType::Integer, Data::Int32(vec![0, 7].into()))
4256 .unwrap()
4257 .with_validity(Validity::from_iter(2, |index| index != 0));
4258 let vector = Vector::dictionary(vec![0, 1, 0], values).unwrap();
4259 assert!(vector.validity().is_valid(0), "the mask at this level says present");
4260 assert!(vector.is_null_at(0));
4261 assert!(!vector.is_null_at(1));
4262 assert!(vector.is_null_at(2));
4263 assert!(vector.is_null_at(3), "a row past the end is null");
4264 }
4265
4266 /// The same for runs, which are built the same way and keep their nulls in the same place.
4267 #[test]
4268 fn a_null_inside_a_run_reads_as_null_even_though_the_mask_says_otherwise() {
4269 let values = Vector::flat(LogicalType::Integer, Data::Int32(vec![0, 7].into()))
4270 .unwrap()
4271 .with_validity(Validity::from_iter(2, |index| index != 0));
4272 let vector = Vector::runs(vec![2, 3], values).unwrap();
4273 assert!(vector.validity().is_valid(0));
4274 assert!(vector.is_null_at(0));
4275 assert!(vector.is_null_at(1));
4276 assert!(!vector.is_null_at(2));
4277 }
4278
4279 /// Every other form keeps its nulls in its own mask, so the two answers agree there.
4280 #[test]
4281 fn the_forms_that_hold_their_own_nulls_answer_the_same_either_way() {
4282 let flat = Vector::flat(LogicalType::Integer, Data::Int32(vec![0, 7].into()))
4283 .unwrap()
4284 .with_validity(Validity::from_iter(2, |index| index != 0));
4285 let constant = Vector::constant(LogicalType::Integer, Value::Null, 2);
4286 let sequence = Vector::sequence(10, 2, 2);
4287 for vector in [flat, constant, sequence] {
4288 for row in 0..vector.len() {
4289 assert_eq!(vector.is_null_at(row), !vector.validity().is_valid(row));
4290 }
4291 }
4292 }
4293
4294 #[test]
4295 fn flattening_a_flat_vector_is_the_same_vector() {
4296 let vector = integers(&[1, 2, 3]);
4297 assert_eq!(vector.flatten().unwrap(), vector);
4298 }
4299
4300 #[test]
4301 fn a_decimal_reads_its_width_and_scale_from_the_type_and_not_the_data() {
4302 let ty = LogicalType::decimal(9, 2).unwrap();
4303 let vector = Vector::flat(ty, Data::Int32(vec![1234].into())).unwrap();
4304 assert_eq!(vector.value_at(0), Value::Decimal { unscaled: 1234, width: 9, scale: 2 });
4305 assert_eq!(vector.value_at(0).to_string(), "12.34");
4306 }
4307
4308 #[test]
4309 fn a_decimal_writes_into_whichever_of_the_four_runs_its_precision_chose() {
4310 // The read path worked at every width and the write path only accepted the 128 bit run, so
4311 // `SELECT 2.5` produced a value nothing could store. All four widths round trip now.
4312 for (width, scale, unscaled) in
4313 [(4u8, 1u8, 25i128), (9, 2, 1234), (18, 3, 123_456), (38, 4, 1_234_567)]
4314 {
4315 let ty = LogicalType::decimal(width, scale).unwrap();
4316 let value = Value::Decimal { unscaled, width, scale };
4317 let vector = Vector::from_values(ty, &[value.clone(), Value::Null]).unwrap();
4318 assert_eq!(vector.value_at(0), value, "a decimal of width {width}");
4319 assert_eq!(vector.value_at(1), Value::Null, "a null decimal of width {width}");
4320 }
4321 }
4322
4323 /// The bytes a blob holds are not required to be text, and a vector of them used to refuse the
4324 /// ones that were not. A byte array column in a Parquet file that nothing annotated is a blob,
4325 /// which is what ClickHouse writes and what ten of the ClickBench queries compare against, so
4326 /// this is the path those take rather than a corner of the type system.
4327 #[test]
4328 fn a_blob_holds_bytes_that_are_not_text() {
4329 let bytes = |raw: &[u8]| Value::Blob(raw.to_vec());
4330 let values = [
4331 bytes(b"a\xffb"),
4332 bytes(b"\x00\x01\x02"),
4333 Value::Null,
4334 bytes(b"\xed\xa0\x80 and long enough to leave the view"),
4335 bytes(b""),
4336 ];
4337 let vector = Vector::from_values(LogicalType::Blob, &values).unwrap();
4338 for (index, value) in values.iter().enumerate() {
4339 assert_eq!(&vector.value_at(index), value, "row {index}");
4340 }
4341 }
4342
4343 #[test]
4344 fn a_decimal_too_wide_for_the_run_its_type_chose_is_an_error_and_not_a_wrong_number() {
4345 // Only reachable by hand, since a value's width is what picked the run. Truncating here
4346 // would store a different number and say nothing about it.
4347 let ty = LogicalType::decimal(4, 1).unwrap();
4348 let value = Value::Decimal { unscaled: 1_000_000, width: 4, scale: 1 };
4349 let error = Vector::from_values(ty, &[value]).unwrap_err();
4350 assert!(error.to_string().contains("does not fit"), "{error}");
4351 }
4352
4353 #[test]
4354 fn a_flat_vector_costs_its_values_and_a_constant_costs_one() {
4355 let flat = integers(&[1; 1000]);
4356 assert!(
4357 flat.footprint() >= 4000,
4358 "a thousand i32 are four thousand bytes: {}",
4359 flat.footprint()
4360 );
4361 // The forms that compute their values rather than storing them cost nothing per value,
4362 // which is the point of having them and is what the memory limit should see.
4363 let constant = Vector::constant(LogicalType::Integer, Value::Integer(1), 1_000_000);
4364 assert!(constant.footprint() < 200, "a constant is one value: {}", constant.footprint());
4365 let sequence = Vector::sequence(0, 1, 1_000_000);
4366 assert!(sequence.footprint() < 200, "a sequence is two numbers: {}", sequence.footprint());
4367 }
4368
4369 #[test]
4370 fn a_string_vector_costs_the_bytes_of_its_long_strings() {
4371 let short =
4372 Vector::from_values(LogicalType::Varchar, &[Value::Varchar("red".into())]).unwrap();
4373 let long = "a string well past the sixteen bytes a view holds inline".to_string();
4374 let spilled =
4375 Vector::from_values(LogicalType::Varchar, &[Value::Varchar(long.clone())]).unwrap();
4376 assert!(
4377 spilled.footprint() >= short.footprint() + long.len(),
4378 "the arena is counted: {} against {}",
4379 spilled.footprint(),
4380 short.footprint()
4381 );
4382 }
4383
4384 /// The cases worth checking are the widths where a code straddles a word boundary, which is
4385 /// every width that does not divide sixty four, and the two ends of the range.
4386 #[test]
4387 fn a_narrow_column_packs_and_reads_back_the_same_at_every_width() {
4388 for width in 1..=20u32 {
4389 let span = (1i64 << width) - 1;
4390 let values: Vec<i64> =
4391 (0..1000).map(|row| 1_000_000 + (row * 7919) % (span + 1)).collect();
4392 let flat =
4393 Vector::flat(LogicalType::BigInt, Data::Int64(values.clone().into())).unwrap();
4394 let packed = flat.bit_packed().unwrap();
4395 assert_eq!(packed.len(), flat.len());
4396 assert_eq!(
4397 packed.iter().collect::<Vec<_>>(),
4398 flat.iter().collect::<Vec<_>>(),
4399 "width {width} read back differently"
4400 );
4401 }
4402 }
4403
4404 #[test]
4405 fn the_width_is_the_bits_the_range_needs_and_not_the_bits_the_type_has() {
4406 let values: Vec<i32> = (0..1024).map(|row| 40 + (row * 2560) / 1023).collect();
4407 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
4408 let packed = flat.bit_packed().unwrap();
4409 assert_eq!(packed.form(), Form::BitPacked);
4410 let parts = packed.packed_parts().expect("packed");
4411 assert_eq!(parts.width(), 12, "0 to 2560 is twelve bits");
4412 assert_eq!(parts.base(), 40);
4413 assert!(
4414 packed.footprint() * 2 < flat.footprint(),
4415 "twelve bits against thirty two: {} against {}",
4416 packed.footprint(),
4417 flat.footprint()
4418 );
4419 }
4420
4421 /// The check is worth having in both directions, the way the run length one is. A form that is
4422 /// only ever bigger than what it replaced costs a pass over the column to decide not to use.
4423 #[test]
4424 fn a_column_that_uses_its_whole_type_is_left_flat() {
4425 let values: Vec<i32> = (0..1024).map(|row| row * 2_000_000 - 1_000_000_000).collect();
4426 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
4427 assert_eq!(flat.bit_packed().unwrap().form(), Form::Flat);
4428 }
4429
4430 /// A column of one value would pack to no bits at all, and one run is smaller than any packing
4431 /// of it, so the two forms do not fight over that column.
4432 #[test]
4433 fn a_column_of_one_value_is_left_to_the_run_length_form() {
4434 let flat = integers(&[9; 1024]);
4435 assert_eq!(flat.bit_packed().unwrap().form(), Form::Flat);
4436 assert_eq!(flat.run_encoded().unwrap().form(), Form::Rle);
4437 }
4438
4439 #[test]
4440 fn a_string_column_has_no_range_to_pack() {
4441 let text = Vector::from_values(
4442 LogicalType::Varchar,
4443 &[Value::Varchar("red".into()), Value::Varchar("blue".into())],
4444 )
4445 .unwrap();
4446 assert_eq!(text.bit_packed().unwrap().form(), Form::Flat);
4447 }
4448
4449 /// The cut is the reason the form carries a row to start reading at. It stays packed, it shares
4450 /// the same words, and it reads the rows the range asked for.
4451 #[test]
4452 fn a_cut_of_a_packed_column_stays_packed_and_shares_its_bits() {
4453 let values: Vec<i32> = (0..1024).map(|row| 100 + row % 300).collect();
4454 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
4455 let packed = flat.bit_packed().unwrap();
4456 let cut = packed.slice(500, 24).unwrap();
4457 assert_eq!(cut.form(), Form::BitPacked);
4458 assert_eq!(cut.len(), 24);
4459 assert_eq!(
4460 cut.iter().collect::<Vec<_>>(),
4461 flat.slice(500, 24).unwrap().iter().collect::<Vec<_>>()
4462 );
4463 assert!(
4464 cut.footprint() >= packed.footprint(),
4465 "a cut shares the words rather than copying a piece of them"
4466 );
4467 }
4468
4469 #[test]
4470 fn a_gather_of_a_packed_column_comes_out_flat_and_keeps_the_nulls() {
4471 let values: Vec<i32> = (0..64).map(|row| 10 + row).collect();
4472 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
4473 let packed =
4474 flat.bit_packed().unwrap().with_validity(Validity::from_iter(64, |row| row % 3 != 0));
4475 let taken = packed.gather(&[0, 1, 2, 3, 62]).unwrap();
4476 assert_eq!(taken.form(), Form::Flat);
4477 assert_eq!(
4478 taken.iter().collect::<Vec<_>>(),
4479 vec![
4480 Value::Null,
4481 Value::Integer(11),
4482 Value::Integer(12),
4483 Value::Null,
4484 Value::Integer(72)
4485 ]
4486 );
4487 }
4488
4489 /// The pair a comparison kernel asks for before it reads a bit. A literal inside the range has a
4490 /// code and a literal outside it does not, which answers the whole vector at once.
4491 #[test]
4492 fn a_literal_outside_the_packed_range_has_no_code() {
4493 let values: Vec<i32> = (0..256).map(|row| 1000 + row).collect();
4494 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into())).unwrap();
4495 let packed = flat.bit_packed().unwrap();
4496 let parts = packed.packed_parts().expect("packed");
4497 assert_eq!(parts.code_of(1000), Some(0));
4498 assert_eq!(parts.code_of(1100), Some(100));
4499 assert_eq!(parts.code_of(999), None);
4500 assert!(parts.ceiling() >= 1255);
4501 assert_eq!(parts.code_of(parts.ceiling() + 1), None);
4502 }
4503
4504 /// The bits arriving from a file rather than from a flat vector, which is what the form is for.
4505 #[test]
4506 fn packed_bits_can_be_handed_in_without_a_flat_vector_to_start_from() {
4507 let packed = Vector::packed(LogicalType::SmallInt, vec![0x0000_0000_0000_4321], 4, 7, 4)
4508 .expect("four codes of four bits");
4509 assert_eq!(
4510 packed.iter().collect::<Vec<_>>(),
4511 vec![Value::SmallInt(8), Value::SmallInt(9), Value::SmallInt(10), Value::SmallInt(11)]
4512 );
4513 }
4514
4515 #[test]
4516 fn packed_bits_that_could_not_hold_what_they_claim_are_refused() {
4517 assert!(Vector::packed(LogicalType::Varchar, vec![0], 4, 0, 4).is_err(), "not an integer");
4518 assert!(Vector::packed(LogicalType::Integer, vec![0], 0, 0, 4).is_err(), "no width");
4519 assert!(Vector::packed(LogicalType::Integer, vec![0], 64, 0, 4).is_err(), "too wide");
4520 assert!(Vector::packed(LogicalType::Integer, vec![0], 8, 0, 9).is_err(), "too few words");
4521 assert!(Vector::packed(LogicalType::TinyInt, vec![0], 8, 100, 8).is_err(), "would not fit");
4522 }
4523
4524 /// A column of strings long enough that the payload is in the arena rather than in the views.
4525 fn long_strings(count: usize) -> Vector {
4526 let values: Vec<Value> = (0..count)
4527 .map(|row| {
4528 Value::Varchar(format!("a string too long to sit inside a view, number {row}"))
4529 })
4530 .collect();
4531 Vector::from_values(LogicalType::Varchar, &values).unwrap()
4532 }
4533
4534 #[test]
4535 fn a_string_column_in_view_form_reads_back_the_same_strings() {
4536 let flat = long_strings(40);
4537 let shared = flat.clone().shared_text().unwrap();
4538 assert_eq!(shared.form(), Form::StringView);
4539 assert_eq!(shared.len(), 40);
4540 for row in 0..40 {
4541 assert_eq!(shared.value_at(row), flat.value_at(row), "row {row}");
4542 assert_eq!(shared.text_at(row), flat.text_at(row), "row {row}");
4543 }
4544 }
4545
4546 #[test]
4547 fn a_short_string_is_read_out_of_its_view_and_never_out_of_the_arena() {
4548 let flat = Vector::from_values(
4549 LogicalType::Varchar,
4550 &[Value::Varchar("red".into()), Value::Varchar("green".into()), Value::Null],
4551 )
4552 .unwrap();
4553 let shared = flat.shared_text().unwrap();
4554 // Nothing went to the arena, so the whole column resolves with an empty one.
4555 let (views, arena) = shared.text_parts().unwrap();
4556 assert!(arena.is_empty(), "three short strings need no arena");
4557 assert_eq!(views[0].bytes_in(arena), Some(&b"red"[..]));
4558 assert_eq!(shared.value_at(1), Value::Varchar("green".into()));
4559 assert_eq!(shared.value_at(2), Value::Null, "the validity came across");
4560 }
4561
4562 #[test]
4563 fn a_cut_of_a_view_column_shares_the_arena_rather_than_copying_the_bytes() {
4564 let shared = long_strings(64).shared_text().unwrap();
4565 let cut = shared.slice(16, 8).unwrap();
4566 assert_eq!(cut.form(), Form::StringView, "a cut of views is views");
4567 assert_eq!(cut.len(), 8);
4568 assert_eq!(cut.value_at(0), shared.value_at(16));
4569 assert_eq!(cut.value_at(7), shared.value_at(23));
4570 // The arena is the same bytes at the same address, which is the whole point of the form.
4571 let (_, whole) = shared.text_parts().unwrap();
4572 let (_, piece) = cut.text_parts().unwrap();
4573 assert_eq!(piece.as_ptr(), whole.as_ptr(), "the cut shares the page");
4574 assert_eq!(piece.len(), whole.len());
4575 }
4576
4577 #[test]
4578 fn a_flat_string_column_has_to_copy_the_bytes_its_cut_keeps() {
4579 let flat = long_strings(64);
4580 let cut = flat.slice(16, 8).unwrap();
4581 assert_eq!(cut.form(), Form::Flat);
4582 let (_, whole) = flat.text_parts().unwrap();
4583 let (_, piece) = cut.text_parts().unwrap();
4584 assert!(piece.len() < whole.len(), "the flat cut carries only what it kept");
4585 }
4586
4587 #[test]
4588 fn a_gather_of_a_view_column_keeps_the_form_and_a_flatten_copies_out_of_it() {
4589 let shared = long_strings(32).shared_text().unwrap();
4590 let picked: Vec<u32> = (0..32).step_by(3).collect();
4591 let gathered = shared.gather(&picked).unwrap();
4592 assert_eq!(gathered.form(), Form::StringView, "selecting rows moves views, not bytes");
4593 assert_eq!(gathered.len(), picked.len());
4594 for (row, &from) in picked.iter().enumerate() {
4595 assert_eq!(gathered.value_at(row), shared.value_at(from as usize), "row {row}");
4596 }
4597 let flattened = gathered.flatten().unwrap();
4598 assert_eq!(flattened.form(), Form::Flat);
4599 assert_eq!(flattened.iter().collect::<Vec<_>>(), gathered.iter().collect::<Vec<_>>());
4600 // The flatten is what narrows the bytes, so the arena it built holds only the rows it kept.
4601 let (_, narrowed) = flattened.text_parts().unwrap();
4602 let (_, whole) = shared.text_parts().unwrap();
4603 assert!(narrowed.len() < whole.len(), "flattening lets the page go");
4604 }
4605
4606 #[test]
4607 fn a_null_in_a_view_column_survives_being_gathered_and_flattened() {
4608 let shared = long_strings(8)
4609 .with_validity(Validity::from_iter(8, |row| row % 3 != 0))
4610 .shared_text()
4611 .unwrap();
4612 let gathered = shared.gather(&[0, 1, 2, 3, 4]).unwrap();
4613 let expected =
4614 [Value::Null, shared.value_at(1), shared.value_at(2), Value::Null, shared.value_at(4)];
4615 assert_eq!(gathered.iter().collect::<Vec<_>>(), expected);
4616 assert_eq!(gathered.flatten().unwrap().iter().collect::<Vec<_>>(), expected);
4617 }
4618
4619 #[test]
4620 fn both_string_forms_hand_a_kernel_the_same_views_and_the_same_bytes() {
4621 let flat = long_strings(6);
4622 let shared = flat.clone().shared_text().unwrap();
4623 let (flat_views, flat_arena) = flat.text_parts().unwrap();
4624 let (shared_views, shared_arena) = shared.text_parts().unwrap();
4625 assert_eq!(flat_views.len(), shared_views.len());
4626 for row in 0..6 {
4627 assert_eq!(
4628 flat_views[row].bytes_in(flat_arena),
4629 shared_views[row].bytes_in(shared_arena),
4630 "row {row}"
4631 );
4632 }
4633 // Nothing else answers this, which is what keeps a kernel from taking it for a string column.
4634 assert!(Vector::sequence(0, 1, 4).text_parts().is_none());
4635 assert!(integers(&[1, 2, 3]).text_parts().is_none());
4636 }
4637
4638 #[test]
4639 fn a_column_that_is_not_strings_cannot_be_held_as_views() {
4640 let views = vec![StringView::inline("red")];
4641 let arena = Arc::new(Buffer::new());
4642 let wrong = Vector::string_views(LogicalType::Integer, views, arena);
4643 assert!(wrong.is_err(), "an integer column has no views");
4644 assert_eq!(integers(&[1, 2]).shared_text().unwrap().form(), Form::Flat, "left alone");
4645 }
4646
4647 /// A column with enough repeated structure for a symbol table to find something, which is what
4648 /// a real text column has and a column of random bytes does not.
4649 fn sentences(count: usize) -> Vector {
4650 let values: Vec<Value> = (0..count)
4651 .map(|row| {
4652 Value::Varchar(format!(
4653 "http://example.test/catalogue/section/{}/item/{row}",
4654 row % 7
4655 ))
4656 })
4657 .collect();
4658 Vector::from_values(LogicalType::Varchar, &values).unwrap()
4659 }
4660
4661 #[test]
4662 fn a_compressed_column_reads_back_the_strings_that_went_into_it() {
4663 let flat = sentences(64);
4664 let coded = flat.clone().compressed().unwrap();
4665 assert_eq!(coded.form(), Form::Fsst, "a text column compresses");
4666 assert_eq!(coded.len(), 64);
4667 for row in 0..64 {
4668 assert_eq!(coded.value_at(row), flat.value_at(row), "row {row}");
4669 }
4670 assert_eq!(coded.flatten().unwrap(), flat, "flattening is the column it came from");
4671 }
4672
4673 #[test]
4674 fn compressing_halves_the_bytes_or_the_column_is_left_flat() {
4675 let flat = sentences(200);
4676 let coded = flat.clone().compressed().unwrap();
4677 let parts = coded.coded_parts().expect("compressed");
4678 // Read through the flat column, because the compressed one has no bytes to hand back where
4679 // they are and answers `None` to `text_at` rather than decompressing into a borrow.
4680 assert_eq!(coded.text_at(0), None, "nothing to borrow until it is flattened");
4681 let plain: usize = (0..200).map(|row| flat.text_at(row).map_or(0, str::len)).sum();
4682 let codes: usize = (0..200).map(|row| parts.row(row).map_or(0, <[u8]>::len)).sum();
4683 assert!(codes * FSST_PAYS_AT <= plain, "{codes} codes against {plain} bytes");
4684 // Text with no repeated structure in it gives a table nothing longer than a byte to find,
4685 // so the codes are the bytes and the column stays where it is rather than paying a
4686 // decompression per read to save nothing.
4687 let mut seed = 0x2545_f491_4f6c_dd1du64;
4688 let values: Vec<Value> = (0..256)
4689 .map(|_| {
4690 let mut text = String::new();
4691 while text.len() < 12 {
4692 seed = seed.wrapping_mul(6_364_136_223_846_793_005).wrapping_add(1);
4693 text.push(char::from(b'!' + ((seed >> 33) % 90) as u8));
4694 }
4695 Value::Varchar(text)
4696 })
4697 .collect();
4698 let noise = Vector::from_values(LogicalType::Varchar, &values).unwrap();
4699 assert_eq!(noise.compressed().unwrap().form(), Form::Flat);
4700 }
4701
4702 #[test]
4703 fn a_cut_of_a_compressed_column_shares_the_codes_and_the_table() {
4704 let coded = sentences(64).compressed().unwrap();
4705 let cut = coded.slice(8, 16).unwrap();
4706 assert_eq!(cut.form(), Form::Fsst);
4707 assert_eq!(cut.len(), 16);
4708 for row in 0..16 {
4709 assert_eq!(cut.value_at(row), coded.value_at(8 + row), "row {row}");
4710 }
4711 let (whole, piece) = (coded.coded_parts().unwrap(), cut.coded_parts().unwrap());
4712 assert_eq!(piece.row(0), whole.row(8), "the spans point into the same codes");
4713 }
4714
4715 #[test]
4716 fn a_gather_of_a_compressed_column_stays_compressed_and_keeps_the_nulls() {
4717 let coded = sentences(32)
4718 .with_validity(Validity::from_iter(32, |row| row % 5 != 2))
4719 .compressed()
4720 .unwrap();
4721 let picked: Vec<u32> = (0..32).step_by(2).collect();
4722 let gathered = coded.gather(&picked).unwrap();
4723 assert_eq!(gathered.form(), Form::Fsst, "selecting rows moves spans, not bytes");
4724 for (row, &from) in picked.iter().enumerate() {
4725 assert_eq!(gathered.value_at(row), coded.value_at(from as usize), "row {row}");
4726 }
4727 assert_eq!(
4728 gathered.flatten().unwrap().iter().collect::<Vec<_>>(),
4729 gathered.iter().collect::<Vec<_>>()
4730 );
4731 }
4732
4733 #[test]
4734 fn a_literal_lands_in_the_same_codes_the_row_holding_it_does() {
4735 let coded = sentences(40).compressed().unwrap();
4736 let parts = coded.coded_parts().expect("compressed");
4737 let text = coded.value_at(11);
4738 let Value::Varchar(text) = text else { panic!("a string column reads back strings") };
4739 assert_eq!(parts.encode(text.as_bytes()), parts.row(11).expect("row 11"));
4740 assert_ne!(parts.encode(b"something else entirely"), parts.row(11).unwrap());
4741 }
4742
4743 #[test]
4744 fn codes_that_run_past_what_is_there_are_refused() {
4745 let table = Arc::new(SymbolTable::empty());
4746 let codes = Arc::new(vec![1u8, 2, 3, 4]);
4747 let good = vec![(0u32, 2u32), (2, 4)];
4748 assert!(
4749 Vector::coded(LogicalType::Varchar, Arc::clone(&codes), good, Arc::clone(&table))
4750 .is_ok()
4751 );
4752 let past = vec![(0u32, 9u32)];
4753 assert!(
4754 Vector::coded(LogicalType::Varchar, Arc::clone(&codes), past, Arc::clone(&table))
4755 .is_err(),
4756 "a span past the end of the codes"
4757 );
4758 let backwards = vec![(3u32, 1u32)];
4759 assert!(
4760 Vector::coded(LogicalType::Varchar, Arc::clone(&codes), backwards, Arc::clone(&table))
4761 .is_err(),
4762 "a span that ends before it starts"
4763 );
4764 let wrong = vec![(0u32, 2u32)];
4765 assert!(
4766 Vector::coded(LogicalType::Integer, codes, wrong, table).is_err(),
4767 "an integer column has no codes"
4768 );
4769 }
4770
4771 #[test]
4772 fn a_view_pointing_past_its_arena_is_refused_at_construction() {
4773 let long = "a string too long to sit inside a view";
4774 let arena: Arc<Buffer<u8>> = Arc::new(long.as_bytes().to_vec().into());
4775 let good = vec![StringView::over(long.as_bytes(), 0)];
4776 assert!(Vector::string_views(LogicalType::Varchar, good, Arc::clone(&arena)).is_ok());
4777 let bad = vec![StringView::over(long.as_bytes(), 4)];
4778 assert!(
4779 Vector::string_views(LogicalType::Varchar, bad, arena).is_err(),
4780 "four bytes short of what the view claims"
4781 );
4782 }
4783}