mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-15 06:04:19 +01:00
core/mvcc/cursor: CursorPosition::Loaded include if points to btree
This commit is contained in:
@@ -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<Clock: LogicalClock> {
|
||||
tx_id: u64,
|
||||
/// Reusable immutable record, used to allow better allocation strategy.
|
||||
reusable_immutable_record: RefCell<Option<ImmutableRecord>>,
|
||||
_btree_cursor: Box<dyn CursorTrait>,
|
||||
btree_cursor: Box<dyn CursorTrait>,
|
||||
null_flag: bool,
|
||||
record_cursor: RefCell<RecordCursor>,
|
||||
next_rowid_lock: Arc<RwLock<()>>,
|
||||
@@ -48,14 +48,13 @@ impl<Clock: LogicalClock + 'static> MvccLazyCursor<Clock> {
|
||||
"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<Clock: LogicalClock + 'static> MvccLazyCursor<Clock> {
|
||||
|
||||
pub fn current_row(&self) -> Result<Option<Row>> {
|
||||
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<Clock: LogicalClock + 'static> MvccLazyCursor<Clock> {
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
fn last(&mut self) -> Result<IOResult<()>> {
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
fn next(&mut self) -> Result<IOResult<bool>> {
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
}
|
||||
};
|
||||
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
}
|
||||
}
|
||||
};
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
|
||||
fn rowid(&self) -> Result<IOResult<Option<i64>>> {
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
};
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
// 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<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user