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