Skip to main content

rudb_graph/
keymap.rs

1//! Turning a parent key value into a [`Rid`].
2//!
3//! A link is built from an equality between a child column and a parent column, and to build it the
4//! parent column's values have to become row ids. That map is the key map. It has the three
5//! physical forms of spec/graph/02-the-data-model.md section 2.2, chosen by measurement at build
6//! time rather than by declaration, and the form that was chosen is recorded in the header so that
7//! a reader does not have to guess.
8//!
9//! The three exist because they are three different answers to the same question and the cheapest
10//! one is usually available:
11//!
12//! - [`Form::Identity`] when the keys are exactly `base .. base + n` in order. Nothing is stored
13//!   but two numbers, and TPC-H hits this on six of its eight tables.
14//! - [`Form::Dense`] when the keys are distinct integers packed densely enough into a range that a
15//!   bitmap plus a rank index beats storing them.
16//! - [`Form::Permuted`] when the keys are dense in their range the way the second form needs, but
17//!   the rows are not stored in key order. The same bitmap and rank, and then a permutation from
18//!   rank to `rid`, because a rank is a `rid` only while the rows are in key order.
19//! - [`Form::Sorted`] for everything else, including every string key, which arrives here as
20//!   dictionary codes rather than as text.
21//!
22//! The fourth exists because the stored order is a choice, and spec/graph/12-the-order-the-suite-
23//! asks-for.md section 12.5 makes it one. `orders` stored by date holds the same keys `orders`
24//! stored by key does, and a map that answered one in constant time and needed the budget four times
25//! over for the other would make the layer depend on the order it was supposed to be free to pick.
26//!
27//! What is deliberately absent is a hash. A minimal perfect hash is faster to probe than the sorted
28//! form and much slower to build, and there is no measurement yet saying the probe is where the
29//! time goes. spec/graph/11-open-questions.md keeps it open, and adding it later costs nothing
30//! because the form is a tag in a header that a reader is already required to be able to not
31//! recognize.
32
33use rudb_common::{Error, Result};
34use rudb_encoding::bitpack;
35
36use crate::bits::Rank;
37use crate::rid::Rid;
38
39/// How dense a range has to be before the bitmap form beats the sorted form.
40///
41/// One in eight, per section 2.2. Below it the bitmap is larger than storing the keys: a bitmap
42/// costs `range / 8` bytes plus about an eighth again for the rank index, and the sorted form costs
43/// `count` keys plus `count` permutation entries, so the crossover is a ratio rather than a size.
44/// The default is here as a named constant rather than inline because it is a number somebody will
45/// want to move once there is a measurement that says where, and moving it should be a diff.
46pub const DENSE_THRESHOLD: u64 = 8;
47
48/// Which of the three physical forms a key map took.
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum Form {
51    /// `rid = key - base`, and nothing is stored but `base` and the count.
52    Identity,
53    /// `rid = rank(key - base)` over a bitmap of the range, with a two level rank index.
54    Dense,
55    /// Binary search over the sorted keys, then a permutation lookup.
56    Sorted,
57    /// `rid = perm[rank(key - base)]`, the dense form with a permutation behind it.
58    Permuted,
59}
60
61impl Form {
62    /// The tag this form takes in a section header.
63    #[must_use]
64    pub fn tag(self) -> u8 {
65        match self {
66            Self::Identity => 0,
67            Self::Dense => 1,
68            Self::Sorted => 2,
69            Self::Permuted => 3,
70        }
71    }
72
73    /// What this form is called where a person reads it, which is `rudb_links()`.
74    #[must_use]
75    pub fn label(self) -> &'static str {
76        match self {
77            Self::Identity => "identity",
78            Self::Dense => "dense",
79            Self::Sorted => "sorted",
80            Self::Permuted => "permuted",
81        }
82    }
83
84    /// The form a header tag names.
85    ///
86    /// # Errors
87    ///
88    /// If the tag is not one of the three. A reader that meets an unfamiliar form has met a file
89    /// written by a later build, and the right response is the one section 3.2 requires of an
90    /// unfamiliar section kind: ignore this key map and answer the query without it. So this
91    /// returns an error and the caller drops the section rather than failing the open.
92    pub fn from_tag(tag: u8) -> Result<Self> {
93        match tag {
94            0 => Ok(Self::Identity),
95            1 => Ok(Self::Dense),
96            2 => Ok(Self::Sorted),
97            3 => Ok(Self::Permuted),
98            _ => Err(malformed(format!("key map form {tag} is not one this build knows"))),
99        }
100    }
101}
102
103/// What the build saw while it read the parent key column.
104///
105/// This is the cardinality verification of section 2.3, and it is written into the header rather
106/// than recomputed because the build already had every value in front of it. Recording what was
107/// observed rather than what was declared is what keeps a wrong `FOREIGN KEY` from producing a
108/// wrong answer: a declaration that fails verification is reported, and no link is built.
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
110pub struct Observed {
111    /// Non-null values seen.
112    pub rows: u64,
113    /// Nulls seen, which are not keys and match no child row.
114    pub nulls: u64,
115    /// Whether every non-null value was distinct. False means no link may be built at all.
116    pub distinct: bool,
117    /// Whether the values arrived in non-decreasing order.
118    pub sorted: bool,
119    /// The smallest non-null value, or `None` when there were none.
120    pub min: Option<i128>,
121    /// The largest non-null value, or `None` when there were none.
122    pub max: Option<i128>,
123}
124
125impl Observed {
126    /// Whether this column can be the parent side of a link.
127    ///
128    /// Distinctness is the whole requirement. A parent side that is not unique is not an error and
129    /// is not a link: section 2.3 says it is a relationship that has to be executed as an ordinary
130    /// join, and the planner is told so rather than left to find out.
131    #[must_use]
132    pub fn usable_as_parent(&self) -> bool {
133        self.distinct
134    }
135}
136
137/// The three forms, behind one interface.
138#[derive(Debug, Clone)]
139enum Body {
140    Identity {
141        base: i128,
142        count: u64,
143    },
144    Dense {
145        base: i128,
146        range: u64,
147        bits: Vec<u64>,
148        rank: Rank,
149    },
150    Sorted {
151        /// The smallest key, so that every stored key is a `u64` offset from it whatever the
152        /// column's own type was.
153        base: i128,
154        /// Bits one stored key offset takes.
155        key_width: usize,
156        /// The key offsets in ascending order, bit packed.
157        keys: Vec<u8>,
158        /// Bits one permutation entry takes, which is `ceil(log2(rows))`.
159        rid_width: usize,
160        /// Sorted position to `rid`, bit packed.
161        perm: Vec<u8>,
162        count: u64,
163    },
164    Permuted {
165        base: i128,
166        range: u64,
167        bits: Vec<u64>,
168        rank: Rank,
169        /// Bits one permutation entry takes, which is `ceil(log2(rows))`.
170        rid_width: usize,
171        /// Rank to `rid`, bit packed, one entry per key.
172        perm: Vec<u8>,
173    },
174}
175
176/// A map from a parent key value to the `rid` of the row that holds it.
177#[derive(Debug, Clone)]
178pub struct KeyMap {
179    body: Body,
180    observed: Observed,
181}
182
183impl KeyMap {
184    /// Builds the cheapest correct form for these keys.
185    ///
186    /// `keys` is the parent key column in `rid` order, with `None` for a null. The `rid` of a value
187    /// is its index, which is what makes this the whole build: the caller has already read the
188    /// column in append order, so the row ids are the positions and there is nothing to look up.
189    ///
190    /// String keys arrive here as dictionary codes rather than as text, per section 2.2. That is
191    /// not a convenience, it is the reason a sorted key map over a `VARCHAR` column never touches a
192    /// byte of text: the codes of a file wide stable dictionary are integers with the column's own
193    /// order, so the search is over `u32`.
194    ///
195    /// # Errors
196    ///
197    /// If the column's values span more than a `u64`, if it holds more rows than a `u64` of
198    /// `rid`s, or if a bit packed payload cannot be written. A non-distinct column is not an
199    /// error: it produces a key map whose [`Observed`] says so, and the caller is expected to ask
200    /// before building a link on it.
201    pub fn build(keys: &[Option<i128>]) -> Result<Self> {
202        let mut observed = observe(keys);
203        // See [`KeyMap::build_from`], which takes the same shortcut for the same reason and is
204        // where the reason is written. The two paths agree on every column or a table's key map
205        // depends on which of them built it.
206        if !observed.distinct {
207            return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
208        }
209        Ok(match plan(&observed)? {
210            Plan::Empty => Self { body: Body::Identity { base: 0, count: 0 }, observed },
211            Plan::Identity { base, count } => {
212                Self { body: Body::Identity { base, count }, observed }
213            }
214            Plan::Dense { base, range } => Self { body: dense(keys, base, range)?, observed },
215            Plan::Permuted { base, range } => {
216                let mut bits = DenseBits::new(base, range);
217                for key in keys.iter().flatten() {
218                    if !bits.mark(*key)? {
219                        observed.distinct = false;
220                        return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
221                    }
222                }
223                let mut perm = Permutation::new(bits, keys.len())?;
224                for (rid, key) in keys.iter().enumerate() {
225                    if let Some(key) = *key {
226                        perm.place(key, rid)?;
227                    }
228                }
229                Self { body: perm.finish()?, observed }
230            }
231            Plan::Sorted { base } => {
232                // The sorted form sorts, so it is the one place distinctness can be settled for a
233                // column that did not arrive in order. `observe` can only see an adjacent
234                // duplicate; this sees every duplicate, and the answer replaces the guess.
235                let (body, distinct) = sorted(keys, base, observed.rows)?;
236                observed.distinct = distinct;
237                Self { body, observed }
238            }
239        })
240    }
241
242    /// Builds the cheapest correct form by reading the column rather than by holding it.
243    ///
244    /// The same build as [`KeyMap::build`] and the same decision, taken from a source that can be
245    /// scanned twice instead of from a slice that is already in memory. That difference is the
246    /// whole reason this exists. A parent key column at TPC-H SF10 is fifteen million rows of
247    /// `orders`, and a `Vec<Option<i128>>` of those is four hundred and eighty megabytes held for
248    /// the length of a build that does not need a single one of them twice. At SF100 it is four and
249    /// a half gigabytes, which is not a slow build, it is a build that does not happen.
250    ///
251    /// So the first scan observes and nothing else, and what the second scan does depends on what
252    /// the first one found. The identity form, which is the form every TPC-H parent key takes,
253    /// needs no second scan at all: the four observed facts are the whole map. The dense form fills
254    /// a bitmap sized from the range, which is bounded by the table rather than by the scan. Only
255    /// the sorted form has to hold the column, because sorting is what it is, and it says so here
256    /// rather than surprising a caller with it.
257    ///
258    /// # Errors
259    ///
260    /// If the scan fails, or for any of the reasons [`KeyMap::build`] fails.
261    pub fn build_from<K: Keys + ?Sized>(keys: &K) -> Result<Self> {
262        let mut observer = Observer::new();
263        keys.scan(&mut |key| {
264            observer.push(key);
265            Ok(())
266        })?;
267        let mut observed = observer.observed;
268        // A column the first scan already saw a repeat in gets no body at all. No form answers a
269        // rid for a key that is in two rows, so every byte spent on one is spent on a map nothing
270        // may use, and the bytes are not small: TPC-H SF10 `lineitem(l_orderkey)` sorts sixty
271        // million keys into three hundred and ninety megabytes before the budget throws all of it
272        // away. This is only reachable where the duplicates are adjacent, which is where the column
273        // arrived in order, and that is the case this is for. A repeat that only the sort can find
274        // is still found by the sort, below.
275        if !observed.distinct {
276            return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
277        }
278        Ok(match plan(&observed)? {
279            Plan::Empty => Self { body: Body::Identity { base: 0, count: 0 }, observed },
280            Plan::Identity { base, count } => {
281                Self { body: Body::Identity { base, count }, observed }
282            }
283            Plan::Dense { base, range } => {
284                let mut bits = DenseBits::new(base, range);
285                keys.scan(&mut |key| match key {
286                    Some(key) => bits.push(key),
287                    None => Ok(()),
288                })?;
289                Self { body: bits.finish(), observed }
290            }
291            Plan::Permuted { base, range } => {
292                // Three scans rather than one that holds the column. The second marks the bitmap,
293                // and is where a repeat the first scan could not see is found, since a key is
294                // marked twice only when two rows hold it. The third places each row at its key's
295                // rank. Holding the column instead would be sixteen bytes a row for the length of
296                // the build, which is the cost `build_from` exists to avoid.
297                let mut bits = DenseBits::new(base, range);
298                let mut repeated = false;
299                keys.scan(&mut |key| {
300                    if let Some(key) = key {
301                        repeated |= !bits.mark(key)?;
302                    }
303                    Ok(())
304                })?;
305                if repeated {
306                    observed.distinct = false;
307                    return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
308                }
309                let rows = observed.rows + observed.nulls;
310                let rows = usize::try_from(rows)
311                    .map_err(|_| malformed("the column is too long for this machine"))?;
312                let mut perm = Permutation::new(bits, rows)?;
313                let mut rid = 0_usize;
314                keys.scan(&mut |key| {
315                    if let Some(key) = key {
316                        perm.place(key, rid)?;
317                    }
318                    rid += 1;
319                    Ok(())
320                })?;
321                Self { body: perm.finish()?, observed }
322            }
323            Plan::Sorted { base } => {
324                let mut held = Vec::with_capacity(
325                    usize::try_from(observed.rows + observed.nulls).unwrap_or_default(),
326                );
327                keys.scan(&mut |key| {
328                    held.push(key);
329                    Ok(())
330                })?;
331                let (body, distinct) = sorted(&held, base, observed.rows)?;
332                observed.distinct = distinct;
333                Self { body, observed }
334            }
335        })
336    }
337
338    /// Which form this map took.
339    #[must_use]
340    pub fn form(&self) -> Form {
341        match self.body {
342            Body::Identity { .. } => Form::Identity,
343            Body::Dense { .. } => Form::Dense,
344            Body::Sorted { .. } => Form::Sorted,
345            Body::Permuted { .. } => Form::Permuted,
346        }
347    }
348
349    /// The smallest key and how many key values from it the map spans, when the keys are compact.
350    ///
351    /// The identity and dense forms are the two that exist because the keys fill most of a range,
352    /// at most one hole in [`DENSE_THRESHOLD`] values, so a bitmap over that range is at most that
353    /// many bits a parent row. That is what lets a join test a child's key against a set of parents
354    /// with one subtraction and one bit, and with no link at all. The permuted form spans the same
355    /// range the dense one does, since the span is about the keys and not about where their rows
356    /// are. The sorted form is the one for keys spread over a range too wide for that, and answers
357    /// `None`.
358    #[must_use]
359    pub fn span(&self) -> Option<(i128, u64)> {
360        match self.body {
361            Body::Identity { base, count } => Some((base, count)),
362            Body::Dense { base, range, .. } | Body::Permuted { base, range, .. } => {
363                Some((base, range))
364            }
365            Body::Sorted { .. } => None,
366        }
367    }
368
369    /// What the build saw, which is the cardinality verification.
370    #[must_use]
371    pub fn observed(&self) -> &Observed {
372        &self.observed
373    }
374
375    /// The value every stored key is an offset from, which is the smallest key.
376    pub(crate) fn base(&self) -> i128 {
377        match &self.body {
378            Body::Identity { base, .. }
379            | Body::Dense { base, .. }
380            | Body::Sorted { base, .. }
381            | Body::Permuted { base, .. } => *base,
382        }
383    }
384
385    /// Appends the form's own bytes, after the header that `wire` has already written.
386    ///
387    /// Nothing here is stored that the header and the form together derive. The identity form
388    /// writes nothing at all, because its count is the header's row count, which is section 3.3's
389    /// "no extents beyond the header" in code rather than in prose.
390    pub(crate) fn write_body(&self, out: &mut Vec<u8>) -> Result<()> {
391        match &self.body {
392            Body::Identity { .. } => Ok(()),
393            Body::Dense { range, bits, rank, .. } => {
394                out.extend_from_slice(&range.to_le_bytes());
395                for word in bits {
396                    out.extend_from_slice(&word.to_le_bytes());
397                }
398                rank.write(out);
399                Ok(())
400            }
401            Body::Sorted { key_width, keys, rid_width, perm, .. } => {
402                // The widths are a byte each, and a width past sixty four is a width no `u64` key
403                // offset can have taken, so it is a torn header rather than a wide key.
404                let widths = [*key_width, *rid_width];
405                for width in widths {
406                    let width = u8::try_from(width)
407                        .map_err(|_| malformed("a sorted key map's width does not fit a byte"))?;
408                    out.push(width);
409                }
410                out.extend_from_slice(keys);
411                out.extend_from_slice(perm);
412                Ok(())
413            }
414            Body::Permuted { range, bits, rank, rid_width, perm, .. } => {
415                // The dense form's bytes and then the permutation, so that everything up to the
416                // rank index reads the way the dense form's does. The rank index's length follows
417                // from the range, which is how a reader finds where the permutation starts.
418                out.extend_from_slice(&range.to_le_bytes());
419                for word in bits {
420                    out.extend_from_slice(&word.to_le_bytes());
421                }
422                rank.write(out);
423                let width = u8::try_from(*rid_width)
424                    .map_err(|_| malformed("a permuted key map's width does not fit a byte"))?;
425                out.push(width);
426                out.extend_from_slice(perm);
427                Ok(())
428            }
429        }
430    }
431
432    /// Reads back what [`KeyMap::write_body`] wrote, and fills in the maximum key.
433    ///
434    /// The maximum is not in the header because each form derives it: identity from its count,
435    /// dense from its range, sorted from its last stored key. That is the whole reason this takes
436    /// [`Observed`] and returns a map rather than taking a finished one.
437    ///
438    /// # Errors
439    ///
440    /// If the body is not exactly the length its header implies. Exactly, not at least: a body
441    /// longer than its form needs means the header and the body disagree about which form this is,
442    /// and the safe reading of a disagreement is neither of them.
443    pub(crate) fn read_body(
444        form: Form,
445        base: i128,
446        mut observed: Observed,
447        body: &[u8],
448    ) -> Result<Self> {
449        match form {
450            Form::Identity => {
451                if !body.is_empty() {
452                    return Err(malformed("an identity key map has no body"));
453                }
454                if observed.rows > 0 {
455                    observed.max = Some(
456                        base.checked_add(i128::from(observed.rows) - 1)
457                            .ok_or_else(|| malformed("an identity key map's range overflows"))?,
458                    );
459                }
460                Ok(Self { body: Body::Identity { base, count: observed.rows }, observed })
461            }
462            Form::Dense => {
463                let Some(head) = body.get(..size_of::<u64>()) else {
464                    return Err(malformed("a dense key map has no range"));
465                };
466                let range = u64::from_le_bytes(head.try_into().expect("eight bytes"));
467                let Ok(range_usize) = usize::try_from(range) else {
468                    return Err(malformed("a dense key map's range does not fit this machine"));
469                };
470                let words = range_usize.div_ceil(64);
471                let bitmap = words * size_of::<u64>();
472                let rest = &body[size_of::<u64>()..];
473                if rest.len() < bitmap {
474                    return Err(malformed("a dense key map's bitmap is shorter than its range"));
475                }
476                let bits: Vec<u64> = rest[..bitmap]
477                    .chunks_exact(size_of::<u64>())
478                    .map(|word| u64::from_le_bytes(word.try_into().expect("eight bytes")))
479                    .collect();
480                let rank = Rank::read(&rest[bitmap..], words)?;
481                observed.max = Some(
482                    base.checked_add(i128::from(range) - 1)
483                        .ok_or_else(|| malformed("a dense key map's range overflows"))?,
484                );
485                Ok(Self { body: Body::Dense { base, range, bits, rank }, observed })
486            }
487            Form::Sorted => {
488                if body.len() < 2 {
489                    return Err(malformed("a sorted key map has no widths"));
490                }
491                let key_width = usize::from(body[0]);
492                let rid_width = usize::from(body[1]);
493                if key_width == 0 || key_width > 64 || rid_width == 0 || rid_width > 64 {
494                    return Err(malformed("a sorted key map's width is not one a u64 can take"));
495                }
496                let count = observed.rows;
497                let Ok(count_usize) = usize::try_from(count) else {
498                    return Err(malformed(
499                        "a sorted key map holds more keys than this machine can",
500                    ));
501                };
502                let key_bytes = (count_usize * key_width).div_ceil(8);
503                let perm_bytes = (count_usize * rid_width).div_ceil(8);
504                let rest = &body[2..];
505                if rest.len() != key_bytes + perm_bytes {
506                    return Err(malformed(
507                        "a sorted key map's arrays are not the size its widths and count imply",
508                    ));
509                }
510                let keys = rest[..key_bytes].to_vec();
511                let perm = rest[key_bytes..].to_vec();
512                if count > 0 {
513                    let largest = bitpack::tail_at(&keys, key_width, count_usize - 1)?;
514                    observed.max =
515                        Some(base.checked_add(i128::from(largest)).ok_or_else(|| {
516                            malformed("a sorted key map's largest key overflows")
517                        })?);
518                }
519                Ok(Self {
520                    body: Body::Sorted { base, key_width, keys, rid_width, perm, count },
521                    observed,
522                })
523            }
524            Form::Permuted => {
525                let Some(head) = body.get(..size_of::<u64>()) else {
526                    return Err(malformed("a permuted key map has no range"));
527                };
528                let range = u64::from_le_bytes(head.try_into().expect("eight bytes"));
529                let Ok(range_usize) = usize::try_from(range) else {
530                    return Err(malformed("a permuted key map's range does not fit this machine"));
531                };
532                let words = range_usize.div_ceil(64);
533                let bitmap = words * size_of::<u64>();
534                let (blocks, superblocks) = Rank::shape(words);
535                let ranks = superblocks * size_of::<u32>() + blocks * size_of::<u16>();
536                let rest = &body[size_of::<u64>()..];
537                if rest.len() < bitmap + ranks + 1 {
538                    return Err(malformed("a permuted key map is shorter than its range implies"));
539                }
540                let bits: Vec<u64> = rest[..bitmap]
541                    .chunks_exact(size_of::<u64>())
542                    .map(|word| u64::from_le_bytes(word.try_into().expect("eight bytes")))
543                    .collect();
544                let rank = Rank::read(&rest[bitmap..bitmap + ranks], words)?;
545                let rid_width = usize::from(rest[bitmap + ranks]);
546                if rid_width == 0 || rid_width > 64 {
547                    return Err(malformed("a permuted key map's width is not one a u64 can take"));
548                }
549                let Ok(count) = usize::try_from(observed.rows) else {
550                    return Err(malformed(
551                        "a permuted key map holds more keys than this machine can",
552                    ));
553                };
554                let perm = rest[bitmap + ranks + 1..].to_vec();
555                if perm.len() != (count * rid_width).div_ceil(8) {
556                    return Err(malformed(
557                        "a permuted key map's permutation is not the size its width and count imply",
558                    ));
559                }
560                observed.max = Some(
561                    base.checked_add(i128::from(range) - 1)
562                        .ok_or_else(|| malformed("a permuted key map's range overflows"))?,
563                );
564                Ok(Self {
565                    body: Body::Permuted { base, range, bits, rank, rid_width, perm },
566                    observed,
567                })
568            }
569        }
570    }
571
572    /// Keys this map resolves.
573    #[must_use]
574    pub fn len(&self) -> u64 {
575        match &self.body {
576            Body::Identity { count, .. } | Body::Sorted { count, .. } => *count,
577            Body::Dense { .. } | Body::Permuted { .. } => self.observed.rows,
578        }
579    }
580
581    /// Whether this map resolves nothing.
582    #[must_use]
583    pub fn is_empty(&self) -> bool {
584        self.len() == 0
585    }
586
587    /// Bytes this map holds resident, for the budget of section 3.7 and the cache of section 4.4.
588    ///
589    /// Identity is twenty four bytes and says so, which is the number that makes the budget
590    /// livable on TPC-H.
591    #[must_use]
592    pub fn bytes(&self) -> usize {
593        match &self.body {
594            Body::Identity { .. } => size_of::<i128>() + size_of::<u64>(),
595            Body::Dense { bits, rank, .. } => bits.len() * size_of::<u64>() + rank.bytes(),
596            Body::Sorted { keys, perm, .. } => keys.len() + perm.len(),
597            Body::Permuted { bits, rank, perm, .. } => {
598                bits.len() * size_of::<u64>() + rank.bytes() + perm.len()
599            }
600        }
601    }
602
603    /// The rows holding a set of keys, where the set is a bitmap over [`Self::span`] and so is the
604    /// answer, over the `rows` rows of the parent.
605    ///
606    /// The same set a [`Self::lookup`] of every key in `held` would make, for a walk over the words
607    /// of the two bitmaps. A key's row in the dense form is how many keys come before it, and the
608    /// word it sits in says that for all sixty four of its keys at once, so the rank is kept running
609    /// from one word to the next rather than asked for again at each key. On TPC-H q21 a lookup
610    /// at a time was about 185 instructions a key, over the three hundred thousand `lineitem` keys
611    /// two of its joins hold, and the join had already set the same keys in a bitmap over the span.
612    ///
613    /// `held` may run one word past the span, which is what a join's bitmap does so that a key past
614    /// the end has somewhere to land, as long as nothing past the span is set.
615    ///
616    /// `None` when the map has no span, which is the sorted form, or when `held` holds a key the
617    /// map does not, which a caller answers the way it would a key [`Self::lookup`] did not find.
618    ///
619    /// # Errors
620    ///
621    /// If a bit packed payload is torn, the same as [`Self::lookup`].
622    pub fn rows_of_span(&self, held: &[u64], rows: u64) -> Result<Option<Vec<u64>>> {
623        let words = usize::try_from(rows.div_ceil(64)).unwrap_or(usize::MAX);
624        let Some((_, range)) = self.span() else { return Ok(None) };
625        let span_words = usize::try_from(range.div_ceil(64)).unwrap_or(usize::MAX);
626        if held.len() < span_words || held[span_words..].iter().any(|&word| word != 0) {
627            return Ok(None);
628        }
629        // The last word of the span is only partly inside it.
630        if range % 64 != 0 && held[span_words - 1] >> (range % 64) != 0 {
631            return Ok(None);
632        }
633        let held = &held[..span_words];
634        let mut out = vec![0_u64; words];
635        match &self.body {
636            Body::Identity { count, .. } => {
637                if *count > rows {
638                    return Ok(None);
639                }
640                out[..span_words].copy_from_slice(held);
641            }
642            Body::Dense { bits, .. } => {
643                if bits.len() < held.len() {
644                    return Ok(None);
645                }
646                let mut before = 0_u64;
647                for (&keys, &present) in held.iter().zip(bits) {
648                    if keys & !present != 0 {
649                        return Ok(None);
650                    }
651                    let mut left = keys;
652                    while left != 0 {
653                        let below = (1_u64 << left.trailing_zeros()) - 1;
654                        let rid = before + u64::from((present & below).count_ones());
655                        let Some(word) = out.get_mut((rid / 64) as usize) else { return Ok(None) };
656                        *word |= 1 << (rid % 64);
657                        left &= left - 1;
658                    }
659                    before += u64::from(present.count_ones());
660                }
661            }
662            Body::Permuted { bits, rid_width, perm, .. } => {
663                if bits.len() < held.len() {
664                    return Ok(None);
665                }
666                let mut before = 0_u64;
667                for (&keys, &present) in held.iter().zip(bits) {
668                    if keys & !present != 0 {
669                        return Ok(None);
670                    }
671                    let mut left = keys;
672                    while left != 0 {
673                        let below = (1_u64 << left.trailing_zeros()) - 1;
674                        let place = before + u64::from((present & below).count_ones());
675                        #[expect(
676                            clippy::cast_possible_truncation,
677                            reason = "a rank is below the key count, which the build checked fits a usize"
678                        )]
679                        let rid = bitpack::tail_at(perm, *rid_width, place as usize)?;
680                        let Some(word) = out.get_mut((rid / 64) as usize) else { return Ok(None) };
681                        *word |= 1 << (rid % 64);
682                        left &= left - 1;
683                    }
684                    before += u64::from(present.count_ones());
685                }
686            }
687            Body::Sorted { .. } => return Ok(None),
688        }
689        if !rows.is_multiple_of(64) && out.last().is_some_and(|&word| word >> (rows % 64) != 0) {
690            return Ok(None);
691        }
692        Ok(Some(out))
693    }
694
695    /// The `rid` of the row holding this key, or `None` when no row holds it.
696    ///
697    /// `None` is the ordinary answer and not an exceptional one: a child key with no matching
698    /// parent is what section 2.4 reserves *no parent* for, and a null child key never reaches
699    /// here at all.
700    ///
701    /// # Errors
702    ///
703    /// If a bit packed payload is torn, which is a corrupt section rather than a missing key.
704    pub fn lookup(&self, key: i128) -> Result<Option<Rid>> {
705        match &self.body {
706            Body::Identity { base, count } => {
707                let Some(offset) = key.checked_sub(*base) else {
708                    return Ok(None);
709                };
710                match u64::try_from(offset) {
711                    Ok(rid) if rid < *count => Ok(Some(rid)),
712                    _ => Ok(None),
713                }
714            }
715            Body::Dense { base, range, bits, rank } => {
716                let Some(offset) = key.checked_sub(*base) else {
717                    return Ok(None);
718                };
719                let Ok(offset) = u64::try_from(offset) else {
720                    return Ok(None);
721                };
722                if offset >= *range {
723                    return Ok(None);
724                }
725                #[expect(
726                    clippy::cast_possible_truncation,
727                    reason = "the build checked the range fits a usize"
728                )]
729                let at = offset as usize;
730                if bits[at / 64] >> (at % 64) & 1 == 0 {
731                    return Ok(None);
732                }
733                Ok(Some(rank.rank(bits, at)))
734            }
735            Body::Permuted { base, range, bits, rank, rid_width, perm } => {
736                let Some(offset) = key.checked_sub(*base) else {
737                    return Ok(None);
738                };
739                let Ok(offset) = u64::try_from(offset) else {
740                    return Ok(None);
741                };
742                if offset >= *range {
743                    return Ok(None);
744                }
745                #[expect(
746                    clippy::cast_possible_truncation,
747                    reason = "the build checked the range fits a usize"
748                )]
749                let at = offset as usize;
750                if bits[at / 64] >> (at % 64) & 1 == 0 {
751                    return Ok(None);
752                }
753                #[expect(
754                    clippy::cast_possible_truncation,
755                    reason = "a rank is below the key count, which the build checked fits a usize"
756                )]
757                let place = rank.rank(bits, at) as usize;
758                Ok(Some(bitpack::tail_at(perm, *rid_width, place)?))
759            }
760            Body::Sorted { base, key_width, keys, rid_width, perm, count } => {
761                let Some(offset) = key.checked_sub(*base) else {
762                    return Ok(None);
763                };
764                let Ok(wanted) = u64::try_from(offset) else {
765                    return Ok(None);
766                };
767                #[expect(
768                    clippy::cast_possible_truncation,
769                    reason = "the build refused a column wider than a usize of rows"
770                )]
771                let len = *count as usize;
772                // A plain binary search over the packed keys. Branchless in the sense that matters
773                // here, which is that the comparison drives an index rather than a branch to a
774                // different loop, and every probe is one `tail_at` rather than a decode of the
775                // block around it.
776                let mut low = 0_usize;
777                let mut high = len;
778                while low < high {
779                    let mid = low + (high - low) / 2;
780                    let at = bitpack::tail_at(keys, *key_width, mid)?;
781                    if at < wanted {
782                        low = mid + 1;
783                    } else {
784                        high = mid;
785                    }
786                }
787                if low >= len || bitpack::tail_at(keys, *key_width, low)? != wanted {
788                    return Ok(None);
789                }
790                Ok(Some(bitpack::tail_at(perm, *rid_width, low)?))
791            }
792        }
793    }
794}
795
796/// A parent key column that can be read more than once, in `rid` order.
797///
798/// The build wants two passes over a column it does not want to hold, so this is what it reads
799/// instead of a slice: something that can be asked to produce the column again. A file can do that
800/// for the price of a read, and the second read is against pages the first one just warmed.
801///
802/// Values arrive as `Option<i128>`, with `None` for a null. A string key arrives as its dictionary
803/// code rather than as text, per section 2.2, which is why one integer signature covers every key
804/// type rudb has.
805pub trait Keys {
806    /// Calls `each` once per row of the column, in `rid` order.
807    ///
808    /// # Errors
809    ///
810    /// If the column cannot be read, or if `each` fails, which stops the scan rather than
811    /// continuing past a value that could not be used.
812    fn scan(&self, each: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()>;
813}
814
815impl Keys for [Option<i128>] {
816    fn scan(&self, each: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()> {
817        for key in self {
818            each(*key)?;
819        }
820        Ok(())
821    }
822}
823
824/// Which form the build chose, decided once and carried out twice.
825///
826/// Separating the decision from the filling is what lets [`KeyMap::build`] and
827/// [`KeyMap::build_from`] be the same build. A second copy of these three conditions is a second
828/// place for the positional guard below to be got wrong.
829enum Plan {
830    Empty,
831    Identity { base: i128, count: u64 },
832    Dense { base: i128, range: u64 },
833    Permuted { base: i128, range: u64 },
834    Sorted { base: i128 },
835}
836
837/// Picks the cheapest form that is correct for what the column turned out to hold.
838fn plan(observed: &Observed) -> Result<Plan> {
839    // A column with no keys in it at all is an identity map over nothing. It is worth having rather
840    // than refusing, because an empty parent table is a legal table and a join against it returns
841    // no rows rather than failing.
842    if observed.rows == 0 {
843        return Ok(Plan::Empty);
844    }
845    let (Some(min), Some(max)) = (observed.min, observed.max) else {
846        // A non-zero row count guarantees both, so this is unreachable. It is an error rather than
847        // an `expect` because a key map that panicked on its own bookkeeping would take down a
848        // query that section 3.1 promises can always be answered without it.
849        return Err(malformed("a column with keys in it reported no minimum"));
850    };
851    let range = range_of(min, max)?;
852
853    // Both of the cheap forms answer with a *count of keys below the value*, and both are correct
854    // only where that count is the `rid`. It is the `rid` when the column is ascending and holds no
855    // nulls, and it is not otherwise: a null earlier in the column, or a value out of order, shifts
856    // every row after it. Getting this wrong would not fail, it would resolve every key to a
857    // neighbour of the right row, which is the one failure mode section 3.1 does not catch for
858    // free. So the guard is shared and stated once.
859    let positional = observed.distinct && observed.sorted && observed.nulls == 0;
860
861    if positional && range == observed.rows {
862        // Identity needs more than positional: it needs the values to be exactly the positions,
863        // which on a distinct ascending column is the range equalling the row count. The check is
864        // subtraction rather than a walk because the walk already happened in the observation.
865        return Ok(Plan::Identity { base: min, count: observed.rows });
866    }
867
868    // The bitmap is over the value range, so a range that does not fit a `usize` cannot be one
869    // however dense it is.
870    let compact = usize::try_from(range).is_ok() && range / observed.rows < DENSE_THRESHOLD;
871    if positional && compact {
872        return Ok(Plan::Dense { base: min, range });
873    }
874
875    // The same keys stored in another order, or with nulls between them. A rank is no longer a
876    // `rid`, so a permutation turns one into the other. It is half the sorted form or less whenever
877    // the range is compact, because the bitmap costs under a byte a key where the sorted keys cost
878    // their width, and it answers with a bit test and a rank rather than a search. A column the
879    // first scan already saw repeat never gets here.
880    if observed.distinct && compact {
881        return Ok(Plan::Permuted { base: min, range });
882    }
883
884    Ok(Plan::Sorted { base: min })
885}
886
887/// The four facts section 3.3 says the build records, accumulated one value at a time.
888///
889/// One value at a time rather than one column at a time so that the pass can be driven by a scan
890/// of a file as easily as by a slice. See [`KeyMap::build_from`] for why that matters.
891struct Observer {
892    observed: Observed,
893    previous: Option<i128>,
894}
895
896impl Observer {
897    fn new() -> Self {
898        Self {
899            observed: Observed {
900                rows: 0,
901                nulls: 0,
902                distinct: true,
903                sorted: true,
904                min: None,
905                max: None,
906            },
907            previous: None,
908        }
909    }
910
911    // Distinctness on a column that is not sorted cannot be settled in one pass without a set, so
912    // this settles it for the sorted case and leaves the unsorted case to the sort that the sorted
913    // form does anyway. That is why `distinct` is fixed up in `sorted` below rather than being
914    // final here, and it is worth the awkwardness: the common case on real keys is ascending, and a
915    // hash set over fifteen million rows to discover what adjacency already proves is the build
916    // cost this avoids.
917    fn push(&mut self, key: Option<i128>) {
918        let Some(key) = key else {
919            self.observed.nulls += 1;
920            return;
921        };
922        self.observed.rows += 1;
923        self.observed.min = Some(self.observed.min.map_or(key, |held| held.min(key)));
924        self.observed.max = Some(self.observed.max.map_or(key, |held| held.max(key)));
925        if let Some(previous) = self.previous {
926            if key < previous {
927                self.observed.sorted = false;
928            } else if key == previous {
929                self.observed.distinct = false;
930            }
931        }
932        self.previous = Some(key);
933    }
934}
935
936/// One pass over the column, recording the four facts section 3.3 says the build records.
937fn observe(keys: &[Option<i128>]) -> Observed {
938    let mut observer = Observer::new();
939    for key in keys {
940        observer.push(*key);
941    }
942    observer.observed
943}
944
945/// How many distinct values lie between `min` and `max` inclusive.
946///
947/// The arithmetic is in `u128` and not `i128` because a column holding both `i128::MIN` and
948/// `i128::MAX` has a range of `2^128`, and `max - min` on an `i128` for that column is an overflow
949/// rather than a number. A `HUGEINT` key column spanning more than a `u64` of values is pathological
950/// but legal, so it gets an error naming what happened rather than a panic in a build: the caller
951/// records the relationship as not built, exactly as it does for one that does not fit the budget.
952///
953/// `max >= min` always holds here, so the wrapping subtraction is exact in `u128`.
954fn range_of(min: i128, max: i128) -> Result<u64> {
955    let span = max.wrapping_sub(min) as u128;
956    u64::try_from(span)
957        .ok()
958        .and_then(|span| span.checked_add(1))
959        .ok_or_else(|| malformed("the key column spans more than a u64 of values"))
960}
961
962/// The offset a key takes from the base.
963///
964/// `range_of` bounded the span to a `u64` before either form that uses this was chosen, so the
965/// subtraction cannot overflow and the offset cannot exceed a `u64`. Both are checked anyway: this
966/// is the one arithmetic in the crate whose silent failure would resolve keys to the wrong rows.
967fn offset_of(key: i128, base: i128) -> Result<u64> {
968    let offset = key
969        .checked_sub(base)
970        .ok_or_else(|| malformed("a key is further from the base than an i128 holds"))?;
971    u64::try_from(offset)
972        .map_err(|_| malformed("a key is below the base or further from it than a u64 holds"))
973}
974
975/// Builds the bitmap form one key at a time.
976///
977/// The caller guarantees the column is distinct, ascending and null free, which is what makes a
978/// rank equal to a `rid`. The assertion restates it where the correctness depends on it rather than
979/// where the decision was made.
980struct DenseBits {
981    base: i128,
982    range: u64,
983    bits: Vec<u64>,
984    previous: Option<i128>,
985}
986
987impl DenseBits {
988    fn new(base: i128, range: u64) -> Self {
989        #[expect(
990            clippy::cast_possible_truncation,
991            reason = "the caller checked the range fits a usize"
992        )]
993        let range_usize = range as usize;
994        Self { base, range, bits: vec![0_u64; range_usize.div_ceil(64)], previous: None }
995    }
996
997    fn push(&mut self, key: i128) -> Result<()> {
998        debug_assert!(
999            self.previous.is_none_or(|held| key > held),
1000            "the bitmap form needs a distinct ascending column, because a rank is a count of keys below a value and that is a rid only there"
1001        );
1002        self.previous = Some(key);
1003        let offset = offset_of(key, self.base)?;
1004        #[expect(
1005            clippy::cast_possible_truncation,
1006            reason = "the caller checked the range fits a usize and the offset is inside it"
1007        )]
1008        let at = offset as usize;
1009        self.bits[at / 64] |= 1 << (at % 64);
1010        Ok(())
1011    }
1012
1013    fn finish(self) -> Body {
1014        let rank = Rank::build(&self.bits);
1015        Body::Dense { base: self.base, range: self.range, bits: self.bits, rank }
1016    }
1017
1018    /// Sets a key's bit in any order, and says whether it was clear, which is false for a repeat.
1019    fn mark(&mut self, key: i128) -> Result<bool> {
1020        let offset = offset_of(key, self.base)?;
1021        #[expect(
1022            clippy::cast_possible_truncation,
1023            reason = "the caller checked the range fits a usize and the offset is inside it"
1024        )]
1025        let at = offset as usize;
1026        let bit = 1 << (at % 64);
1027        let fresh = self.bits[at / 64] & bit == 0;
1028        self.bits[at / 64] |= bit;
1029        Ok(fresh)
1030    }
1031}
1032
1033/// The permutation of the permuted form, filled one row at a time in any order.
1034///
1035/// Built over a finished bitmap, so a key's place is its rank and every place is filled exactly
1036/// once. Held as `u64` a key while it fills, which is the one allocation the build makes that the
1037/// map does not keep, and packed at the end to the width the row count needs.
1038struct Permutation {
1039    base: i128,
1040    range: u64,
1041    bits: Vec<u64>,
1042    rank: Rank,
1043    places: Vec<u64>,
1044    rid_width: usize,
1045}
1046
1047impl Permutation {
1048    /// Takes the finished bitmap, and `rows`, which is how many rows the column has, nulls included.
1049    fn new(bits: DenseBits, rows: usize) -> Result<Self> {
1050        let keys: u64 = bits.bits.iter().map(|word| u64::from(word.count_ones())).sum();
1051        let keys =
1052            usize::try_from(keys).map_err(|_| malformed("too many keys for this machine"))?;
1053        let largest = u64::try_from(rows.saturating_sub(1))
1054            .map_err(|_| malformed("the column is too long for a rid"))?;
1055        let rank = Rank::build(&bits.bits);
1056        Ok(Self {
1057            base: bits.base,
1058            range: bits.range,
1059            bits: bits.bits,
1060            rank,
1061            places: vec![0; keys],
1062            rid_width: width_for(largest),
1063        })
1064    }
1065
1066    /// Puts `rid` at the place of `key`, which the bitmap already holds.
1067    fn place(&mut self, key: i128, rid: usize) -> Result<()> {
1068        let offset = offset_of(key, self.base)?;
1069        #[expect(
1070            clippy::cast_possible_truncation,
1071            reason = "the offset is inside a range the caller checked fits a usize"
1072        )]
1073        let at = offset as usize;
1074        let place = usize::try_from(self.rank.rank(&self.bits, at))
1075            .map_err(|_| malformed("a rank past what this machine can index"))?;
1076        let rid = u64::try_from(rid).map_err(|_| malformed("the column is too long for a rid"))?;
1077        let slot = self
1078            .places
1079            .get_mut(place)
1080            .ok_or_else(|| malformed("a key was placed that the bitmap does not hold"))?;
1081        *slot = rid;
1082        Ok(())
1083    }
1084
1085    fn finish(self) -> Result<Body> {
1086        let mut perm = Vec::new();
1087        // The linear packer for the reason [`sorted`] gives: a parent key column is longer than a
1088        // tail, and `tail_at` reads either layout.
1089        bitpack::pack_linear(&self.places, self.rid_width, &mut perm)?;
1090        Ok(Body::Permuted {
1091            base: self.base,
1092            range: self.range,
1093            bits: self.bits,
1094            rank: self.rank,
1095            rid_width: self.rid_width,
1096            perm,
1097        })
1098    }
1099}
1100
1101fn dense(keys: &[Option<i128>], base: i128, range: u64) -> Result<Body> {
1102    let mut bits = DenseBits::new(base, range);
1103    for key in keys.iter().flatten() {
1104        bits.push(*key)?;
1105    }
1106    Ok(bits.finish())
1107}
1108
1109/// Builds the general form, and settles distinctness on the way.
1110///
1111/// Returns the body and whether every key was distinct. The second is not a courtesy: the sort this
1112/// form performs is the only place a duplicate that is not adjacent in the column can be seen, and
1113/// section 2.3 needs that answer to decide whether a link may be built at all.
1114fn sorted(keys: &[Option<i128>], base: i128, rows: u64) -> Result<(Body, bool)> {
1115    let mut pairs: Vec<(u64, u64)> = Vec::with_capacity(keys.len());
1116    for (rid, key) in keys.iter().enumerate() {
1117        let Some(key) = *key else { continue };
1118        let offset = offset_of(key, base)?;
1119        let rid = u64::try_from(rid).map_err(|_| malformed("the column is too long for a rid"))?;
1120        pairs.push((offset, rid));
1121    }
1122    // Sorted by key, then by rid so that a duplicated key resolves to its first row rather than to
1123    // whichever one the sort happened to leave first. A duplicated key means no link gets built, so
1124    // this only decides what a map nobody should be using returns, and deciding it anyway is what
1125    // keeps a test of this form reproducible.
1126    pairs.sort_unstable();
1127    let distinct = pairs.windows(2).all(|pair| pair[0].0 != pair[1].0);
1128    debug_assert_eq!(
1129        u64::try_from(pairs.len()).ok(),
1130        Some(rows),
1131        "the pair list is the non-null column"
1132    );
1133    let key_width = width_for(pairs.last().map_or(0, |pair| pair.0));
1134    let rows_width = u64::try_from(keys.len().saturating_sub(1))
1135        .map_err(|_| malformed("the column is too long for a rid"))?;
1136    let rid_width = width_for(rows_width);
1137    let mut key_bytes = Vec::new();
1138    let mut rid_bytes = Vec::new();
1139    let key_values: Vec<u64> = pairs.iter().map(|pair| pair.0).collect();
1140    let rid_values: Vec<u64> = pairs.iter().map(|pair| pair.1).collect();
1141    // The linear packer and not the tail one, because a tail is bounded at a thousand values and a
1142    // parent key column is not. The layout is the same and `tail_at` reads either.
1143    bitpack::pack_linear(&key_values, key_width, &mut key_bytes)?;
1144    bitpack::pack_linear(&rid_values, rid_width, &mut rid_bytes)?;
1145    Ok((
1146        Body::Sorted { base, key_width, keys: key_bytes, rid_width, perm: rid_bytes, count: rows },
1147        distinct,
1148    ))
1149}
1150
1151/// Bits needed to hold every value up to and including `largest`.
1152///
1153/// One rather than zero for a largest of zero, because a width of zero is a packed payload with no
1154/// bytes in it and `tail_at` on one of those has nothing to return. A column of a single key is a
1155/// real column.
1156fn width_for(largest: u64) -> usize {
1157    let bits = u64::BITS - largest.leading_zeros();
1158    bits.max(1) as usize
1159}
1160
1161fn malformed(message: impl Into<String>) -> Error {
1162    Error::invalid_input(format!("invalid rudb key map: {}", message.into()))
1163}
1164
1165#[cfg(test)]
1166mod tests {
1167    use super::*;
1168
1169    fn keys(values: &[i128]) -> Vec<Option<i128>> {
1170        values.iter().copied().map(Some).collect()
1171    }
1172
1173    /// Every key in the column resolves to the row that holds it, whatever form was chosen.
1174    fn resolves(column: &[Option<i128>], map: &KeyMap) {
1175        for (rid, key) in column.iter().enumerate() {
1176            let Some(key) = *key else { continue };
1177            let found = map.lookup(key).expect("lookup").expect("a key in the column resolves");
1178            assert_eq!(found, rid as u64, "key {key} resolved to {found} rather than {rid}");
1179        }
1180    }
1181
1182    #[test]
1183    fn a_sequence_from_one_is_the_identity_form_and_stores_two_numbers() {
1184        // TPC-H's `region`, `nation`, `supplier`, `customer`, `part` and `orders` all land here,
1185        // which is the case the whole budget in section 3.7 depends on.
1186        let column = keys(&(1..=1000).collect::<Vec<i128>>());
1187        let map = KeyMap::build(&column).expect("build");
1188        assert_eq!(map.form(), Form::Identity);
1189        assert_eq!(map.bytes(), 24, "section 4.2 says identity is twenty four bytes");
1190        assert_eq!(map.len(), 1000);
1191        resolves(&column, &map);
1192        assert_eq!(map.lookup(0).expect("lookup"), None, "below the base");
1193        assert_eq!(map.lookup(1001).expect("lookup"), None, "past the end");
1194        assert_eq!(map.span(), Some((1, 1000)));
1195    }
1196
1197    #[test]
1198    fn the_rows_of_a_span_are_the_rows_a_lookup_of_each_key_finds() {
1199        let identity = keys(&(5..1005).collect::<Vec<i128>>());
1200        let dense = keys(&(0..3000).filter(|value| value % 3 != 1).collect::<Vec<i128>>());
1201        let mut shuffled = (0..3000).filter(|value| value % 3 != 1).collect::<Vec<i128>>();
1202        shuffled.sort_by_key(|value| (value * 7919) % 3001);
1203        let permuted = keys(&shuffled);
1204        for (column, form) in
1205            [(identity, Form::Identity), (dense, Form::Dense), (permuted, Form::Permuted)]
1206        {
1207            let map = KeyMap::build(&column).expect("build");
1208            assert_eq!(map.form(), form);
1209            let rows = column.len() as u64;
1210            let (base, range) = map.span().expect("a span");
1211            let mut held = vec![0_u64; (range / 64 + 1) as usize];
1212            let mut wanted = vec![0_u64; rows.div_ceil(64) as usize];
1213            for key in column.iter().flatten().filter(|key| *key % 5 == 0 || *key % 7 == 3) {
1214                let offset = (key - base) as u64;
1215                held[(offset / 64) as usize] |= 1 << (offset % 64);
1216                let rid = map.lookup(*key).expect("lookup").expect("a key in the column");
1217                wanted[(rid / 64) as usize] |= 1 << (rid % 64);
1218            }
1219            assert_eq!(map.rows_of_span(&held, rows).expect("rows"), Some(wanted), "{form:?}");
1220            if form != Form::Identity {
1221                // A key inside the span that no row holds.
1222                let missing = (0..range).find(|offset| {
1223                    map.lookup(base + i128::from(*offset)).expect("lookup").is_none()
1224                });
1225                let offset = missing.expect("a hole in the span");
1226                held[(offset / 64) as usize] |= 1 << (offset % 64);
1227                assert_eq!(map.rows_of_span(&held, rows).expect("rows"), None, "{form:?}");
1228            }
1229            let last = held.len() - 1;
1230            held[last] |= 1 << 63;
1231            assert_eq!(map.rows_of_span(&held, rows).expect("rows"), None, "past the span");
1232        }
1233        let sorted = keys(&(0..1000).map(|value| value * 1000).collect::<Vec<i128>>());
1234        let map = KeyMap::build(&sorted).expect("build");
1235        assert_eq!(map.rows_of_span(&[0; 4], 1000).expect("rows"), None, "no span");
1236    }
1237
1238    #[test]
1239    fn a_sequence_from_zero_is_also_the_identity_form() {
1240        let column = keys(&(0..64).collect::<Vec<i128>>());
1241        let map = KeyMap::build(&column).expect("build");
1242        assert_eq!(map.form(), Form::Identity);
1243        resolves(&column, &map);
1244    }
1245
1246    #[test]
1247    fn a_sequence_with_a_gap_in_it_is_the_dense_form() {
1248        // Every other value over a range of two thousand, which is a density of one in two and
1249        // comfortably inside the threshold.
1250        let column = keys(&(0..1000).map(|value| value * 2).collect::<Vec<i128>>());
1251        let map = KeyMap::build(&column).expect("build");
1252        assert_eq!(map.form(), Form::Dense);
1253        resolves(&column, &map);
1254        assert_eq!(
1255            map.lookup(1).expect("lookup"),
1256            None,
1257            "a value in the range and not in the column"
1258        );
1259        assert_eq!(map.lookup(2001).expect("lookup"), None, "past the range");
1260        assert_eq!(map.span(), Some((0, 1999)), "from the smallest key to the largest");
1261    }
1262
1263    #[test]
1264    fn a_range_too_sparse_for_a_bitmap_is_the_sorted_form() {
1265        // A thousand keys spread over a million, which is a density of one in a thousand: the
1266        // bitmap would be 125 KB to hold a thousand values and the sorted form is a few kilobytes.
1267        let column = keys(&(0..1000).map(|value| value * 1000).collect::<Vec<i128>>());
1268        let map = KeyMap::build(&column).expect("build");
1269        assert_eq!(map.form(), Form::Sorted);
1270        resolves(&column, &map);
1271        assert_eq!(map.lookup(500).expect("lookup"), None);
1272        assert_eq!(map.span(), None, "too sparse for a bitmap over the range");
1273    }
1274
1275    #[test]
1276    fn the_sorted_form_is_not_bounded_by_a_packed_unit() {
1277        // The sorted form packs its keys and its permutation sequentially, and the sequential
1278        // packer a column uses is for the remainder past the last transposed unit, so it refuses a
1279        // thousand and twenty four values. A parent key column is sixty times that at SF1 and
1280        // fifteen thousand times it at SF10, so the form would exist only for toy tables. This is
1281        // the smallest column that would have hit it.
1282        let column = keys(&(0..5000).map(|value| (value * 7919) % 100_003).collect::<Vec<i128>>());
1283        let map = KeyMap::build(&column).expect("build");
1284        assert_eq!(map.form(), Form::Sorted);
1285        resolves(&column, &map);
1286    }
1287
1288    #[test]
1289    fn keys_in_no_order_at_all_resolve_to_the_rows_that_hold_them() {
1290        // The case the permutation exists for. The column is not sorted, so the sorted form's
1291        // position is not the rid, and a map that confused the two would resolve every key to the
1292        // wrong row while looking exactly like a working map.
1293        let column = keys(&[500, 3, 9000, 12, 7, 88, 41, 6]);
1294        let map = KeyMap::build(&column).expect("build");
1295        assert_eq!(map.form(), Form::Sorted);
1296        resolves(&column, &map);
1297    }
1298
1299    #[test]
1300    fn a_descending_column_dense_enough_for_a_bitmap_still_resolves_correctly() {
1301        // The trap in the dense form: a bitmap is in value order, so a rank is a position in value
1302        // order, and on a descending column that is not the rid. So it takes the permutation too.
1303        let column = keys(&(0..500).rev().collect::<Vec<i128>>());
1304        let map = KeyMap::build(&column).expect("build");
1305        assert_eq!(map.form(), Form::Permuted, "a descending column cannot take the bare bitmap");
1306        resolves(&column, &map);
1307    }
1308
1309    #[test]
1310    fn nulls_are_not_keys_and_do_not_shift_the_rows_around_them() {
1311        // This column is distinct, ascending, and dense enough for a bitmap on the numbers alone:
1312        // three keys over a range of twenty one. It cannot have the bare one, because a rank counts
1313        // keys below a value and the nulls in between mean that count is not the row's position. A
1314        // map that took the bitmap here would resolve key 20 to row 1 and look entirely healthy
1315        // doing it, so it takes the permutation behind the bitmap.
1316        let column = vec![Some(10), None, Some(20), None, Some(30)];
1317        let map = KeyMap::build(&column).expect("build");
1318        assert_eq!(
1319            map.form(),
1320            Form::Permuted,
1321            "a null before a key shifts it out of the positional forms"
1322        );
1323        resolves(&column, &map);
1324        assert_eq!(map.observed().nulls, 2);
1325        assert_eq!(map.observed().rows, 3);
1326        assert_eq!(
1327            map.lookup(20).expect("lookup"),
1328            Some(2),
1329            "the rid is the position in the column"
1330        );
1331    }
1332
1333    #[test]
1334    fn a_leading_null_keeps_an_otherwise_perfect_sequence_out_of_the_identity_form() {
1335        // The same trap on the form that would otherwise be free. Worth its own test because a
1336        // sequence from one is the case every TPC-H table hits, and the version of it with a null
1337        // in front is one `INSERT` away.
1338        let mut column = vec![None];
1339        column.extend((1..=1000).map(Some));
1340        let map = KeyMap::build(&column).expect("build");
1341        assert_ne!(map.form(), Form::Identity);
1342        resolves(&column, &map);
1343        assert_eq!(map.lookup(1).expect("lookup"), Some(1), "row zero is the null, not key one");
1344    }
1345
1346    #[test]
1347    fn a_null_only_column_builds_and_resolves_nothing() {
1348        let column = vec![None, None, None];
1349        let map = KeyMap::build(&column).expect("build");
1350        assert!(map.is_empty());
1351        assert_eq!(map.observed().nulls, 3);
1352        assert_eq!(map.lookup(0).expect("lookup"), None);
1353    }
1354
1355    #[test]
1356    fn an_empty_column_builds_and_resolves_nothing() {
1357        let map = KeyMap::build(&[]).expect("build");
1358        assert!(map.is_empty());
1359        assert_eq!(map.lookup(0).expect("lookup"), None);
1360        assert!(map.observed().usable_as_parent(), "an empty parent is unique, vacuously");
1361    }
1362
1363    #[test]
1364    fn a_duplicated_key_is_reported_rather_than_resolved_to_one_of_its_rows() {
1365        // Section 2.3's verification. The map still builds, because the caller is the one that
1366        // decides what to do about it, and what it decides is to build no link.
1367        let column = keys(&[5, 7, 5, 9]);
1368        let map = KeyMap::build(&column).expect("build");
1369        assert!(!map.observed().distinct);
1370        assert!(!map.observed().usable_as_parent(), "a non-unique parent side takes no link");
1371    }
1372
1373    #[test]
1374    fn a_column_that_arrives_with_its_repeats_together_is_not_sorted_into_a_map() {
1375        // The scan sees the repeat, so nothing is packed. What matters is the bytes: this is
1376        // `lineitem(l_orderkey)`, where the form that would have been chosen holds one packed key
1377        // and one packed permutation entry per row.
1378        let column = keys(&[1, 1, 2, 2, 2, 90_000, 90_000]);
1379        let map = KeyMap::build_from(&column[..]).expect("build");
1380        assert!(!map.observed().distinct);
1381        assert_eq!(map.observed().rows, 7, "the column was still counted");
1382        assert_eq!(map.observed().max, Some(90_000));
1383        assert_eq!(map.bytes(), KeyMap::build(&keys(&[])).expect("build").bytes());
1384        assert_eq!(map.lookup(2).expect("lookup"), None, "and it answers nothing, as it must");
1385    }
1386
1387    #[test]
1388    fn a_single_key_column_resolves_it() {
1389        // The width of zero case: one key at the base is an offset of zero, and a packed payload of
1390        // width zero has no bytes for `tail_at` to read.
1391        let column = keys(&[42]);
1392        let map = KeyMap::build(&column).expect("build");
1393        resolves(&column, &map);
1394        assert_eq!(map.lookup(41).expect("lookup"), None);
1395        assert_eq!(map.lookup(43).expect("lookup"), None);
1396    }
1397
1398    #[test]
1399    fn negative_keys_resolve_because_the_base_is_the_minimum_and_not_zero() {
1400        let column = keys(&[-9000, -3, -1, 0, 7]);
1401        let map = KeyMap::build(&column).expect("build");
1402        resolves(&column, &map);
1403        assert_eq!(map.lookup(-9001).expect("lookup"), None);
1404    }
1405
1406    #[test]
1407    fn a_column_spanning_more_than_a_u64_of_values_is_refused_and_not_panicked_over() {
1408        // `max - min` on a HUGEINT column holding both ends of the type overflows an i128, so this
1409        // is where a build panics if the range arithmetic is done in the column's own type. It is
1410        // refused instead, and the caller records the relationship as not built.
1411        let column = keys(&[i128::MIN, 0, i128::MAX]);
1412        let error = KeyMap::build(&column).expect_err("refused");
1413        assert!(error.to_string().contains("spans more than a u64"), "{error}");
1414    }
1415
1416    #[test]
1417    fn keys_at_the_far_end_of_the_integer_type_resolve_when_their_range_is_narrow() {
1418        // The other half of the same arithmetic: the values are extreme and the range is not, which
1419        // is a column a key map has to handle rather than refuse.
1420        let column = keys(&[i128::MIN, i128::MIN + 5, i128::MIN + 2]);
1421        let map = KeyMap::build(&column).expect("build");
1422        resolves(&column, &map);
1423        assert_eq!(map.lookup(i128::MAX).expect("lookup"), None);
1424        assert_eq!(map.lookup(0).expect("lookup"), None);
1425    }
1426
1427    #[test]
1428    fn the_rank_index_agrees_with_counting_the_bits_by_hand() {
1429        // The rank structure is two levels and an eight word popcount, and an off by one in any of
1430        // the three resolves every key past the fault to the row before or after the right one. So
1431        // it is checked against the naive count over a bitmap wide enough to use every level: 4096
1432        // bits is one superblock exactly, so 20,000 forces five of them and the last one partial.
1433        let column = keys(&(0..10_000).map(|value| value * 2).collect::<Vec<i128>>());
1434        let map = KeyMap::build(&column).expect("build");
1435        assert_eq!(map.form(), Form::Dense);
1436        resolves(&column, &map);
1437    }
1438
1439    #[test]
1440    fn a_string_key_arrives_as_dictionary_codes_and_never_as_text() {
1441        // Section 2.2's composition with the global dictionary. There is nothing string shaped in
1442        // this crate and that is the point: the codes of a file wide stable dictionary carry the
1443        // column's own order, so a sorted key map over a VARCHAR is this and the search is over
1444        // integers.
1445        let codes = keys(&[7, 1, 4, 9, 2]);
1446        let map = KeyMap::build(&codes).expect("build");
1447        resolves(&codes, &map);
1448    }
1449
1450    #[test]
1451    fn the_form_tag_round_trips_and_an_unknown_one_is_refused() {
1452        for form in [Form::Identity, Form::Dense, Form::Sorted, Form::Permuted] {
1453            assert_eq!(Form::from_tag(form.tag()).expect("a known tag"), form);
1454        }
1455        assert!(Form::from_tag(4).is_err(), "an unfamiliar form is refused rather than guessed");
1456    }
1457
1458    #[test]
1459    fn the_dense_form_costs_a_bitmap_and_about_an_eighth_again() {
1460        // The space claim in section 3.3, checked. A range of 80,000 bits is 10,000 bytes and the
1461        // index is a u16 per 512 bits plus a u32 per 4096, which is about 12.5 percent.
1462        let column = keys(&(0..10_000).map(|value| value * 8).collect::<Vec<i128>>());
1463        let map = KeyMap::build(&column).expect("build");
1464        assert_eq!(map.form(), Form::Dense);
1465        let bitmap = 80_000 / 8;
1466        let bytes = map.bytes();
1467        assert!(bytes > bitmap, "the map took {bytes} bytes and the bitmap alone is {bitmap}");
1468        assert!(
1469            bytes < bitmap * 5 / 4,
1470            "the map took {bytes} bytes, more than a quarter over the bitmap's {bitmap}"
1471        );
1472    }
1473
1474    /// A column that counts how many times it was read, so a test can say what a build cost.
1475    struct Counted {
1476        column: Vec<Option<i128>>,
1477        scans: std::cell::Cell<usize>,
1478    }
1479
1480    impl Keys for Counted {
1481        fn scan(&self, each: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()> {
1482            self.scans.set(self.scans.get() + 1);
1483            self.column.scan(each)
1484        }
1485    }
1486
1487    #[test]
1488    fn a_build_from_a_scan_is_the_same_map_as_a_build_from_a_slice() {
1489        // The two builds have to agree on every column, because the streaming one is not a second
1490        // implementation, it is the same decision carried out against a source that is read twice.
1491        // If these ever disagree, a table's key map depends on which path built it.
1492        let columns: Vec<Vec<Option<i128>>> = vec![
1493            Vec::new(),
1494            keys(&[]),
1495            keys(&(1..=1000).collect::<Vec<i128>>()),
1496            keys(&(0..500).map(|value| value * 4).collect::<Vec<i128>>()),
1497            keys(&[100, 3, 40, 7, 9000]),
1498            keys(&[5, 5, 9]),
1499            vec![Some(10), None, Some(20), None, Some(30)],
1500            vec![None, None],
1501            shuffled(1_000, 4),
1502            keys(&[1, 3, 2, 1]),
1503        ];
1504        for column in &columns {
1505            let held = KeyMap::build(column).expect("build from a slice");
1506            let read = KeyMap::build_from(&column[..]).expect("build from a scan");
1507            assert_eq!(read.form(), held.form(), "{column:?}");
1508            assert_eq!(read.observed(), held.observed(), "{column:?}");
1509            assert_eq!(read.len(), held.len(), "{column:?}");
1510            assert_eq!(read.bytes(), held.bytes(), "{column:?}");
1511            // A column with a repeat in it has no one right row for its key, which is exactly why
1512            // section 2.3 refuses to build a link on one. So the round trip is checked where the
1513            // question has an answer.
1514            if read.observed().usable_as_parent() {
1515                resolves(column, &read);
1516            }
1517        }
1518    }
1519
1520    #[test]
1521    fn the_identity_form_is_built_without_reading_the_column_twice() {
1522        // The reason `build_from` exists. Every TPC-H parent key takes the identity form, and the
1523        // identity form is two numbers, so a build of one has no business holding fifteen million
1524        // values or reading them a second time.
1525        let identity =
1526            Counted { column: keys(&(1..=1000).collect::<Vec<i128>>()), scans: 0.into() };
1527        assert_eq!(KeyMap::build_from(&identity).expect("build").form(), Form::Identity);
1528        assert_eq!(
1529            identity.scans.get(),
1530            1,
1531            "the identity form is the observation and nothing more"
1532        );
1533
1534        // The other two forms have something to fill, so they read it again, and once is the number
1535        // that matters: a form that scanned per value would be a build nobody could afford.
1536        let dense = Counted {
1537            column: keys(&(0..500).map(|v| v * 4).collect::<Vec<i128>>()),
1538            scans: 0.into(),
1539        };
1540        assert_eq!(KeyMap::build_from(&dense).expect("build").form(), Form::Dense);
1541        assert_eq!(dense.scans.get(), 2);
1542
1543        let sorted = Counted { column: keys(&[100, 3, 40, 7, 9000]), scans: 0.into() };
1544        assert_eq!(KeyMap::build_from(&sorted).expect("build").form(), Form::Sorted);
1545        assert_eq!(sorted.scans.get(), 2);
1546
1547        // The permuted form reads it twice more, once to mark the bitmap and once to place the
1548        // rows, rather than holding it.
1549        let permuted = Counted { column: shuffled(1_000, 4), scans: 0.into() };
1550        assert_eq!(KeyMap::build_from(&permuted).expect("build").form(), Form::Permuted);
1551        assert_eq!(permuted.scans.get(), 3);
1552    }
1553
1554    /// `count` keys a `step` apart from zero, stored in an order that is not theirs.
1555    ///
1556    /// The order is a multiplication by a prime modulo the count, so it is the same every run and
1557    /// visits every key once.
1558    fn shuffled(count: i128, step: i128) -> Vec<Option<i128>> {
1559        (0..count).map(|at| Some((at * 7_919 % count) * step)).collect()
1560    }
1561
1562    #[test]
1563    fn dense_keys_stored_out_of_key_order_take_the_permuted_form() {
1564        // `orders` stored by date: the same keys, one in four of their range, in an order that has
1565        // nothing to do with them. The dense form cannot answer it and the sorted form costs its
1566        // keys and its permutation, which on SF1 was 8.25 MB and over the budget.
1567        let column = shuffled(10_000, 4);
1568        let map = KeyMap::build(&column).expect("build");
1569        assert_eq!(map.form(), Form::Permuted);
1570        assert!(map.observed().distinct);
1571        assert!(!map.observed().sorted);
1572        resolves(&column, &map);
1573        assert_eq!(map.lookup(1).expect("lookup"), None, "a key between two keys is not a key");
1574        assert_eq!(map.lookup(40_000).expect("lookup"), None, "past the end");
1575        assert_eq!(map.span(), Some((0, 39_997)), "the span is about the keys and not the rows");
1576        // The sorted form would hold a 16 bit key and a 14 bit rid a row. This holds a bit per value
1577        // of the range, the rank index over it, and the rid.
1578        let sorted = 10_000 * (16 + 14) / 8;
1579        assert!(map.bytes() * 10 < sorted * 7, "{} bytes against {sorted}", map.bytes());
1580    }
1581
1582    #[test]
1583    fn a_repeat_that_is_not_adjacent_keeps_a_dense_column_out_of_every_form() {
1584        // The first scan only sees a repeat that sits next to itself. The bitmap sees every one,
1585        // because a key is marked twice only when two rows hold it.
1586        let column = keys(&[4, 1, 3, 2, 4]);
1587        let map = KeyMap::build(&column).expect("build");
1588        assert!(!map.observed().distinct);
1589        assert!(!map.observed().usable_as_parent());
1590        assert_eq!(map.lookup(4).expect("lookup"), None);
1591        let read = KeyMap::build_from(&column[..]).expect("build");
1592        assert_eq!(read.observed(), map.observed());
1593    }
1594
1595    #[test]
1596    fn a_scan_that_fails_stops_the_build_rather_than_half_finishing_it() {
1597        struct Broken;
1598        impl Keys for Broken {
1599            fn scan(&self, _: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()> {
1600                Err(malformed("the column could not be read"))
1601            }
1602        }
1603        let error = KeyMap::build_from(&Broken).expect_err("a build over an unreadable column");
1604        assert!(error.to_string().contains("could not be read"), "{error}");
1605    }
1606}