spacetimedb_table/table_index/
mod.rs

1//! Table indexes with specialized key types.
2//!
3//! Indexes could be implemented as `MultiMap<AlgebraicValue, RowPointer>` (and once were),
4//! but that results in wasted memory and spurious comparisons and branches
5//! because the keys must always be homogeneous at a more specific type than `AlgebraicValue`.
6//!
7//! As an optimization, we hoist the enum out of the keys to the index itself.
8//! This is a sizeable improvement for integer keys,
9//! as e.g. `u64::cmp` is much faster than `AlgebraicValue::cmp`.
10//!
11//! This results in some pretty ugly code, where types that would be structs
12//! are instead enums with similar-looking variants for each specialized key type,
13//! and methods that interact with those enums have matches with similar-looking arms.
14//! Some day we may devise a better solution, but this is good enough for now.
15//
16// I (pgoldman 2024-02-05) suspect, but have not measured, that there's no real reason
17// to have a `ProductType` variant, which would apply to multi-column indexes.
18// I believe `ProductValue::cmp` to not be meaningfully faster than `AlgebraicValue::cmp`.
19// Eventually, we will likely want to compile comparison functions and representations
20// for `ProductValue`-keyed indexes which take advantage of type information,
21// since we know when creating the index the number and type of all the indexed columns.
22// This may involve a bytecode compiler, a tree of closures, or a native JIT.
23///
24/// We also represent unique indices more compactly than non-unique ones, avoiding the multi-map.
25/// Additionally, beyond our btree indices,
26/// we support direct unique indices, where key are indices into `Vec`s.
27use super::indexes::RowPointer;
28use super::table::RowRef;
29use crate::{read_column::ReadColumn, static_assert_size, MemoryUsage};
30use core::ops::RangeBounds;
31use spacetimedb_primitives::ColList;
32use spacetimedb_sats::{
33    algebraic_value::Packed, i256, product_value::InvalidFieldError, u256, AlgebraicType, AlgebraicValue, ProductType,
34};
35
36mod key_size;
37mod multimap;
38pub mod unique_direct_index;
39pub mod uniquemap;
40
41pub use key_size::KeySize;
42use spacetimedb_schema::def::IndexAlgorithm;
43use unique_direct_index::{UniqueDirectIndex, UniqueDirectIndexPointIter, UniqueDirectIndexRangeIter};
44
45type BtreeIndex<K> = multimap::MultiMap<K, RowPointer>;
46type BtreeIndexPointIter<'a> = multimap::MultiMapPointIter<'a, RowPointer>;
47type BtreeIndexRangeIter<'a, K> = multimap::MultiMapRangeIter<'a, K, RowPointer>;
48type BtreeUniqueIndex<K> = uniquemap::UniqueMap<K, RowPointer>;
49type BtreeUniqueIndexPointIter<'a> = uniquemap::UniqueMapPointIter<'a, RowPointer>;
50type BtreeUniqueIndexRangeIter<'a, K> = uniquemap::UniqueMapRangeIter<'a, K, RowPointer>;
51
52/// A point iterator over a [`TypedIndex`], with a specialized key type.
53///
54/// See module docs for info about specialization.
55enum TypedIndexPointIter<'a> {
56    BTree(BtreeIndexPointIter<'a>),
57    UniqueBTree(BtreeUniqueIndexPointIter<'a>),
58    UniqueDirect(UniqueDirectIndexPointIter),
59}
60
61impl Iterator for TypedIndexPointIter<'_> {
62    type Item = RowPointer;
63    fn next(&mut self) -> Option<Self::Item> {
64        match self {
65            Self::BTree(this) => this.next().copied(),
66            Self::UniqueBTree(this) => this.next().copied(),
67            Self::UniqueDirect(this) => this.next(),
68        }
69    }
70}
71
72/// An iterator over rows matching a certain [`AlgebraicValue`] on the [`TableIndex`].
73pub struct TableIndexPointIter<'a> {
74    /// The iterator seeking for matching values.
75    iter: TypedIndexPointIter<'a>,
76}
77
78impl Iterator for TableIndexPointIter<'_> {
79    type Item = RowPointer;
80
81    fn next(&mut self) -> Option<Self::Item> {
82        self.iter.next()
83    }
84}
85
86/// A ranged iterator over a [`TypedIndex`], with a specialized key type.
87///
88/// See module docs for info about specialization.
89enum TypedIndexRangeIter<'a> {
90    // All the non-unique btree index iterators.
91    BtreeBool(BtreeIndexRangeIter<'a, bool>),
92    BtreeU8(BtreeIndexRangeIter<'a, u8>),
93    BtreeI8(BtreeIndexRangeIter<'a, i8>),
94    BtreeU16(BtreeIndexRangeIter<'a, u16>),
95    BtreeI16(BtreeIndexRangeIter<'a, i16>),
96    BtreeU32(BtreeIndexRangeIter<'a, u32>),
97    BtreeI32(BtreeIndexRangeIter<'a, i32>),
98    BtreeU64(BtreeIndexRangeIter<'a, u64>),
99    BtreeI64(BtreeIndexRangeIter<'a, i64>),
100    BtreeU128(BtreeIndexRangeIter<'a, Packed<u128>>),
101    BtreeI128(BtreeIndexRangeIter<'a, Packed<i128>>),
102    BtreeU256(BtreeIndexRangeIter<'a, u256>),
103    BtreeI256(BtreeIndexRangeIter<'a, i256>),
104    BtreeString(BtreeIndexRangeIter<'a, Box<str>>),
105    BtreeAV(BtreeIndexRangeIter<'a, AlgebraicValue>),
106
107    // All the unique btree index iterators.
108    UniqueBtreeBool(BtreeUniqueIndexRangeIter<'a, bool>),
109    UniqueBtreeU8(BtreeUniqueIndexRangeIter<'a, u8>),
110    UniqueBtreeI8(BtreeUniqueIndexRangeIter<'a, i8>),
111    UniqueBtreeU16(BtreeUniqueIndexRangeIter<'a, u16>),
112    UniqueBtreeI16(BtreeUniqueIndexRangeIter<'a, i16>),
113    UniqueBtreeU32(BtreeUniqueIndexRangeIter<'a, u32>),
114    UniqueBtreeI32(BtreeUniqueIndexRangeIter<'a, i32>),
115    UniqueBtreeU64(BtreeUniqueIndexRangeIter<'a, u64>),
116    UniqueBtreeI64(BtreeUniqueIndexRangeIter<'a, i64>),
117    UniqueBtreeU128(BtreeUniqueIndexRangeIter<'a, Packed<u128>>),
118    UniqueBtreeI128(BtreeUniqueIndexRangeIter<'a, Packed<i128>>),
119    UniqueBtreeU256(BtreeUniqueIndexRangeIter<'a, u256>),
120    UniqueBtreeI256(BtreeUniqueIndexRangeIter<'a, i256>),
121    UniqueBtreeString(BtreeUniqueIndexRangeIter<'a, Box<str>>),
122    UniqueBtreeAV(BtreeUniqueIndexRangeIter<'a, AlgebraicValue>),
123
124    UniqueDirect(UniqueDirectIndexRangeIter<'a>),
125}
126
127impl Iterator for TypedIndexRangeIter<'_> {
128    type Item = RowPointer;
129    fn next(&mut self) -> Option<Self::Item> {
130        match self {
131            Self::BtreeBool(this) => this.next().copied(),
132            Self::BtreeU8(this) => this.next().copied(),
133            Self::BtreeI8(this) => this.next().copied(),
134            Self::BtreeU16(this) => this.next().copied(),
135            Self::BtreeI16(this) => this.next().copied(),
136            Self::BtreeU32(this) => this.next().copied(),
137            Self::BtreeI32(this) => this.next().copied(),
138            Self::BtreeU64(this) => this.next().copied(),
139            Self::BtreeI64(this) => this.next().copied(),
140            Self::BtreeU128(this) => this.next().copied(),
141            Self::BtreeI128(this) => this.next().copied(),
142            Self::BtreeU256(this) => this.next().copied(),
143            Self::BtreeI256(this) => this.next().copied(),
144            Self::BtreeString(this) => this.next().copied(),
145            Self::BtreeAV(this) => this.next().copied(),
146
147            Self::UniqueBtreeBool(this) => this.next().copied(),
148            Self::UniqueBtreeU8(this) => this.next().copied(),
149            Self::UniqueBtreeI8(this) => this.next().copied(),
150            Self::UniqueBtreeU16(this) => this.next().copied(),
151            Self::UniqueBtreeI16(this) => this.next().copied(),
152            Self::UniqueBtreeU32(this) => this.next().copied(),
153            Self::UniqueBtreeI32(this) => this.next().copied(),
154            Self::UniqueBtreeU64(this) => this.next().copied(),
155            Self::UniqueBtreeI64(this) => this.next().copied(),
156            Self::UniqueBtreeU128(this) => this.next().copied(),
157            Self::UniqueBtreeI128(this) => this.next().copied(),
158            Self::UniqueBtreeU256(this) => this.next().copied(),
159            Self::UniqueBtreeI256(this) => this.next().copied(),
160            Self::UniqueBtreeString(this) => this.next().copied(),
161            Self::UniqueBtreeAV(this) => this.next().copied(),
162
163            Self::UniqueDirect(this) => this.next(),
164        }
165    }
166}
167
168/// An iterator over rows matching a range of [`AlgebraicValue`]s on the [`TableIndex`].
169pub struct TableIndexRangeIter<'a> {
170    /// The iterator seeking for matching values.
171    iter: TypedIndexRangeIter<'a>,
172}
173
174impl Iterator for TableIndexRangeIter<'_> {
175    type Item = RowPointer;
176
177    fn next(&mut self) -> Option<Self::Item> {
178        self.iter.next()
179    }
180}
181
182/// An index from a key type determined at runtime to `RowPointer`(s).
183///
184/// See module docs for info about specialization.
185#[derive(Debug, PartialEq, Eq)]
186enum TypedIndex {
187    // All the non-unique btree index types.
188    BtreeBool(BtreeIndex<bool>),
189    BtreeU8(BtreeIndex<u8>),
190    BtreeI8(BtreeIndex<i8>),
191    BtreeU16(BtreeIndex<u16>),
192    BtreeI16(BtreeIndex<i16>),
193    BtreeU32(BtreeIndex<u32>),
194    BtreeI32(BtreeIndex<i32>),
195    BtreeU64(BtreeIndex<u64>),
196    BtreeI64(BtreeIndex<i64>),
197    BtreeU128(BtreeIndex<Packed<u128>>),
198    BtreeI128(BtreeIndex<Packed<i128>>),
199    BtreeU256(BtreeIndex<u256>),
200    BtreeI256(BtreeIndex<i256>),
201    BtreeString(BtreeIndex<Box<str>>),
202    BtreeAV(BtreeIndex<AlgebraicValue>),
203
204    // All the unique btree index types.
205    UniqueBtreeBool(BtreeUniqueIndex<bool>),
206    UniqueBtreeU8(BtreeUniqueIndex<u8>),
207    UniqueBtreeI8(BtreeUniqueIndex<i8>),
208    UniqueBtreeU16(BtreeUniqueIndex<u16>),
209    UniqueBtreeI16(BtreeUniqueIndex<i16>),
210    UniqueBtreeU32(BtreeUniqueIndex<u32>),
211    UniqueBtreeI32(BtreeUniqueIndex<i32>),
212    UniqueBtreeU64(BtreeUniqueIndex<u64>),
213    UniqueBtreeI64(BtreeUniqueIndex<i64>),
214    UniqueBtreeU128(BtreeUniqueIndex<Packed<u128>>),
215    UniqueBtreeI128(BtreeUniqueIndex<Packed<i128>>),
216    UniqueBtreeU256(BtreeUniqueIndex<u256>),
217    UniqueBtreeI256(BtreeUniqueIndex<i256>),
218    UniqueBtreeString(BtreeUniqueIndex<Box<str>>),
219    UniqueBtreeAV(BtreeUniqueIndex<AlgebraicValue>),
220
221    // All the unique direct index types.
222    UniqueDirectU8(UniqueDirectIndex),
223    UniqueDirectU16(UniqueDirectIndex),
224    UniqueDirectU32(UniqueDirectIndex),
225    UniqueDirectU64(UniqueDirectIndex),
226}
227
228impl MemoryUsage for TypedIndex {
229    fn heap_usage(&self) -> usize {
230        match self {
231            TypedIndex::BtreeBool(this) => this.heap_usage(),
232            TypedIndex::BtreeU8(this) => this.heap_usage(),
233            TypedIndex::BtreeI8(this) => this.heap_usage(),
234            TypedIndex::BtreeU16(this) => this.heap_usage(),
235            TypedIndex::BtreeI16(this) => this.heap_usage(),
236            TypedIndex::BtreeU32(this) => this.heap_usage(),
237            TypedIndex::BtreeI32(this) => this.heap_usage(),
238            TypedIndex::BtreeU64(this) => this.heap_usage(),
239            TypedIndex::BtreeI64(this) => this.heap_usage(),
240            TypedIndex::BtreeU128(this) => this.heap_usage(),
241            TypedIndex::BtreeI128(this) => this.heap_usage(),
242            TypedIndex::BtreeU256(this) => this.heap_usage(),
243            TypedIndex::BtreeI256(this) => this.heap_usage(),
244            TypedIndex::BtreeString(this) => this.heap_usage(),
245            TypedIndex::BtreeAV(this) => this.heap_usage(),
246
247            TypedIndex::UniqueBtreeBool(this) => this.heap_usage(),
248            TypedIndex::UniqueBtreeU8(this) => this.heap_usage(),
249            TypedIndex::UniqueBtreeI8(this) => this.heap_usage(),
250            TypedIndex::UniqueBtreeU16(this) => this.heap_usage(),
251            TypedIndex::UniqueBtreeI16(this) => this.heap_usage(),
252            TypedIndex::UniqueBtreeU32(this) => this.heap_usage(),
253            TypedIndex::UniqueBtreeI32(this) => this.heap_usage(),
254            TypedIndex::UniqueBtreeU64(this) => this.heap_usage(),
255            TypedIndex::UniqueBtreeI64(this) => this.heap_usage(),
256            TypedIndex::UniqueBtreeU128(this) => this.heap_usage(),
257            TypedIndex::UniqueBtreeI128(this) => this.heap_usage(),
258            TypedIndex::UniqueBtreeU256(this) => this.heap_usage(),
259            TypedIndex::UniqueBtreeI256(this) => this.heap_usage(),
260            TypedIndex::UniqueBtreeString(this) => this.heap_usage(),
261            TypedIndex::UniqueBtreeAV(this) => this.heap_usage(),
262
263            TypedIndex::UniqueDirectU8(this)
264            | TypedIndex::UniqueDirectU16(this)
265            | TypedIndex::UniqueDirectU32(this)
266            | TypedIndex::UniqueDirectU64(this) => this.heap_usage(),
267        }
268    }
269}
270
271impl TypedIndex {
272    /// Returns a new index with keys being of `key_type` and the index possibly `is_unique`.
273    fn new(key_type: &AlgebraicType, index_algo: &IndexAlgorithm, is_unique: bool) -> Self {
274        use TypedIndex::*;
275
276        if let IndexAlgorithm::Direct(_) = index_algo {
277            assert!(is_unique);
278            return match key_type {
279                AlgebraicType::U8 => Self::UniqueDirectU8(<_>::default()),
280                AlgebraicType::U16 => Self::UniqueDirectU16(<_>::default()),
281                AlgebraicType::U32 => Self::UniqueDirectU32(<_>::default()),
282                AlgebraicType::U64 => Self::UniqueDirectU64(<_>::default()),
283                _ => unreachable!("unexpected key type {key_type:?} for direct index"),
284            };
285        }
286
287        // If the index is on a single column of a primitive type,
288        // use a homogeneous map with a native key type.
289        if is_unique {
290            match key_type {
291                AlgebraicType::Bool => UniqueBtreeBool(<_>::default()),
292                AlgebraicType::I8 => UniqueBtreeI8(<_>::default()),
293                AlgebraicType::U8 => UniqueBtreeU8(<_>::default()),
294                AlgebraicType::I16 => UniqueBtreeI16(<_>::default()),
295                AlgebraicType::U16 => UniqueBtreeU16(<_>::default()),
296                AlgebraicType::I32 => UniqueBtreeI32(<_>::default()),
297                AlgebraicType::U32 => UniqueBtreeU32(<_>::default()),
298                AlgebraicType::I64 => UniqueBtreeI64(<_>::default()),
299                AlgebraicType::U64 => UniqueBtreeU64(<_>::default()),
300                AlgebraicType::I128 => UniqueBtreeI128(<_>::default()),
301                AlgebraicType::U128 => UniqueBtreeU128(<_>::default()),
302                AlgebraicType::I256 => UniqueBtreeI256(<_>::default()),
303                AlgebraicType::U256 => UniqueBtreeU256(<_>::default()),
304                AlgebraicType::String => UniqueBtreeString(<_>::default()),
305
306                // The index is either multi-column,
307                // or we don't care to specialize on the key type,
308                // so use a map keyed on `AlgebraicValue`.
309                _ => UniqueBtreeAV(<_>::default()),
310            }
311        } else {
312            match key_type {
313                AlgebraicType::Bool => BtreeBool(<_>::default()),
314                AlgebraicType::I8 => BtreeI8(<_>::default()),
315                AlgebraicType::U8 => BtreeU8(<_>::default()),
316                AlgebraicType::I16 => BtreeI16(<_>::default()),
317                AlgebraicType::U16 => BtreeU16(<_>::default()),
318                AlgebraicType::I32 => BtreeI32(<_>::default()),
319                AlgebraicType::U32 => BtreeU32(<_>::default()),
320                AlgebraicType::I64 => BtreeI64(<_>::default()),
321                AlgebraicType::U64 => BtreeU64(<_>::default()),
322                AlgebraicType::I128 => BtreeI128(<_>::default()),
323                AlgebraicType::U128 => BtreeU128(<_>::default()),
324                AlgebraicType::I256 => BtreeI256(<_>::default()),
325                AlgebraicType::U256 => BtreeU256(<_>::default()),
326                AlgebraicType::String => BtreeString(<_>::default()),
327
328                // The index is either multi-column,
329                // or we don't care to specialize on the key type,
330                // so use a map keyed on `AlgebraicValue`.
331                _ => BtreeAV(<_>::default()),
332            }
333        }
334    }
335
336    /// Clones the structure of this index but not the indexed elements,
337    /// so the returned index is empty.
338    fn clone_structure(&self) -> Self {
339        use TypedIndex::*;
340        match self {
341            BtreeBool(_) => BtreeBool(<_>::default()),
342            BtreeU8(_) => BtreeU8(<_>::default()),
343            BtreeI8(_) => BtreeI8(<_>::default()),
344            BtreeU16(_) => BtreeU16(<_>::default()),
345            BtreeI16(_) => BtreeI16(<_>::default()),
346            BtreeU32(_) => BtreeU32(<_>::default()),
347            BtreeI32(_) => BtreeI32(<_>::default()),
348            BtreeU64(_) => BtreeU64(<_>::default()),
349            BtreeI64(_) => BtreeI64(<_>::default()),
350            BtreeU128(_) => BtreeU128(<_>::default()),
351            BtreeI128(_) => BtreeI128(<_>::default()),
352            BtreeU256(_) => BtreeU256(<_>::default()),
353            BtreeI256(_) => BtreeI256(<_>::default()),
354            BtreeString(_) => BtreeString(<_>::default()),
355            BtreeAV(_) => BtreeAV(<_>::default()),
356            UniqueBtreeBool(_) => UniqueBtreeBool(<_>::default()),
357            UniqueBtreeU8(_) => UniqueBtreeU8(<_>::default()),
358            UniqueBtreeI8(_) => UniqueBtreeI8(<_>::default()),
359            UniqueBtreeU16(_) => UniqueBtreeU16(<_>::default()),
360            UniqueBtreeI16(_) => UniqueBtreeI16(<_>::default()),
361            UniqueBtreeU32(_) => UniqueBtreeU32(<_>::default()),
362            UniqueBtreeI32(_) => UniqueBtreeI32(<_>::default()),
363            UniqueBtreeU64(_) => UniqueBtreeU64(<_>::default()),
364            UniqueBtreeI64(_) => UniqueBtreeI64(<_>::default()),
365            UniqueBtreeU128(_) => UniqueBtreeU128(<_>::default()),
366            UniqueBtreeI128(_) => UniqueBtreeI128(<_>::default()),
367            UniqueBtreeU256(_) => UniqueBtreeU256(<_>::default()),
368            UniqueBtreeI256(_) => UniqueBtreeI256(<_>::default()),
369            UniqueBtreeString(_) => UniqueBtreeString(<_>::default()),
370            UniqueBtreeAV(_) => UniqueBtreeAV(<_>::default()),
371            UniqueDirectU8(_) => UniqueDirectU8(<_>::default()),
372            UniqueDirectU16(_) => UniqueDirectU16(<_>::default()),
373            UniqueDirectU32(_) => UniqueDirectU32(<_>::default()),
374            UniqueDirectU64(_) => UniqueDirectU64(<_>::default()),
375        }
376    }
377
378    /// Returns whether this is a unique index or not.
379    fn is_unique(&self) -> bool {
380        use TypedIndex::*;
381        match self {
382            BtreeBool(_) | BtreeU8(_) | BtreeI8(_) | BtreeU16(_) | BtreeI16(_) | BtreeU32(_) | BtreeI32(_)
383            | BtreeU64(_) | BtreeI64(_) | BtreeU128(_) | BtreeI128(_) | BtreeU256(_) | BtreeI256(_)
384            | BtreeString(_) | BtreeAV(_) => false,
385            UniqueBtreeBool(_) | UniqueBtreeU8(_) | UniqueBtreeI8(_) | UniqueBtreeU16(_) | UniqueBtreeI16(_)
386            | UniqueBtreeU32(_) | UniqueBtreeI32(_) | UniqueBtreeU64(_) | UniqueBtreeI64(_) | UniqueBtreeU128(_)
387            | UniqueBtreeI128(_) | UniqueBtreeU256(_) | UniqueBtreeI256(_) | UniqueBtreeString(_)
388            | UniqueBtreeAV(_) | UniqueDirectU8(_) | UniqueDirectU16(_) | UniqueDirectU32(_) | UniqueDirectU64(_) => {
389                true
390            }
391        }
392    }
393
394    /// Add the row referred to by `row_ref` to the index `self`,
395    /// which must be keyed at `cols`.
396    ///
397    /// The returned `usize` is the number of bytes used by the key.
398    /// [`TableIndex::check_and_insert`] will use this
399    /// to update the counter for [`TableIndex::num_key_bytes`].
400    /// We want to store said counter outside of the [`TypedIndex`] enum,
401    /// but we can only compute the size using type info within the [`TypedIndex`],
402    /// so we have to return the size across this boundary.
403    ///
404    /// Returns `Errs(existing_row)` if this index was a unique index that was violated.
405    /// The index is not inserted to in that case.
406    ///
407    /// # Safety
408    ///
409    /// 1. Caller promises that `cols` matches what was given at construction (`Self::new`).
410    /// 2. Caller promises that the projection of `row_ref`'s type's equals the index's key type.
411    unsafe fn insert(&mut self, cols: &ColList, row_ref: RowRef<'_>) -> Result<usize, RowPointer> {
412        fn project_to_singleton_key<T: ReadColumn>(cols: &ColList, row_ref: RowRef<'_>) -> T {
413            // Extract the column.
414            let col_pos = cols.as_singleton();
415            // SAFETY: Caller promised that `cols` matches what was given at construction (`Self::new`).
416            // In the case of `.clone_structure()`, the structure is preserved,
417            // so the promise is also preserved.
418            // This entails, that because we reached here, that `cols` is singleton.
419            let col_pos = unsafe { col_pos.unwrap_unchecked() }.idx();
420
421            // Extract the layout of the column.
422            let col_layouts = &row_ref.row_layout().product().elements;
423            // SAFETY:
424            // - Caller promised that projecting the `row_ref`'s type/layout to `self.indexed_columns`
425            //   gives us the index's key type.
426            //   This entails that each `ColId` in `self.indexed_columns`
427            //   must be in-bounds of `row_ref`'s layout.
428            let col_layout = unsafe { col_layouts.get_unchecked(col_pos) };
429
430            // Read the column in `row_ref`.
431            // SAFETY:
432            // - `col_layout` was just derived from the row layout.
433            // - Caller promised that the type-projection of the row type/layout
434            //   equals the index's key type.
435            //   We've reached here, so the index's key type is compatible with `T`.
436            // - `self` is a valid row so offsetting to `col_layout` is valid.
437            unsafe { T::unchecked_read_column(row_ref, col_layout) }
438        }
439
440        fn mm_insert_at_type<T: Ord + ReadColumn + KeySize>(
441            this: &mut BtreeIndex<T>,
442            cols: &ColList,
443            row_ref: RowRef<'_>,
444        ) -> Result<usize, RowPointer> {
445            let key: T = project_to_singleton_key(cols, row_ref);
446            let key_size = key.key_size_in_bytes();
447            this.insert(key, row_ref.pointer());
448            Ok(key_size)
449        }
450        fn um_insert_at_type<T: Ord + ReadColumn + KeySize>(
451            this: &mut BtreeUniqueIndex<T>,
452            cols: &ColList,
453            row_ref: RowRef<'_>,
454        ) -> Result<usize, RowPointer> {
455            let key: T = project_to_singleton_key(cols, row_ref);
456            let key_size = key.key_size_in_bytes();
457            this.insert(key, row_ref.pointer())
458                .map_err(|ptr| *ptr)
459                .map(|_| key_size)
460        }
461        fn direct_insert_at_type<T: ReadColumn>(
462            this: &mut UniqueDirectIndex,
463            cols: &ColList,
464            row_ref: RowRef<'_>,
465            to_usize: impl FnOnce(T) -> usize,
466        ) -> Result<usize, RowPointer> {
467            let key: T = project_to_singleton_key(cols, row_ref);
468            let key = to_usize(key);
469            let key_size = key.key_size_in_bytes();
470            this.insert(key, row_ref.pointer()).map(|_| key_size)
471        }
472        match self {
473            Self::BtreeBool(idx) => mm_insert_at_type(idx, cols, row_ref),
474            Self::BtreeU8(idx) => mm_insert_at_type(idx, cols, row_ref),
475            Self::BtreeI8(idx) => mm_insert_at_type(idx, cols, row_ref),
476            Self::BtreeU16(idx) => mm_insert_at_type(idx, cols, row_ref),
477            Self::BtreeI16(idx) => mm_insert_at_type(idx, cols, row_ref),
478            Self::BtreeU32(idx) => mm_insert_at_type(idx, cols, row_ref),
479            Self::BtreeI32(idx) => mm_insert_at_type(idx, cols, row_ref),
480            Self::BtreeU64(idx) => mm_insert_at_type(idx, cols, row_ref),
481            Self::BtreeI64(idx) => mm_insert_at_type(idx, cols, row_ref),
482            Self::BtreeU128(idx) => mm_insert_at_type(idx, cols, row_ref),
483            Self::BtreeI128(idx) => mm_insert_at_type(idx, cols, row_ref),
484            Self::BtreeU256(idx) => mm_insert_at_type(idx, cols, row_ref),
485            Self::BtreeI256(idx) => mm_insert_at_type(idx, cols, row_ref),
486            Self::BtreeString(idx) => mm_insert_at_type(idx, cols, row_ref),
487            Self::BtreeAV(this) => {
488                // SAFETY: Caller promised that any `col` in `cols` is in-bounds of `row_ref`'s layout.
489                let key = unsafe { row_ref.project_unchecked(cols) };
490                let key_size = key.key_size_in_bytes();
491                this.insert(key, row_ref.pointer());
492                Ok(key_size)
493            }
494            Self::UniqueBtreeBool(idx) => um_insert_at_type(idx, cols, row_ref),
495            Self::UniqueBtreeU8(idx) => um_insert_at_type(idx, cols, row_ref),
496            Self::UniqueBtreeI8(idx) => um_insert_at_type(idx, cols, row_ref),
497            Self::UniqueBtreeU16(idx) => um_insert_at_type(idx, cols, row_ref),
498            Self::UniqueBtreeI16(idx) => um_insert_at_type(idx, cols, row_ref),
499            Self::UniqueBtreeU32(idx) => um_insert_at_type(idx, cols, row_ref),
500            Self::UniqueBtreeI32(idx) => um_insert_at_type(idx, cols, row_ref),
501            Self::UniqueBtreeU64(idx) => um_insert_at_type(idx, cols, row_ref),
502            Self::UniqueBtreeI64(idx) => um_insert_at_type(idx, cols, row_ref),
503            Self::UniqueBtreeU128(idx) => um_insert_at_type(idx, cols, row_ref),
504            Self::UniqueBtreeI128(idx) => um_insert_at_type(idx, cols, row_ref),
505            Self::UniqueBtreeU256(idx) => um_insert_at_type(idx, cols, row_ref),
506            Self::UniqueBtreeI256(idx) => um_insert_at_type(idx, cols, row_ref),
507            Self::UniqueBtreeString(idx) => um_insert_at_type(idx, cols, row_ref),
508            Self::UniqueBtreeAV(this) => {
509                // SAFETY: Caller promised that any `col` in `cols` is in-bounds of `row_ref`'s layout.
510                let key = unsafe { row_ref.project_unchecked(cols) };
511                let key_size = key.key_size_in_bytes();
512                this.insert(key, row_ref.pointer())
513                    .map_err(|ptr| *ptr)
514                    .map(|_| key_size)
515            }
516            Self::UniqueDirectU8(idx) => direct_insert_at_type(idx, cols, row_ref, |k: u8| k as usize),
517            Self::UniqueDirectU16(idx) => direct_insert_at_type(idx, cols, row_ref, |k: u16| k as usize),
518            Self::UniqueDirectU32(idx) => direct_insert_at_type(idx, cols, row_ref, |k: u32| k as usize),
519            Self::UniqueDirectU64(idx) => direct_insert_at_type(idx, cols, row_ref, |k: u64| k as usize),
520        }
521    }
522
523    /// Remove the row referred to by `row_ref` from the index `self`,
524    /// which must be keyed at `cols`.
525    ///
526    /// If `cols` is inconsistent with `self`,
527    /// or the `row_ref` has a row type other than that used for `self`,
528    /// this will behave oddly; it may return an error, do nothing,
529    /// or remove the wrong value from the index.
530    /// Note, however, that it will not invoke undefined behavior.
531    ///
532    /// If the row was present and has been deleted, returns `Ok(Some(key_size_in_bytes))`,
533    /// where `key_size_in_bytes` is the size of the key.
534    /// [`TableIndex::delete`] will use this
535    /// to update the counter for [`TableIndex::num_key_bytes`].
536    /// We want to store said counter outside of the [`TypedIndex`] enum,
537    /// but we can only compute the size using type info within the [`TypedIndex`],
538    /// so we have to return the size across this boundary.
539    fn delete(&mut self, cols: &ColList, row_ref: RowRef<'_>) -> Result<Option<usize>, InvalidFieldError> {
540        fn mm_delete_at_type<T: Ord + ReadColumn + KeySize>(
541            this: &mut BtreeIndex<T>,
542            cols: &ColList,
543            row_ref: RowRef<'_>,
544        ) -> Result<Option<usize>, InvalidFieldError> {
545            let col_pos = cols.as_singleton().unwrap();
546            let key: T = row_ref.read_col(col_pos).map_err(|_| col_pos)?;
547            let key_size = key.key_size_in_bytes();
548            Ok(this.delete(&key, &row_ref.pointer()).then_some(key_size))
549        }
550        fn um_delete_at_type<T: Ord + ReadColumn + KeySize>(
551            this: &mut BtreeUniqueIndex<T>,
552            cols: &ColList,
553            row_ref: RowRef<'_>,
554        ) -> Result<Option<usize>, InvalidFieldError> {
555            let col_pos = cols.as_singleton().unwrap();
556            let key: T = row_ref.read_col(col_pos).map_err(|_| col_pos)?;
557            let key_size = key.key_size_in_bytes();
558            Ok(this.delete(&key).then_some(key_size))
559        }
560        fn direct_delete_at_type<T: ReadColumn>(
561            this: &mut UniqueDirectIndex,
562            cols: &ColList,
563            row_ref: RowRef<'_>,
564            to_usize: impl FnOnce(T) -> usize,
565        ) -> Result<Option<usize>, InvalidFieldError> {
566            let col_pos = cols.as_singleton().unwrap();
567            let key: T = row_ref.read_col(col_pos).map_err(|_| col_pos)?;
568            let key = to_usize(key);
569            let key_size = key.key_size_in_bytes();
570            Ok(this.delete(key).then_some(key_size))
571        }
572
573        match self {
574            Self::BtreeBool(this) => mm_delete_at_type(this, cols, row_ref),
575            Self::BtreeU8(this) => mm_delete_at_type(this, cols, row_ref),
576            Self::BtreeI8(this) => mm_delete_at_type(this, cols, row_ref),
577            Self::BtreeU16(this) => mm_delete_at_type(this, cols, row_ref),
578            Self::BtreeI16(this) => mm_delete_at_type(this, cols, row_ref),
579            Self::BtreeU32(this) => mm_delete_at_type(this, cols, row_ref),
580            Self::BtreeI32(this) => mm_delete_at_type(this, cols, row_ref),
581            Self::BtreeU64(this) => mm_delete_at_type(this, cols, row_ref),
582            Self::BtreeI64(this) => mm_delete_at_type(this, cols, row_ref),
583            Self::BtreeU128(this) => mm_delete_at_type(this, cols, row_ref),
584            Self::BtreeI128(this) => mm_delete_at_type(this, cols, row_ref),
585            Self::BtreeU256(this) => mm_delete_at_type(this, cols, row_ref),
586            Self::BtreeI256(this) => mm_delete_at_type(this, cols, row_ref),
587            Self::BtreeString(this) => mm_delete_at_type(this, cols, row_ref),
588            Self::BtreeAV(this) => {
589                let key = row_ref.project(cols)?;
590                let key_size = key.key_size_in_bytes();
591                Ok(this.delete(&key, &row_ref.pointer()).then_some(key_size))
592            }
593            Self::UniqueBtreeBool(this) => um_delete_at_type(this, cols, row_ref),
594            Self::UniqueBtreeU8(this) => um_delete_at_type(this, cols, row_ref),
595            Self::UniqueBtreeI8(this) => um_delete_at_type(this, cols, row_ref),
596            Self::UniqueBtreeU16(this) => um_delete_at_type(this, cols, row_ref),
597            Self::UniqueBtreeI16(this) => um_delete_at_type(this, cols, row_ref),
598            Self::UniqueBtreeU32(this) => um_delete_at_type(this, cols, row_ref),
599            Self::UniqueBtreeI32(this) => um_delete_at_type(this, cols, row_ref),
600            Self::UniqueBtreeU64(this) => um_delete_at_type(this, cols, row_ref),
601            Self::UniqueBtreeI64(this) => um_delete_at_type(this, cols, row_ref),
602            Self::UniqueBtreeU128(this) => um_delete_at_type(this, cols, row_ref),
603            Self::UniqueBtreeI128(this) => um_delete_at_type(this, cols, row_ref),
604            Self::UniqueBtreeU256(this) => um_delete_at_type(this, cols, row_ref),
605            Self::UniqueBtreeI256(this) => um_delete_at_type(this, cols, row_ref),
606            Self::UniqueBtreeString(this) => um_delete_at_type(this, cols, row_ref),
607            Self::UniqueBtreeAV(this) => {
608                let key = row_ref.project(cols)?;
609                let key_size = key.key_size_in_bytes();
610                Ok(this.delete(&key).then_some(key_size))
611            }
612            Self::UniqueDirectU8(this) => direct_delete_at_type(this, cols, row_ref, |k: u8| k as usize),
613            Self::UniqueDirectU16(this) => direct_delete_at_type(this, cols, row_ref, |k: u16| k as usize),
614            Self::UniqueDirectU32(this) => direct_delete_at_type(this, cols, row_ref, |k: u32| k as usize),
615            Self::UniqueDirectU64(this) => direct_delete_at_type(this, cols, row_ref, |k: u64| k as usize),
616        }
617    }
618
619    fn seek_point(&self, key: &AlgebraicValue) -> TypedIndexPointIter<'_> {
620        fn mm_iter_at_type<'a, T: Ord>(
621            this: &'a BtreeIndex<T>,
622            key: &AlgebraicValue,
623            av_as_t: impl Fn(&AlgebraicValue) -> Option<&T>,
624        ) -> BtreeIndexPointIter<'a> {
625            this.values_in_point(av_as_t(key).expect("key does not conform to key type of index"))
626        }
627        fn um_iter_at_type<'a, T: Ord>(
628            this: &'a BtreeUniqueIndex<T>,
629            key: &AlgebraicValue,
630            av_as_t: impl Fn(&AlgebraicValue) -> Option<&T>,
631        ) -> BtreeUniqueIndexPointIter<'a> {
632            this.values_in_point(av_as_t(key).expect("key does not conform to key type of index"))
633        }
634        fn direct_iter_at_type<T>(
635            this: &UniqueDirectIndex,
636            key: &AlgebraicValue,
637            av_as_t: impl Fn(&AlgebraicValue) -> Option<&T>,
638            to_usize: impl Copy + FnOnce(&T) -> usize,
639        ) -> UniqueDirectIndexPointIter {
640            let av_as_t = |v| av_as_t(v).expect("key does not conform to key type of index");
641            this.seek_point(to_usize(av_as_t(key)))
642        }
643
644        use TypedIndex::*;
645        use TypedIndexPointIter::*;
646        match self {
647            BtreeBool(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_bool)),
648            BtreeU8(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_u8)),
649            BtreeI8(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_i8)),
650            BtreeU16(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_u16)),
651            BtreeI16(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_i16)),
652            BtreeU32(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_u32)),
653            BtreeI32(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_i32)),
654            BtreeU64(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_u64)),
655            BtreeI64(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_i64)),
656            BtreeU128(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_u128)),
657            BtreeI128(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_i128)),
658            BtreeU256(this) => BTree(mm_iter_at_type(this, key, |av| av.as_u256().map(|x| &**x))),
659            BtreeI256(this) => BTree(mm_iter_at_type(this, key, |av| av.as_i256().map(|x| &**x))),
660            BtreeString(this) => BTree(mm_iter_at_type(this, key, AlgebraicValue::as_string)),
661            BtreeAV(this) => BTree(this.values_in_point(key)),
662
663            UniqueBtreeBool(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_bool)),
664            UniqueBtreeU8(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_u8)),
665            UniqueBtreeI8(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_i8)),
666            UniqueBtreeU16(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_u16)),
667            UniqueBtreeI16(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_i16)),
668            UniqueBtreeU32(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_u32)),
669            UniqueBtreeI32(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_i32)),
670            UniqueBtreeU64(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_u64)),
671            UniqueBtreeI64(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_i64)),
672            UniqueBtreeU128(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_u128)),
673            UniqueBtreeI128(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_i128)),
674            UniqueBtreeU256(this) => UniqueBTree(um_iter_at_type(this, key, |av| av.as_u256().map(|x| &**x))),
675            UniqueBtreeI256(this) => UniqueBTree(um_iter_at_type(this, key, |av| av.as_i256().map(|x| &**x))),
676            UniqueBtreeString(this) => UniqueBTree(um_iter_at_type(this, key, AlgebraicValue::as_string)),
677            UniqueBtreeAV(this) => UniqueBTree(this.values_in_point(key)),
678
679            UniqueDirectU8(this) => {
680                UniqueDirect(direct_iter_at_type(this, key, AlgebraicValue::as_u8, |k| *k as usize))
681            }
682            UniqueDirectU16(this) => {
683                UniqueDirect(direct_iter_at_type(this, key, AlgebraicValue::as_u16, |k| *k as usize))
684            }
685            UniqueDirectU32(this) => {
686                UniqueDirect(direct_iter_at_type(this, key, AlgebraicValue::as_u32, |k| *k as usize))
687            }
688            UniqueDirectU64(this) => {
689                UniqueDirect(direct_iter_at_type(this, key, AlgebraicValue::as_u64, |k| *k as usize))
690            }
691        }
692    }
693
694    fn seek_range(&self, range: &impl RangeBounds<AlgebraicValue>) -> TypedIndexRangeIter<'_> {
695        fn mm_iter_at_type<'a, T: Ord>(
696            this: &'a BtreeIndex<T>,
697            range: &impl RangeBounds<AlgebraicValue>,
698            av_as_t: impl Fn(&AlgebraicValue) -> Option<&T>,
699        ) -> BtreeIndexRangeIter<'a, T> {
700            let av_as_t = |v| av_as_t(v).expect("bound does not conform to key type of index");
701            let start = range.start_bound().map(av_as_t);
702            let end = range.end_bound().map(av_as_t);
703            this.values_in_range(&(start, end))
704        }
705        fn um_iter_at_type<'a, T: Ord>(
706            this: &'a BtreeUniqueIndex<T>,
707            range: &impl RangeBounds<AlgebraicValue>,
708            av_as_t: impl Fn(&AlgebraicValue) -> Option<&T>,
709        ) -> BtreeUniqueIndexRangeIter<'a, T> {
710            let av_as_t = |v| av_as_t(v).expect("bound does not conform to key type of index");
711            let start = range.start_bound().map(av_as_t);
712            let end = range.end_bound().map(av_as_t);
713            this.values_in_range(&(start, end))
714        }
715        fn direct_iter_at_type<'a, T>(
716            this: &'a UniqueDirectIndex,
717            range: &impl RangeBounds<AlgebraicValue>,
718            av_as_t: impl Fn(&AlgebraicValue) -> Option<&T>,
719            to_usize: impl Copy + FnOnce(&T) -> usize,
720        ) -> UniqueDirectIndexRangeIter<'a> {
721            let av_as_t = |v| av_as_t(v).expect("bound does not conform to key type of index");
722            let start = range.start_bound().map(av_as_t).map(to_usize);
723            let end = range.end_bound().map(av_as_t).map(to_usize);
724            this.seek_range(&(start, end))
725        }
726
727        use TypedIndexRangeIter::*;
728        match self {
729            Self::BtreeBool(this) => BtreeBool(mm_iter_at_type(this, range, AlgebraicValue::as_bool)),
730            Self::BtreeU8(this) => BtreeU8(mm_iter_at_type(this, range, AlgebraicValue::as_u8)),
731            Self::BtreeI8(this) => BtreeI8(mm_iter_at_type(this, range, AlgebraicValue::as_i8)),
732            Self::BtreeU16(this) => BtreeU16(mm_iter_at_type(this, range, AlgebraicValue::as_u16)),
733            Self::BtreeI16(this) => BtreeI16(mm_iter_at_type(this, range, AlgebraicValue::as_i16)),
734            Self::BtreeU32(this) => BtreeU32(mm_iter_at_type(this, range, AlgebraicValue::as_u32)),
735            Self::BtreeI32(this) => BtreeI32(mm_iter_at_type(this, range, AlgebraicValue::as_i32)),
736            Self::BtreeU64(this) => BtreeU64(mm_iter_at_type(this, range, AlgebraicValue::as_u64)),
737            Self::BtreeI64(this) => BtreeI64(mm_iter_at_type(this, range, AlgebraicValue::as_i64)),
738            Self::BtreeU128(this) => BtreeU128(mm_iter_at_type(this, range, AlgebraicValue::as_u128)),
739            Self::BtreeI128(this) => BtreeI128(mm_iter_at_type(this, range, AlgebraicValue::as_i128)),
740            Self::BtreeU256(this) => BtreeU256(mm_iter_at_type(this, range, |av| av.as_u256().map(|x| &**x))),
741            Self::BtreeI256(this) => BtreeI256(mm_iter_at_type(this, range, |av| av.as_i256().map(|x| &**x))),
742            Self::BtreeString(this) => BtreeString(mm_iter_at_type(this, range, AlgebraicValue::as_string)),
743            Self::BtreeAV(this) => BtreeAV(this.values_in_range(range)),
744
745            Self::UniqueBtreeBool(this) => UniqueBtreeBool(um_iter_at_type(this, range, AlgebraicValue::as_bool)),
746            Self::UniqueBtreeU8(this) => UniqueBtreeU8(um_iter_at_type(this, range, AlgebraicValue::as_u8)),
747            Self::UniqueBtreeI8(this) => UniqueBtreeI8(um_iter_at_type(this, range, AlgebraicValue::as_i8)),
748            Self::UniqueBtreeU16(this) => UniqueBtreeU16(um_iter_at_type(this, range, AlgebraicValue::as_u16)),
749            Self::UniqueBtreeI16(this) => UniqueBtreeI16(um_iter_at_type(this, range, AlgebraicValue::as_i16)),
750            Self::UniqueBtreeU32(this) => UniqueBtreeU32(um_iter_at_type(this, range, AlgebraicValue::as_u32)),
751            Self::UniqueBtreeI32(this) => UniqueBtreeI32(um_iter_at_type(this, range, AlgebraicValue::as_i32)),
752            Self::UniqueBtreeU64(this) => UniqueBtreeU64(um_iter_at_type(this, range, AlgebraicValue::as_u64)),
753            Self::UniqueBtreeI64(this) => UniqueBtreeI64(um_iter_at_type(this, range, AlgebraicValue::as_i64)),
754            Self::UniqueBtreeU128(this) => UniqueBtreeU128(um_iter_at_type(this, range, AlgebraicValue::as_u128)),
755            Self::UniqueBtreeI128(this) => UniqueBtreeI128(um_iter_at_type(this, range, AlgebraicValue::as_i128)),
756            Self::UniqueBtreeU256(this) => {
757                UniqueBtreeU256(um_iter_at_type(this, range, |av| av.as_u256().map(|x| &**x)))
758            }
759            Self::UniqueBtreeI256(this) => {
760                UniqueBtreeI256(um_iter_at_type(this, range, |av| av.as_i256().map(|x| &**x)))
761            }
762            Self::UniqueBtreeString(this) => UniqueBtreeString(um_iter_at_type(this, range, AlgebraicValue::as_string)),
763            Self::UniqueBtreeAV(this) => UniqueBtreeAV(this.values_in_range(range)),
764
765            Self::UniqueDirectU8(this) => {
766                UniqueDirect(direct_iter_at_type(this, range, AlgebraicValue::as_u8, |k| *k as usize))
767            }
768            Self::UniqueDirectU16(this) => {
769                UniqueDirect(direct_iter_at_type(this, range, AlgebraicValue::as_u16, |k| {
770                    *k as usize
771                }))
772            }
773            Self::UniqueDirectU32(this) => {
774                UniqueDirect(direct_iter_at_type(this, range, AlgebraicValue::as_u32, |k| {
775                    *k as usize
776                }))
777            }
778            Self::UniqueDirectU64(this) => {
779                UniqueDirect(direct_iter_at_type(this, range, AlgebraicValue::as_u64, |k| {
780                    *k as usize
781                }))
782            }
783        }
784    }
785
786    fn clear(&mut self) {
787        match self {
788            Self::BtreeBool(this) => this.clear(),
789            Self::BtreeU8(this) => this.clear(),
790            Self::BtreeI8(this) => this.clear(),
791            Self::BtreeU16(this) => this.clear(),
792            Self::BtreeI16(this) => this.clear(),
793            Self::BtreeU32(this) => this.clear(),
794            Self::BtreeI32(this) => this.clear(),
795            Self::BtreeU64(this) => this.clear(),
796            Self::BtreeI64(this) => this.clear(),
797            Self::BtreeU128(this) => this.clear(),
798            Self::BtreeI128(this) => this.clear(),
799            Self::BtreeU256(this) => this.clear(),
800            Self::BtreeI256(this) => this.clear(),
801            Self::BtreeString(this) => this.clear(),
802            Self::BtreeAV(this) => this.clear(),
803
804            Self::UniqueBtreeBool(this) => this.clear(),
805            Self::UniqueBtreeU8(this) => this.clear(),
806            Self::UniqueBtreeI8(this) => this.clear(),
807            Self::UniqueBtreeU16(this) => this.clear(),
808            Self::UniqueBtreeI16(this) => this.clear(),
809            Self::UniqueBtreeU32(this) => this.clear(),
810            Self::UniqueBtreeI32(this) => this.clear(),
811            Self::UniqueBtreeU64(this) => this.clear(),
812            Self::UniqueBtreeI64(this) => this.clear(),
813            Self::UniqueBtreeU128(this) => this.clear(),
814            Self::UniqueBtreeI128(this) => this.clear(),
815            Self::UniqueBtreeU256(this) => this.clear(),
816            Self::UniqueBtreeI256(this) => this.clear(),
817            Self::UniqueBtreeString(this) => this.clear(),
818            Self::UniqueBtreeAV(this) => this.clear(),
819
820            Self::UniqueDirectU8(this)
821            | Self::UniqueDirectU16(this)
822            | Self::UniqueDirectU32(this)
823            | Self::UniqueDirectU64(this) => this.clear(),
824        }
825    }
826
827    #[allow(unused)] // used only by tests
828    fn is_empty(&self) -> bool {
829        self.len() == 0
830    }
831
832    #[allow(unused)] // used only by tests
833    fn len(&self) -> usize {
834        match self {
835            Self::BtreeBool(this) => this.len(),
836            Self::BtreeU8(this) => this.len(),
837            Self::BtreeI8(this) => this.len(),
838            Self::BtreeU16(this) => this.len(),
839            Self::BtreeI16(this) => this.len(),
840            Self::BtreeU32(this) => this.len(),
841            Self::BtreeI32(this) => this.len(),
842            Self::BtreeU64(this) => this.len(),
843            Self::BtreeI64(this) => this.len(),
844            Self::BtreeU128(this) => this.len(),
845            Self::BtreeI128(this) => this.len(),
846            Self::BtreeU256(this) => this.len(),
847            Self::BtreeI256(this) => this.len(),
848            Self::BtreeString(this) => this.len(),
849            Self::BtreeAV(this) => this.len(),
850
851            Self::UniqueBtreeBool(this) => this.len(),
852            Self::UniqueBtreeU8(this) => this.len(),
853            Self::UniqueBtreeI8(this) => this.len(),
854            Self::UniqueBtreeU16(this) => this.len(),
855            Self::UniqueBtreeI16(this) => this.len(),
856            Self::UniqueBtreeU32(this) => this.len(),
857            Self::UniqueBtreeI32(this) => this.len(),
858            Self::UniqueBtreeU64(this) => this.len(),
859            Self::UniqueBtreeI64(this) => this.len(),
860            Self::UniqueBtreeU128(this) => this.len(),
861            Self::UniqueBtreeI128(this) => this.len(),
862            Self::UniqueBtreeU256(this) => this.len(),
863            Self::UniqueBtreeI256(this) => this.len(),
864            Self::UniqueBtreeString(this) => this.len(),
865            Self::UniqueBtreeAV(this) => this.len(),
866
867            Self::UniqueDirectU8(this)
868            | Self::UniqueDirectU16(this)
869            | Self::UniqueDirectU32(this)
870            | Self::UniqueDirectU64(this) => this.len(),
871        }
872    }
873
874    fn num_keys(&self) -> usize {
875        match self {
876            Self::BtreeBool(this) => this.num_keys(),
877            Self::BtreeU8(this) => this.num_keys(),
878            Self::BtreeI8(this) => this.num_keys(),
879            Self::BtreeU16(this) => this.num_keys(),
880            Self::BtreeI16(this) => this.num_keys(),
881            Self::BtreeU32(this) => this.num_keys(),
882            Self::BtreeI32(this) => this.num_keys(),
883            Self::BtreeU64(this) => this.num_keys(),
884            Self::BtreeI64(this) => this.num_keys(),
885            Self::BtreeU128(this) => this.num_keys(),
886            Self::BtreeI128(this) => this.num_keys(),
887            Self::BtreeU256(this) => this.num_keys(),
888            Self::BtreeI256(this) => this.num_keys(),
889            Self::BtreeString(this) => this.num_keys(),
890            Self::BtreeAV(this) => this.num_keys(),
891
892            Self::UniqueBtreeBool(this) => this.num_keys(),
893            Self::UniqueBtreeU8(this) => this.num_keys(),
894            Self::UniqueBtreeI8(this) => this.num_keys(),
895            Self::UniqueBtreeU16(this) => this.num_keys(),
896            Self::UniqueBtreeI16(this) => this.num_keys(),
897            Self::UniqueBtreeU32(this) => this.num_keys(),
898            Self::UniqueBtreeI32(this) => this.num_keys(),
899            Self::UniqueBtreeU64(this) => this.num_keys(),
900            Self::UniqueBtreeI64(this) => this.num_keys(),
901            Self::UniqueBtreeU128(this) => this.num_keys(),
902            Self::UniqueBtreeI128(this) => this.num_keys(),
903            Self::UniqueBtreeU256(this) => this.num_keys(),
904            Self::UniqueBtreeI256(this) => this.num_keys(),
905            Self::UniqueBtreeString(this) => this.num_keys(),
906            Self::UniqueBtreeAV(this) => this.num_keys(),
907
908            Self::UniqueDirectU8(this)
909            | Self::UniqueDirectU16(this)
910            | Self::UniqueDirectU32(this)
911            | Self::UniqueDirectU64(this) => this.num_keys(),
912        }
913    }
914}
915
916/// An index on a set of [`ColId`]s of a table.
917#[derive(Debug, PartialEq, Eq)]
918pub struct TableIndex {
919    /// The actual index, specialized for the appropriate key type.
920    idx: TypedIndex,
921    /// The key type of this index.
922    /// This is the projection of the row type to the types of the columns indexed.
923    // NOTE(centril): This is accessed in index scan ABIs for decoding, so don't `Box<_>` it.
924    pub key_type: AlgebraicType,
925
926    /// The number of rows in this index.
927    ///
928    /// Memoized counter for [`Self::num_rows`].
929    num_rows: u64,
930
931    /// The number of key bytes in this index.
932    ///
933    /// Memoized counter for [`Self::num_key_bytes`].
934    /// See that method for more detailed documentation.
935    num_key_bytes: u64,
936
937    /// Given a full row, typed at some `ty: ProductType`,
938    /// these columns are the ones that this index indexes.
939    /// Projecting the `ty` to `self.indexed_columns` yields the index's type `self.key_type`.
940    pub indexed_columns: ColList,
941}
942
943impl MemoryUsage for TableIndex {
944    fn heap_usage(&self) -> usize {
945        let Self {
946            idx,
947            key_type,
948            num_rows,
949            num_key_bytes,
950            indexed_columns,
951        } = self;
952        idx.heap_usage()
953            + key_type.heap_usage()
954            + num_rows.heap_usage()
955            + num_key_bytes.heap_usage()
956            + indexed_columns.heap_usage()
957    }
958}
959
960static_assert_size!(TableIndex, 88);
961
962impl TableIndex {
963    /// Returns a new possibly unique index, with `index_id` for a choice of indexing algorithm.
964    pub fn new(
965        row_type: &ProductType,
966        index_algo: &IndexAlgorithm,
967        is_unique: bool,
968    ) -> Result<Self, InvalidFieldError> {
969        let indexed_columns = index_algo.columns().to_owned();
970        let key_type = row_type.project(&indexed_columns)?;
971        let typed_index = TypedIndex::new(&key_type, index_algo, is_unique);
972        Ok(Self {
973            idx: typed_index,
974            key_type,
975            num_rows: 0,
976            num_key_bytes: 0,
977            indexed_columns,
978        })
979    }
980
981    /// Clones the structure of this index but not the indexed elements,
982    /// so the returned index is empty.
983    pub fn clone_structure(&self) -> Self {
984        let key_type = self.key_type.clone();
985        let idx = self.idx.clone_structure();
986        let indexed_columns = self.indexed_columns.clone();
987        Self {
988            idx,
989            key_type,
990            num_rows: 0,
991            num_key_bytes: 0,
992            indexed_columns,
993        }
994    }
995
996    /// Returns whether this is a unique index or not.
997    pub fn is_unique(&self) -> bool {
998        self.idx.is_unique()
999    }
1000
1001    /// Inserts `ptr` with the value `row` to this index.
1002    /// This index will extract the necessary values from `row` based on `self.indexed_columns`.
1003    ///
1004    /// Returns `Err(existing_row)` if this insertion would violate a unique constraint.
1005    ///
1006    /// # Safety
1007    ///
1008    /// Caller promises that projecting the `row_ref`'s type
1009    /// to the index's columns equals the index's key type.
1010    /// This is entailed by an index belonging to the table's schema.
1011    /// It also follows from `row_ref`'s type/layout
1012    /// being the same as passed in on `self`'s construction.
1013    pub unsafe fn check_and_insert(&mut self, row_ref: RowRef<'_>) -> Result<(), RowPointer> {
1014        // SAFETY:
1015        // 1. We're passing the same `ColList` that was provided during construction.
1016        // 2. Forward the caller's proof obligation.
1017        let res = unsafe { self.idx.insert(&self.indexed_columns, row_ref) };
1018        match res {
1019            Ok(key_size) => {
1020                // No existing row; the new row was inserted.
1021                // Update the `num_rows` and `num_key_bytes` counters
1022                // to account for the new insertion.
1023                self.num_rows += 1;
1024                self.num_key_bytes += key_size as u64;
1025                Ok(())
1026            }
1027            Err(e) => Err(e),
1028        }
1029    }
1030
1031    /// Deletes `row_ref` with its indexed value `row_ref.project(&self.indexed_columns)` from this index.
1032    ///
1033    /// Returns whether `ptr` was present.
1034    pub fn delete(&mut self, row_ref: RowRef<'_>) -> Result<bool, InvalidFieldError> {
1035        if let Some(size_in_bytes) = self.idx.delete(&self.indexed_columns, row_ref)? {
1036            // Was present, and deleted: update the `num_rows` and `num_key_bytes` counters.
1037            self.num_rows -= 1;
1038            self.num_key_bytes -= size_in_bytes as u64;
1039            Ok(true)
1040        } else {
1041            // Was not present: don't update counters.
1042            Ok(false)
1043        }
1044    }
1045
1046    /// Returns whether `value` is in this index.
1047    pub fn contains_any(&self, value: &AlgebraicValue) -> bool {
1048        self.seek_point(value).next().is_some()
1049    }
1050
1051    /// Returns the number of rows associated with this `value`.
1052    /// Returns `None` if 0.
1053    /// Returns `Some(1)` if the index is unique.
1054    pub fn count(&self, value: &AlgebraicValue) -> Option<usize> {
1055        match self.seek_point(value).count() {
1056            0 => None,
1057            n => Some(n),
1058        }
1059    }
1060
1061    /// Returns an iterator that yields all the `RowPointer`s for the given `key`.
1062    pub fn seek_point(&self, key: &AlgebraicValue) -> TableIndexPointIter<'_> {
1063        TableIndexPointIter {
1064            iter: self.idx.seek_point(key),
1065        }
1066    }
1067
1068    /// Returns an iterator over the [TableIndex] that yields all the `RowPointer`s
1069    /// that fall within the specified `range`.
1070    pub fn seek_range(&self, range: &impl RangeBounds<AlgebraicValue>) -> TableIndexRangeIter<'_> {
1071        TableIndexRangeIter {
1072            iter: self.idx.seek_range(range),
1073        }
1074    }
1075
1076    /// Extends [`TableIndex`] with `rows`.s
1077    ///
1078    /// Returns the first unique constraint violation caused when adding this index, if any.
1079    ///
1080    /// # Safety
1081    ///
1082    /// Caller promises that projecting any of the `row_ref`'s type
1083    /// to the index's columns equals the index's key type.
1084    /// This is entailed by an index belonging to the table's schema.
1085    /// It also follows from `row_ref`'s type/layout
1086    /// being the same as passed in on `self`'s construction.
1087    pub unsafe fn build_from_rows<'table>(
1088        &mut self,
1089        rows: impl IntoIterator<Item = RowRef<'table>>,
1090    ) -> Result<(), RowPointer> {
1091        rows.into_iter()
1092            // SAFETY: Forward caller proof obligation.
1093            .try_for_each(|row_ref| unsafe { self.check_and_insert(row_ref) })
1094    }
1095
1096    /// Deletes all entries from the index, leaving it empty.
1097    ///
1098    /// When inserting a newly-created index into the committed state,
1099    /// we clear the tx state's index and insert it,
1100    /// rather than constructing a new `TableIndex`.
1101    pub fn clear(&mut self) {
1102        self.idx.clear();
1103        self.num_key_bytes = 0;
1104        self.num_rows = 0;
1105    }
1106
1107    /// The number of unique keys in this index.
1108    pub fn num_keys(&self) -> usize {
1109        self.idx.num_keys()
1110    }
1111
1112    /// The number of rows stored in this index.
1113    ///
1114    /// Note that, for non-unique indexes, this may be larger than [`Self::num_keys`].
1115    ///
1116    /// This method runs in constant time.
1117    pub fn num_rows(&self) -> u64 {
1118        self.num_rows
1119    }
1120
1121    /// The number of bytes stored in keys in this index.
1122    ///
1123    /// For non-unique indexes, duplicate keys are counted once for each row that refers to them,
1124    /// even though the internal storage may deduplicate them as an optimization.
1125    ///
1126    /// This method runs in constant time.
1127    ///
1128    /// See the [`KeySize`] trait for more details on how this method computes its result.
1129    pub fn num_key_bytes(&self) -> u64 {
1130        self.num_key_bytes
1131    }
1132}
1133
1134#[cfg(test)]
1135mod test {
1136    use super::*;
1137    use crate::{blob_store::HashMapBlobStore, table::test::table};
1138    use core::ops::Bound::*;
1139    use proptest::prelude::*;
1140    use proptest::{collection::vec, test_runner::TestCaseResult};
1141    use spacetimedb_data_structures::map::HashMap;
1142    use spacetimedb_primitives::ColId;
1143    use spacetimedb_sats::{
1144        product,
1145        proptest::{generate_product_value, generate_row_type},
1146        AlgebraicType, ProductType, ProductValue,
1147    };
1148    use spacetimedb_schema::def::BTreeAlgorithm;
1149
1150    fn gen_cols(ty_len: usize) -> impl Strategy<Value = ColList> {
1151        vec((0..ty_len as u16).prop_map_into::<ColId>(), 1..=ty_len)
1152            .prop_map(|cols| cols.into_iter().collect::<ColList>())
1153    }
1154
1155    fn gen_row_and_cols() -> impl Strategy<Value = (ProductType, ColList, ProductValue)> {
1156        generate_row_type(1..16).prop_flat_map(|ty| {
1157            (
1158                Just(ty.clone()),
1159                gen_cols(ty.elements.len()),
1160                generate_product_value(ty),
1161            )
1162        })
1163    }
1164
1165    fn new_index(row_type: &ProductType, cols: &ColList, is_unique: bool) -> TableIndex {
1166        let algo = BTreeAlgorithm { columns: cols.clone() }.into();
1167        TableIndex::new(row_type, &algo, is_unique).unwrap()
1168    }
1169
1170    /// Extracts from `row` the relevant column values according to what columns are indexed.
1171    fn get_fields(cols: &ColList, row: &ProductValue) -> AlgebraicValue {
1172        row.project(cols).unwrap()
1173    }
1174
1175    /// Returns whether indexing `row` again would violate a unique constraint, if any.
1176    fn violates_unique_constraint(index: &TableIndex, cols: &ColList, row: &ProductValue) -> bool {
1177        !index.is_unique() || index.contains_any(&get_fields(cols, row))
1178    }
1179
1180    /// Returns an iterator over the rows that would violate the unique constraint of this index,
1181    /// if `row` were inserted,
1182    /// or `None`, if this index doesn't have a unique constraint.
1183    fn get_rows_that_violate_unique_constraint<'a>(
1184        index: &'a TableIndex,
1185        row: &'a AlgebraicValue,
1186    ) -> Option<TableIndexPointIter<'a>> {
1187        index.is_unique().then(|| index.seek_point(row))
1188    }
1189
1190    proptest! {
1191        #![proptest_config(ProptestConfig { max_shrink_iters: 0x10000000, ..Default::default() })]
1192        #[test]
1193        fn remove_nonexistent_noop(((ty, cols, pv), is_unique) in (gen_row_and_cols(), any::<bool>())) {
1194            let mut index = new_index(&ty, &cols, is_unique);
1195            let mut table = table(ty);
1196            let mut blob_store = HashMapBlobStore::default();
1197            let row_ref = table.insert(&mut blob_store, &pv).unwrap().1;
1198            prop_assert_eq!(index.delete(row_ref).unwrap(), false);
1199            prop_assert!(index.idx.is_empty());
1200        }
1201
1202        #[test]
1203        fn insert_delete_noop(((ty, cols, pv), is_unique) in (gen_row_and_cols(), any::<bool>())) {
1204            let mut index = new_index(&ty, &cols, is_unique);
1205            let mut table = table(ty);
1206            let mut blob_store = HashMapBlobStore::default();
1207            let row_ref = table.insert(&mut blob_store, &pv).unwrap().1;
1208            let value = get_fields(&cols, &pv);
1209
1210            prop_assert_eq!(index.idx.len(), 0);
1211            prop_assert_eq!(index.contains_any(&value), false);
1212
1213            prop_assert_eq!(unsafe { index.check_and_insert(row_ref) }, Ok(()));
1214            prop_assert_eq!(index.idx.len(), 1);
1215            prop_assert_eq!(index.contains_any(&value), true);
1216
1217            prop_assert_eq!(index.delete(row_ref).unwrap(), true);
1218            prop_assert_eq!(index.idx.len(), 0);
1219            prop_assert_eq!(index.contains_any(&value), false);
1220        }
1221
1222        #[test]
1223        fn insert_again_violates_unique_constraint((ty, cols, pv) in gen_row_and_cols()) {
1224            let mut index = new_index(&ty, &cols, true);
1225            let mut table = table(ty);
1226            let mut blob_store = HashMapBlobStore::default();
1227            let row_ref = table.insert(&mut blob_store, &pv).unwrap().1;
1228            let value = get_fields(&cols, &pv);
1229
1230            // Nothing in the index yet.
1231            prop_assert_eq!(index.idx.len(), 0);
1232            prop_assert_eq!(violates_unique_constraint(&index, &cols, &pv), false);
1233            prop_assert_eq!(
1234                get_rows_that_violate_unique_constraint(&index, &value).unwrap().collect::<Vec<_>>(),
1235                []
1236            );
1237
1238            // Insert.
1239            // SAFETY: `row_ref` has the same type as was passed in when constructing `index`.
1240            prop_assert_eq!(unsafe { index.check_and_insert(row_ref) }, Ok(()));
1241
1242            // Inserting again would be a problem.
1243            prop_assert_eq!(index.idx.len(), 1);
1244            prop_assert_eq!(violates_unique_constraint(&index, &cols, &pv), true);
1245            prop_assert_eq!(
1246                get_rows_that_violate_unique_constraint(&index, &value).unwrap().collect::<Vec<_>>(),
1247                [row_ref.pointer()]
1248            );
1249            // SAFETY: `row_ref` has the same type as was passed in when constructing `index`.
1250            prop_assert_eq!(unsafe { index.check_and_insert(row_ref) }, Err(row_ref.pointer()));
1251        }
1252
1253        #[test]
1254        fn seek_various_ranges(needle in 1..u64::MAX) {
1255            use AlgebraicValue::U64 as V;
1256
1257            let cols = 0.into();
1258            let ty = ProductType::from_iter([AlgebraicType::U64]);
1259            let mut index = new_index(&ty, &cols, true);
1260            let mut table = table(ty);
1261            let mut blob_store = HashMapBlobStore::default();
1262
1263            let prev = needle - 1;
1264            let next = needle + 1;
1265            let range = prev..=next;
1266
1267            let mut val_to_ptr = HashMap::default();
1268
1269            // Insert `prev`, `needle`, and `next`.
1270            for x in range.clone() {
1271                let row = product![x];
1272                let row_ref = table.insert(&mut blob_store, &row).unwrap().1;
1273                val_to_ptr.insert(x, row_ref.pointer());
1274                // SAFETY: `row_ref` has the same type as was passed in when constructing `index`.
1275                prop_assert_eq!(unsafe { index.check_and_insert(row_ref) }, Ok(()));
1276            }
1277
1278            fn test_seek(index: &TableIndex, val_to_ptr: &HashMap<u64, RowPointer>, range: impl RangeBounds<AlgebraicValue>, expect: impl IntoIterator<Item = u64>) -> TestCaseResult {
1279                let mut ptrs_in_index = index.seek_range(&range).collect::<Vec<_>>();
1280                ptrs_in_index.sort();
1281                let mut expected_ptrs = expect.into_iter().map(|expected| val_to_ptr.get(&expected).unwrap()).copied().collect::<Vec<_>>();
1282                expected_ptrs.sort();
1283                prop_assert_eq!(
1284                    ptrs_in_index,
1285                    expected_ptrs
1286                );
1287                Ok(())
1288            }
1289
1290            // Test point ranges.
1291            for x in range.clone() {
1292                test_seek(&index, &val_to_ptr, V(x), [x])?;
1293            }
1294
1295            // Test `..` (`RangeFull`).
1296            test_seek(&index, &val_to_ptr, .., [prev, needle, next])?;
1297
1298            // Test `x..` (`RangeFrom`).
1299            test_seek(&index, &val_to_ptr, V(prev).., [prev, needle, next])?;
1300            test_seek(&index, &val_to_ptr, V(needle).., [needle, next])?;
1301            test_seek(&index, &val_to_ptr, V(next).., [next])?;
1302
1303            // Test `..x` (`RangeTo`).
1304            test_seek(&index, &val_to_ptr, ..V(prev), [])?;
1305            test_seek(&index, &val_to_ptr, ..V(needle), [prev])?;
1306            test_seek(&index, &val_to_ptr, ..V(next), [prev, needle])?;
1307
1308            // Test `..=x` (`RangeToInclusive`).
1309            test_seek(&index, &val_to_ptr, ..=V(prev), [prev])?;
1310            test_seek(&index, &val_to_ptr, ..=V(needle), [prev, needle])?;
1311            test_seek(&index, &val_to_ptr, ..=V(next), [prev, needle, next])?;
1312
1313            // Test `x..y` (`Range`).
1314            test_seek(&index, &val_to_ptr, V(prev)..V(prev), [])?;
1315            test_seek(&index, &val_to_ptr, V(prev)..V(needle), [prev])?;
1316            test_seek(&index, &val_to_ptr, V(prev)..V(next), [prev, needle])?;
1317            test_seek(&index, &val_to_ptr, V(needle)..V(next), [needle])?;
1318
1319            // Test `x..=y` (`RangeInclusive`).
1320            test_seek(&index, &val_to_ptr, V(prev)..=V(prev), [prev])?;
1321            test_seek(&index, &val_to_ptr, V(prev)..=V(needle), [prev, needle])?;
1322            test_seek(&index, &val_to_ptr, V(prev)..=V(next), [prev, needle, next])?;
1323            test_seek(&index, &val_to_ptr, V(needle)..=V(next), [needle, next])?;
1324            test_seek(&index, &val_to_ptr, V(next)..=V(next), [next])?;
1325
1326            // Test `(x, y]` (Exclusive start, inclusive end).
1327            test_seek(&index, &val_to_ptr, (Excluded(V(prev)), Included(V(prev))), [])?;
1328            test_seek(&index, &val_to_ptr, (Excluded(V(prev)), Included(V(needle))), [needle])?;
1329            test_seek(&index, &val_to_ptr, (Excluded(V(prev)), Included(V(next))), [needle, next])?;
1330
1331            // Test `(x, inf]` (Exclusive start, unbounded end).
1332            test_seek(&index, &val_to_ptr, (Excluded(V(prev)), Unbounded), [needle, next])?;
1333            test_seek(&index, &val_to_ptr, (Excluded(V(needle)), Unbounded), [next])?;
1334            test_seek(&index, &val_to_ptr, (Excluded(V(next)), Unbounded), [])?;
1335
1336            // Test `(x, y)` (Exclusive start, exclusive end).
1337            test_seek(&index, &val_to_ptr, (Excluded(V(prev)), Excluded(V(needle))), [])?;
1338            test_seek(&index, &val_to_ptr, (Excluded(V(prev)), Excluded(V(next))), [needle])?;
1339        }
1340    }
1341}