initial pass at implementing NewRowId

This commit is contained in:
gandeevanr
2024-08-07 09:03:24 -07:00
parent 0cb45d4ebb
commit a9cb8157b5
7 changed files with 95 additions and 7 deletions

View File

@@ -50,6 +50,10 @@ impl Cursor for PseudoCursor {
unimplemented!();
}
fn seek_to_last(&mut self) -> Result<CursorResult<()>> {
unimplemented!();
}
fn record(&self) -> Result<Ref<Option<OwnedRecord>>> {
Ok(self.current.borrow())
}

View File

@@ -72,6 +72,18 @@ impl BTreeCursor {
}
}
fn is_empty_table(&mut self) -> Result<CursorResult<bool>> {
let page = self.pager.read_page(self.root_page)?;
let page = RefCell::borrow(&page);
if page.is_locked() {
return Ok(CursorResult::IO);
}
let page = page.contents.read().unwrap();
let page = page.as_ref().unwrap();
Ok(CursorResult::Ok(page.cell_count() == 0))
}
fn get_next_record(&mut self) -> Result<CursorResult<(Option<u64>, Option<OwnedRecord>)>> {
loop {
let mem_page = {
@@ -184,6 +196,42 @@ impl BTreeCursor {
.replace(Some(Rc::new(MemPage::new(None, self.root_page, 0))));
}
fn move_to_rightmost(&mut self) -> Result<CursorResult<()>> {
self.move_to_root();
loop {
let mem_page = self.page.borrow().as_ref().unwrap().clone();
let page_idx = mem_page.page_idx;
let page = self.pager.read_page(page_idx)?;
let page = RefCell::borrow(&page);
if page.is_locked() {
return Ok(CursorResult::IO);
}
let page = page.contents.read().unwrap();
let page = page.as_ref().unwrap();
if page.is_leaf() {
if page.cell_count() > 0 {
mem_page.cell_idx.replace(page.cell_count()-1);
}
return Ok(CursorResult::Ok(()));
}
match page.rightmost_pointer() {
Some(right_most_pointer) => {
mem_page.cell_idx.replace(page.cell_count());
let mem_page =
MemPage::new(Some(mem_page.clone()), right_most_pointer as usize, 0);
self.page.replace(Some(Rc::new(mem_page)));
continue;
},
None => {
unreachable!("interior page should have a rightmost pointer");
}
}
}
}
pub fn move_to(&mut self, key: u64) -> Result<CursorResult<()>> {
// For a table with N rows, we can find any row by row id in O(log(N)) time by starting at the root page and following the B-tree pointers.
// B-trees consist of interior pages and leaf pages. Interior pages contain pointers to other pages, while leaf pages contain the actual row data.
@@ -827,6 +875,26 @@ fn find_free_cell(page_ref: &PageContent, db_header: Ref<DatabaseHeader>, amount
}
impl Cursor for BTreeCursor {
fn seek_to_last(&mut self) -> Result<CursorResult<()>> {
self.move_to_rightmost()?;
match self.get_next_record()? {
CursorResult::Ok((rowid, next)) => {
if rowid.is_none() {
match self.is_empty_table()? {
CursorResult::Ok(is_empty) => {
assert!(is_empty)
},
CursorResult::IO => (),
}
}
self.rowid.replace(rowid);
self.record.replace(next);
Ok(CursorResult::Ok(()))
}
CursorResult::IO => Ok(CursorResult::IO),
}
}
fn is_empty(&self) -> bool {
self.record.borrow().is_none()
}

View File

@@ -148,7 +148,7 @@ pub fn translate_insert(
},
notnull_label,
);
program.emit_insn(Insn::NewRowid { reg: row_id_reg });
program.emit_insn(Insn::NewRowid { cursor: cursor_id, rowid_reg: row_id_reg, prev_largest_reg: 0 });
program.resolve_label(notnull_label, program.offset());
program.emit_insn(Insn::MustBeInt { reg: row_id_reg });

View File

@@ -370,6 +370,7 @@ pub trait Cursor {
fn wait_for_completion(&mut self) -> Result<()>;
fn rowid(&self) -> Result<Option<u64>>;
fn seek_rowid(&mut self, rowid: u64) -> Result<CursorResult<bool>>;
fn seek_to_last(&mut self) -> Result<CursorResult<()>>;
fn record(&self) -> Result<Ref<Option<OwnedRecord>>>;
fn insert(
&mut self,

View File

@@ -602,11 +602,11 @@ pub fn insn_to_str(
0,
"".to_string(),
),
Insn::NewRowid { reg } => (
Insn::NewRowid { cursor, rowid_reg, prev_largest_reg } => (
"NewRowId",
0,
*reg as i32,
0,
*cursor as i32,
*rowid_reg as i32,
*prev_largest_reg as i32,
OwnedValue::Text(Rc::new("".to_string())),
0,
"".to_string(),

View File

@@ -333,7 +333,9 @@ pub enum Insn {
},
NewRowid {
reg: usize,
cursor: CursorID, // P1
rowid_reg: usize, // P2 Destination register to store the new rowid
prev_largest_reg: usize // P3 Previous largest rowid in the table (Not used for now)
},
MustBeInt {
@@ -1412,7 +1414,16 @@ impl Program {
cursor.wait_for_completion()?;
state.pc += 1;
}
Insn::NewRowid { reg: _ } => todo!(),
Insn::NewRowid { cursor, rowid_reg, .. } => {
let cursor = cursors.get_mut(cursor).unwrap();
cursor.seek_to_last()?;
if let Some(rowid) = cursor.rowid()? {
state.registers[*rowid_reg] = OwnedValue::Integer((rowid+1) as i64);
} else {
state.registers[*rowid_reg] = OwnedValue::Integer(1);
}
state.pc += 1;
},
Insn::MustBeInt { reg } => {
match state.registers[*reg] {
OwnedValue::Integer(_) => {}

View File

@@ -79,6 +79,10 @@ impl Cursor for Sorter {
unimplemented!();
}
fn seek_to_last(&mut self) -> Result<CursorResult<()>> {
unimplemented!();
}
fn record(&self) -> Result<Ref<Option<OwnedRecord>>> {
Ok(self.current.borrow())
}