Add a Cursor trait and use it

We need an abstract cursor trait to implement a sorter, for example.
This commit is contained in:
Pekka Enberg
2024-03-28 15:01:52 +02:00
parent 1dd33bedcd
commit 9a73ded4fa
5 changed files with 72 additions and 63 deletions

View File

@@ -18,8 +18,7 @@ impl Database {
}
#[wasm_bindgen]
pub fn exec(&self, _sql: &str) {
}
pub fn exec(&self, _sql: &str) {}
}
pub struct IO {}

View File

@@ -1,6 +1,6 @@
use crate::pager::Pager;
use crate::sqlite3_ondisk::{BTreeCell, TableInteriorCell, TableLeafCell};
use crate::types::OwnedRecord;
use crate::types::{Cursor, CursorResult, OwnedRecord};
use anyhow::Result;
@@ -32,12 +32,7 @@ impl MemPage {
}
}
pub enum CursorResult<T> {
Ok(T),
IO,
}
pub struct Cursor {
pub struct BTreeCursor {
pager: Rc<Pager>,
root_page: usize,
page: RefCell<Option<Rc<MemPage>>>,
@@ -45,7 +40,7 @@ pub struct Cursor {
record: RefCell<Option<OwnedRecord>>,
}
impl Cursor {
impl BTreeCursor {
pub fn new(pager: Rc<Pager>, root_page: usize) -> Self {
Self {
pager,
@@ -56,51 +51,6 @@ impl Cursor {
}
}
pub fn is_empty(&self) -> bool {
self.page.borrow().is_none()
}
pub fn rewind(&mut self) -> Result<CursorResult<()>> {
let mem_page = MemPage::new(None, self.root_page, 0);
self.page.replace(Some(Rc::new(mem_page)));
match self.get_next_record()? {
CursorResult::Ok((rowid, next)) => {
self.rowid.replace(rowid);
self.record.replace(next);
Ok(CursorResult::Ok(()))
}
CursorResult::IO => Ok(CursorResult::IO),
}
}
pub fn next(&mut self) -> Result<CursorResult<()>> {
match self.get_next_record()? {
CursorResult::Ok((rowid, next)) => {
self.rowid.replace(rowid);
self.record.replace(next);
Ok(CursorResult::Ok(()))
}
CursorResult::IO => Ok(CursorResult::IO),
}
}
pub fn wait_for_completion(&mut self) -> Result<()> {
// TODO: Wait for pager I/O to complete
Ok(())
}
pub fn rowid(&self) -> Result<Ref<Option<u64>>> {
Ok(self.rowid.borrow())
}
pub fn record(&self) -> Result<Ref<Option<OwnedRecord>>> {
Ok(self.record.borrow())
}
pub fn has_record(&self) -> bool {
self.record.borrow().is_some()
}
fn get_next_record(&mut self) -> Result<CursorResult<(Option<u64>, Option<OwnedRecord>)>> {
loop {
let mem_page = {
@@ -155,3 +105,50 @@ impl Cursor {
}
}
}
impl Cursor for BTreeCursor {
fn is_empty(&self) -> bool {
self.page.borrow().is_none()
}
fn rewind(&mut self) -> Result<CursorResult<()>> {
let mem_page = MemPage::new(None, self.root_page, 0);
self.page.replace(Some(Rc::new(mem_page)));
match self.get_next_record()? {
CursorResult::Ok((rowid, next)) => {
self.rowid.replace(rowid);
self.record.replace(next);
Ok(CursorResult::Ok(()))
}
CursorResult::IO => Ok(CursorResult::IO),
}
}
fn next(&mut self) -> Result<CursorResult<()>> {
match self.get_next_record()? {
CursorResult::Ok((rowid, next)) => {
self.rowid.replace(rowid);
self.record.replace(next);
Ok(CursorResult::Ok(()))
}
CursorResult::IO => Ok(CursorResult::IO),
}
}
fn wait_for_completion(&mut self) -> Result<()> {
// TODO: Wait for pager I/O to complete
Ok(())
}
fn rowid(&self) -> Result<Ref<Option<u64>>> {
Ok(self.rowid.borrow())
}
fn record(&self) -> Result<Ref<Option<OwnedRecord>>> {
Ok(self.record.borrow())
}
fn has_record(&self) -> bool {
self.record.borrow().is_some()
}
}

View File

@@ -95,9 +95,7 @@ fn create_table(tbl_name: QualifiedName, body: CreateTableBody, root_page: usize
|| type_name.contains("TEXT")
{
Type::Text
} else if type_name.contains("BLOB")
|| type_name.is_empty()
{
} else if type_name.contains("BLOB") || type_name.is_empty() {
Type::Blob
} else if type_name.contains("REAL")
|| type_name.contains("FLOA")

View File

@@ -1,4 +1,4 @@
use std::rc::Rc;
use std::{cell::Ref, rc::Rc};
use anyhow::Result;
@@ -74,3 +74,18 @@ impl OwnedRecord {
Self { values }
}
}
pub enum CursorResult<T> {
Ok(T),
IO,
}
pub trait Cursor {
fn is_empty(&self) -> bool;
fn rewind(&mut self) -> Result<CursorResult<()>>;
fn next(&mut self) -> Result<CursorResult<()>>;
fn wait_for_completion(&mut self) -> Result<()>;
fn rowid(&self) -> Result<Ref<Option<u64>>>;
fn record(&self) -> Result<Ref<Option<OwnedRecord>>>;
fn has_record(&self) -> bool;
}

View File

@@ -1,6 +1,6 @@
use crate::btree::{Cursor, CursorResult};
use crate::btree::BTreeCursor;
use crate::pager::Pager;
use crate::types::{OwnedValue, Record};
use crate::types::{Cursor, CursorResult, OwnedValue, Record};
use anyhow::Result;
use std::cell::RefCell;
@@ -153,7 +153,7 @@ pub enum StepResult<'a> {
/// The program state describes the environment in which the program executes.
pub struct ProgramState {
pub pc: usize,
cursors: RefCell<BTreeMap<usize, Cursor>>,
cursors: RefCell<BTreeMap<usize, Box<dyn Cursor>>>,
registers: Vec<OwnedValue>,
}
@@ -209,7 +209,7 @@ impl Program {
cursor_id,
root_page,
} => {
let cursor = Cursor::new(pager.clone(), *root_page);
let cursor = Box::new(BTreeCursor::new(pager.clone(), *root_page));
cursors.insert(*cursor_id, cursor);
state.pc += 1;
}