diff --git a/core/mvcc/cursor.rs b/core/mvcc/cursor.rs index b6965a4c4..cc8cde437 100644 --- a/core/mvcc/cursor.rs +++ b/core/mvcc/cursor.rs @@ -130,4 +130,25 @@ impl MvccLazyCursor { pub fn rewind(&mut self) { self.current_pos = CursorPosition::BeforeFirst; } + + pub fn last(&mut self) { + let last_rowid = self.db.get_last_rowid(self.table_id); + if let Some(last_rowid) = last_rowid { + self.current_pos = CursorPosition::Loaded(RowID { + table_id: self.table_id, + row_id: last_rowid, + }); + } else { + self.current_pos = CursorPosition::BeforeFirst; + } + } + + pub fn get_next_rowid(&mut self) -> i64 { + self.last(); + match self.current_pos { + CursorPosition::Loaded(id) => id.row_id + 1, + CursorPosition::BeforeFirst => i64::MIN, + CursorPosition::End => i64::MAX, + } + } } diff --git a/core/mvcc/database/mod.rs b/core/mvcc/database/mod.rs index cccb713a5..b95ae07c6 100644 --- a/core/mvcc/database/mod.rs +++ b/core/mvcc/database/mod.rs @@ -15,6 +15,7 @@ use parking_lot::RwLock; use std::collections::HashSet; use std::fmt::Debug; use std::marker::PhantomData; +use std::ops::Bound; use std::rc::Rc; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; @@ -1222,6 +1223,18 @@ impl MvStore { } Ok(()) } + + pub fn get_last_rowid(&self, table_id: u64) -> Option { + let last_rowid = self + .rows + .upper_bound(Bound::Included(&RowID { + table_id, + row_id: i64::MAX, + })) + .map(|entry| Some(entry.key().row_id)) + .unwrap_or(None); + last_rowid + } } /// A write-write conflict happens when transaction T_current attempts to update a diff --git a/core/storage/btree.rs b/core/storage/btree.rs index 1217aff55..87f2f5dc0 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -5496,6 +5496,10 @@ impl BTreeCursor { self.pager .do_allocate_page(page_type, offset, BtreePageAllocMode::Any) } + + pub fn get_mvcc_cursor(&self) -> Rc> { + self.mv_cursor.as_ref().unwrap().clone() + } } #[derive(Debug, thiserror::Error)] diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 388ed3ea2..74917d6e7 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -15,6 +15,7 @@ use crate::util::{normalize_ident, IOExt as _}; use crate::vdbe::insn::InsertFlags; use crate::vdbe::registers_to_ref_values; use crate::vector::{vector_concat, vector_slice}; +use crate::MvCursor; use crate::{ error::{ LimboError, SQLITE_CONSTRAINT, SQLITE_CONSTRAINT_NOTNULL, SQLITE_CONSTRAINT_PRIMARYKEY, @@ -61,8 +62,7 @@ use crate::{ }; use crate::{ - info, turso_assert, BufferPool, MvCursor, OpenFlags, RefValue, Row, StepResult, - TransactionState, + info, turso_assert, BufferPool, OpenFlags, RefValue, Row, StepResult, TransactionState, }; use super::{ @@ -5481,7 +5481,13 @@ pub fn op_new_rowid( }; if let Some(mv_store) = mv_store { - let rowid = mv_store.get_next_rowid(); + let rowid = { + let mut cursor = state.get_cursor(*cursor); + let cursor = cursor.as_btree_mut(); + let mvcc_cursor = cursor.get_mvcc_cursor(); + let mut mvcc_cursor = RefCell::borrow_mut(&mvcc_cursor); + mvcc_cursor.get_next_rowid() + }; state.registers[*rowid_reg] = Register::Value(Value::Integer(rowid)); state.pc += 1; return Ok(InsnFunctionStepResult::Step);