From 35350a23683b25b232fdfb8fb6fcef5b5f619aaa Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sun, 18 May 2025 12:08:20 +0300 Subject: [PATCH] Add IndexKeyInfo to btree --- core/storage/btree.rs | 41 +++++++++++++++++++++++++++-------------- core/types.rs | 17 +++++++++++++++++ core/vdbe/execute.rs | 8 ++++---- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/core/storage/btree.rs b/core/storage/btree.rs index bf7844e3d..194e5cee7 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -8,7 +8,7 @@ use crate::{ }, }, translate::{collate::CollationSeq, plan::IterationDirection}, - types::IndexKeySortOrder, + types::{IndexKeyInfo, IndexKeySortOrder}, MvCursor, }; @@ -400,7 +400,7 @@ pub struct BTreeCursor { /// Reusable immutable record, used to allow better allocation strategy. reusable_immutable_record: RefCell>, empty_record: Cell, - pub index_key_sort_order: IndexKeySortOrder, + pub index_key_info: Option, /// Maintain count of the number of records in the btree. Used for the `Count` opcode count: usize, /// Stores the cursor context before rebalancing so that a seek can be done later @@ -436,7 +436,7 @@ impl BTreeCursor { }, reusable_immutable_record: RefCell::new(None), empty_record: Cell::new(true), - index_key_sort_order: IndexKeySortOrder::default(), + index_key_info: None, count: 0, context: None, valid_state: CursorValidState::Valid, @@ -459,12 +459,25 @@ impl BTreeCursor { index: &Index, collations: Vec, ) -> Self { - let index_key_sort_order = IndexKeySortOrder::from_index(index); let mut cursor = Self::new(mv_cursor, pager, root_page, collations); - cursor.index_key_sort_order = index_key_sort_order; + cursor.index_key_info = Some(IndexKeyInfo::new_from_index(index)); cursor } + pub fn key_sort_order(&self) -> IndexKeySortOrder { + match &self.index_key_info { + Some(index_key_info) => index_key_info.sort_order, + None => IndexKeySortOrder::default(), + } + } + + pub fn has_rowid(&self) -> bool { + match &self.index_key_info { + Some(index_key_info) => index_key_info.has_rowid, + None => true, // currently we don't support WITHOUT ROWID tables + } + } + /// Check if the table is empty. /// This is done by checking if the root page has no cells. fn is_empty_table(&self) -> Result> { @@ -624,7 +637,7 @@ impl BTreeCursor { let order = compare_immutable( record_slice_same_num_cols, index_key.get_values(), - self.index_key_sort_order, + self.key_sort_order(), &self.collations, ); order @@ -683,7 +696,7 @@ impl BTreeCursor { let order = compare_immutable( record_slice_same_num_cols, index_key.get_values(), - self.index_key_sort_order, + self.key_sort_order(), &self.collations, ); order @@ -1264,7 +1277,7 @@ impl BTreeCursor { let order = compare_immutable( record_slice_same_num_cols, index_key.get_values(), - self.index_key_sort_order, + self.key_sort_order(), &self.collations, ); order @@ -1325,7 +1338,7 @@ impl BTreeCursor { let order = compare_immutable( record_slice_same_num_cols, index_key.get_values(), - self.index_key_sort_order, + self.key_sort_order(), &self.collations, ); order @@ -1606,7 +1619,7 @@ impl BTreeCursor { let interior_cell_vs_index_key = compare_immutable( record_slice_equal_number_of_cols, index_key.get_values(), - self.index_key_sort_order, + self.key_sort_order(), &self.collations, ); // in sqlite btrees left child pages have <= keys. @@ -1931,7 +1944,7 @@ impl BTreeCursor { let cmp = compare_immutable( record_slice_equal_number_of_cols, key.get_values(), - self.index_key_sort_order, + self.key_sort_order(), &self.collations, ); let found = match seek_op { @@ -2099,8 +2112,8 @@ impl BTreeCursor { .as_ref() .unwrap() .get_values(), - self.index_key_sort_order, - &self.collations, + self.key_sort_order(), + &self.collations, ) == Ordering::Equal { tracing::debug!("insert_into_page: found exact match with cell_idx={cell_idx}, overwriting"); @@ -3746,7 +3759,7 @@ impl BTreeCursor { let order = compare_immutable( key.to_index_key_values(), self.get_immutable_record().as_ref().unwrap().get_values(), - self.index_key_sort_order, + self.key_sort_order(), &self.collations, ); match order { diff --git a/core/types.rs b/core/types.rs index 5021a09cb..606305e30 100644 --- a/core/types.rs +++ b/core/types.rs @@ -1100,6 +1100,23 @@ impl Default for IndexKeySortOrder { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct IndexKeyInfo { + pub sort_order: IndexKeySortOrder, + pub has_rowid: bool, + pub num_cols: usize, +} + +impl IndexKeyInfo { + pub fn new_from_index(index: &Index) -> Self { + Self { + sort_order: IndexKeySortOrder::from_index(index), + has_rowid: index.has_rowid, + num_cols: index.columns.len() + (index.has_rowid as usize), + } + } +} + pub fn compare_immutable( l: &[RefValue], r: &[RefValue], diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 22f0b997d..54ed53148 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -2182,7 +2182,7 @@ pub fn op_idx_ge( let ord = compare_immutable( &idx_values, &record_values, - cursor.index_key_sort_order, + cursor.key_sort_order(), cursor.collations(), ); if ord.is_ge() { @@ -2246,7 +2246,7 @@ pub fn op_idx_le( let ord = compare_immutable( &idx_values, &record_values, - cursor.index_key_sort_order, + cursor.key_sort_order(), cursor.collations(), ); if ord.is_le() { @@ -2292,7 +2292,7 @@ pub fn op_idx_gt( let ord = compare_immutable( &idx_values, &record_values, - cursor.index_key_sort_order, + cursor.key_sort_order(), cursor.collations(), ); if ord.is_gt() { @@ -2338,7 +2338,7 @@ pub fn op_idx_lt( let ord = compare_immutable( &idx_values, &record_values, - cursor.index_key_sort_order, + cursor.key_sort_order(), cursor.collations(), ); if ord.is_lt() {