core: implement exists

This commit is contained in:
Pere Diaz Bou
2024-07-26 14:52:38 +02:00
parent b6468f11e7
commit 3b9f5aa511
6 changed files with 64 additions and 22 deletions

View File

@@ -232,20 +232,9 @@ impl BTreeCursor {
OwnedValue::Integer(i) => *i as u64,
_ => unreachable!("btree tables are indexed by integers!"),
};
let mut cell_idx = 0;
for cell in &page.cells {
match cell {
BTreeCell::TableLeafCell(cell) => {
if int_key <= cell._rowid {
break;
}
}
_ => todo!(),
}
cell_idx += 1;
}
let cell_idx = find_cell(page, int_key);
// if overwrite drop cell
// TODO: if overwrite drop cell
// insert cell
let mut payload: Vec<u8> = Vec::new();
@@ -571,7 +560,60 @@ impl Cursor for BTreeCursor {
self.null_flag
}
fn exists(&mut self, key: &OwnedValue) -> Result<bool> {
Ok(false)
fn exists(&mut self, key: &OwnedValue) -> Result<CursorResult<bool>> {
let int_key = match key {
OwnedValue::Integer(i) => i,
_ => unreachable!("btree tables are indexed by integers!"),
};
match self.move_to(*int_key as u64)? {
CursorResult::Ok(_) => {}
CursorResult::IO => return Ok(CursorResult::IO),
};
let mem_page = {
let mem_page = self.page.borrow();
let mem_page = mem_page.as_ref().unwrap();
mem_page.clone()
};
let page_idx = mem_page.page_idx;
let page_ref = self.pager.read_page(page_idx)?;
let page = page_ref.borrow();
if page.is_locked() {
return Ok(CursorResult::IO);
}
let page = page.contents.read().unwrap();
let page = page.as_ref().unwrap();
// find cell
let int_key = match key {
OwnedValue::Integer(i) => *i as u64,
_ => unreachable!("btree tables are indexed by integers!"),
};
let cell_idx = find_cell(page, int_key);
if cell_idx >= page.cells.len() {
Ok(CursorResult::Ok(false))
} else {
let equals = match &page.cells[cell_idx] {
BTreeCell::TableLeafCell(l) => l._rowid == int_key,
_ => unreachable!(),
};
Ok(CursorResult::Ok(equals))
}
}
}
fn find_cell(page: &BTreePage, int_key: u64) -> usize {
let mut cell_idx = 0;
for cell in &page.cells {
match cell {
BTreeCell::TableLeafCell(cell) => {
if int_key <= cell._rowid {
break;
}
}
_ => todo!(),
}
cell_idx += 1;
}
cell_idx
}

View File

@@ -64,7 +64,7 @@ impl Cursor for PseudoCursor {
// Do nothing
}
fn exists(&mut self, key: &OwnedValue) -> Result<bool> {
fn exists(&mut self, key: &OwnedValue) -> Result<CursorResult<bool>> {
let _ = key;
todo!()
}

View File

@@ -334,7 +334,6 @@ pub fn begin_write_btree_page(pager: &Pager, page: &Rc<RefCell<Page>>) -> Result
}
})
};
dbg!(buffer.borrow().len());
let c = Rc::new(Completion::Write(WriteCompletion::new(write_complete)));
page_source.write(page.id, buffer.clone(), c)?;
Ok(())

View File

@@ -371,7 +371,7 @@ pub trait Cursor {
fn rowid(&self) -> Result<Option<u64>>;
fn record(&self) -> Result<Ref<Option<OwnedRecord>>>;
fn insert(&mut self, key: &OwnedValue, record: &OwnedRecord) -> Result<CursorResult<()>>;
fn exists(&mut self, key: &OwnedValue) -> Result<bool>;
fn exists(&mut self, key: &OwnedValue) -> Result<CursorResult<bool>>;
fn set_null_flag(&mut self, flag: bool);
fn get_null_flag(&self) -> bool;
}

View File

@@ -1346,10 +1346,11 @@ impl Program {
} => {
let cursor = cursors.get_mut(cursor).unwrap();
match cursor.exists(&state.registers[*rowid_reg])? {
true => state.pc += 1,
false => state.pc = *target_pc,
CursorResult::Ok(true) => state.pc += 1,
CursorResult::Ok(false) => state.pc = *target_pc,
CursorResult::IO => return Ok(StepResult::IO),
};
} // TODO(pere): how is not exists implemented? We probably need to traverse keys my pointing cursor.
}
// this cursor may be reused for next insert
// Update: tablemoveto is used to travers on not exists, on insert depending on flags if nonseek it traverses again.
// If not there might be some optimizations obviously.

View File

@@ -95,7 +95,7 @@ impl Cursor for Sorter {
todo!();
}
fn exists(&mut self, key: &OwnedValue) -> Result<bool> {
fn exists(&mut self, key: &OwnedValue) -> Result<CursorResult<bool>> {
let _ = key;
todo!()
}