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