diff --git a/core/mvcc/cursor.rs b/core/mvcc/cursor.rs index b9e0ce136..595d2adb5 100644 --- a/core/mvcc/cursor.rs +++ b/core/mvcc/cursor.rs @@ -16,8 +16,8 @@ use std::sync::Arc; enum CursorPosition { /// We haven't loaded any row yet. BeforeFirst, - /// We have loaded a row. - Loaded(RowID), + /// We have loaded a row. This position points to a rowid in either MVCC index or in BTree. + Loaded { row_id: RowID, in_btree: bool }, /// We have reached the end of the table. End, } @@ -29,7 +29,7 @@ pub struct MvccLazyCursor { tx_id: u64, /// Reusable immutable record, used to allow better allocation strategy. reusable_immutable_record: RefCell>, - _btree_cursor: Box, + btree_cursor: Box, null_flag: bool, record_cursor: RefCell, next_rowid_lock: Arc>, @@ -48,14 +48,13 @@ impl MvccLazyCursor { "BTreeCursor expected for mvcc cursor" ); let table_id = db.get_table_id_from_root_page(root_page_or_table_id); - db.maybe_initialize_table(table_id, pager)?; Ok(Self { db, tx_id, current_pos: RefCell::new(CursorPosition::BeforeFirst), table_id, reusable_immutable_record: RefCell::new(None), - _btree_cursor: btree_cursor, + btree_cursor, null_flag: false, record_cursor: RefCell::new(RecordCursor::new()), next_rowid_lock: Arc::new(RwLock::new(())), @@ -64,14 +63,20 @@ impl MvccLazyCursor { pub fn current_row(&self) -> Result> { match *self.current_pos.borrow() { - CursorPosition::Loaded(id) => self.db.read(self.tx_id, id), + CursorPosition::Loaded { + row_id, + in_btree: _, + } => self.db.read(self.tx_id, row_id), CursorPosition::BeforeFirst => { // If we are before first, we need to try and find the first row. let maybe_rowid = self.db .get_next_row_id_for_table(self.table_id, i64::MIN, self.tx_id); if let Some(id) = maybe_rowid { - self.current_pos.replace(CursorPosition::Loaded(id)); + self.current_pos.replace(CursorPosition::Loaded { + row_id: id, + in_btree: false, + }); self.db.read(self.tx_id, id) } else { Ok(None) @@ -91,7 +96,10 @@ impl MvccLazyCursor { let _lock = lock.write(); let _ = self.last(); match *self.current_pos.borrow() { - CursorPosition::Loaded(id) => id.row_id + 1, + CursorPosition::Loaded { + row_id, + in_btree: _, + } => row_id.row_id + 1, CursorPosition::BeforeFirst => 1, CursorPosition::End => i64::MAX, } @@ -115,10 +123,13 @@ impl CursorTrait for MvccLazyCursor { fn last(&mut self) -> Result> { let last_rowid = self.db.get_last_rowid(self.table_id); if let Some(last_rowid) = last_rowid { - self.current_pos.replace(CursorPosition::Loaded(RowID { - table_id: self.table_id, - row_id: last_rowid, - })); + self.current_pos.replace(CursorPosition::Loaded { + row_id: RowID { + table_id: self.table_id, + row_id: last_rowid, + }, + in_btree: false, + }); } else { self.current_pos.replace(CursorPosition::BeforeFirst); } @@ -130,7 +141,10 @@ impl CursorTrait for MvccLazyCursor { fn next(&mut self) -> Result> { let before_first = matches!(self.get_current_pos(), CursorPosition::BeforeFirst); let min_id = match *self.current_pos.borrow() { - CursorPosition::Loaded(id) => id.row_id + 1, + CursorPosition::Loaded { + row_id, + in_btree: _, + } => row_id.row_id + 1, // TODO: do we need to forward twice? CursorPosition::BeforeFirst => i64::MIN, // we need to find first row, so we look from the first id, CursorPosition::End => { @@ -139,12 +153,15 @@ impl CursorTrait for MvccLazyCursor { } }; - let new_position = + let new_position_in_mvcc = match self .db .get_next_row_id_for_table(self.table_id, min_id, self.tx_id) { - Some(id) => CursorPosition::Loaded(id), + Some(id) => CursorPosition::Loaded { + row_id: id, + in_btree: false, + }, None => { if before_first { // if it wasn't loaded and we didn't find anything, it means the table is empty. @@ -155,12 +172,13 @@ impl CursorTrait for MvccLazyCursor { } } }; - self.current_pos.replace(new_position); + // let new_position_in_btree = self.btree_cursor.next(); + self.current_pos.replace(new_position_in_mvcc); self.invalidate_record(); Ok(IOResult::Done(matches!( self.get_current_pos(), - CursorPosition::Loaded(_) + CursorPosition::Loaded { .. } ))) } @@ -170,14 +188,20 @@ impl CursorTrait for MvccLazyCursor { fn rowid(&self) -> Result>> { let rowid = match self.get_current_pos() { - CursorPosition::Loaded(id) => Some(id.row_id), + CursorPosition::Loaded { + row_id, + in_btree: _, + } => Some(row_id.row_id), CursorPosition::BeforeFirst => { // If we are before first, we need to try and find the first row. let maybe_rowid = self.db .get_next_row_id_for_table(self.table_id, i64::MIN, self.tx_id); if let Some(id) = maybe_rowid { - self.current_pos.replace(CursorPosition::Loaded(id)); + self.current_pos.replace(CursorPosition::Loaded { + row_id: id, + in_btree: false, + }); Some(id.row_id) } else { self.current_pos.replace(CursorPosition::BeforeFirst); @@ -232,7 +256,10 @@ impl CursorTrait for MvccLazyCursor { self.invalidate_record(); let rowid = self.db.seek_rowid(bound, lower_bound, self.tx_id); if let Some(rowid) = rowid { - self.current_pos.replace(CursorPosition::Loaded(rowid)); + self.current_pos.replace(CursorPosition::Loaded { + row_id: rowid, + in_btree: false, + }); if op.eq_only() { if rowid.row_id == row_id { Ok(IOResult::Done(SeekResult::Found)) @@ -267,7 +294,10 @@ impl CursorTrait for MvccLazyCursor { }; let row = crate::mvcc::database::Row::new(row_id, record_buf, num_columns); - self.current_pos.replace(CursorPosition::Loaded(row.id)); + self.current_pos.replace(CursorPosition::Loaded { + row_id: row.id, + in_btree: false, + }); if self.db.read(self.tx_id, row.id)?.is_some() { self.db.update(self.tx_id, row).inspect_err(|_| { self.current_pos.replace(CursorPosition::BeforeFirst); @@ -320,10 +350,13 @@ impl CursorTrait for MvccLazyCursor { false }; if exists { - self.current_pos.replace(CursorPosition::Loaded(RowID { - table_id: self.table_id, - row_id: *int_key, - })); + self.current_pos.replace(CursorPosition::Loaded { + row_id: RowID { + table_id: self.table_id, + row_id: *int_key, + }, + in_btree: false, + }); } Ok(IOResult::Done(exists)) } @@ -345,7 +378,7 @@ impl CursorTrait for MvccLazyCursor { // If we reached the end of the table, it means we traversed the whole table therefore there must be something in the table. // If we have loaded a row, it means there is something in the table. match self.get_current_pos() { - CursorPosition::Loaded(_) => false, + CursorPosition::Loaded { .. } => false, CursorPosition::BeforeFirst => true, CursorPosition::End => true, } @@ -392,7 +425,10 @@ impl CursorTrait for MvccLazyCursor { let rowid = self.db.seek_rowid(bound, lower_bound, self.tx_id); if let Some(rowid) = rowid { - self.current_pos.replace(CursorPosition::Loaded(rowid)); + self.current_pos.replace(CursorPosition::Loaded { + row_id: rowid, + in_btree: false, + }); } else { self.current_pos.replace(CursorPosition::End); }