Skip to content

Commit

Permalink
Merge 'CREATE TABLE support' from Pekka Enberg
Browse files Browse the repository at this point in the history
Closes #383
  • Loading branch information
pereman2 committed Nov 18, 2024
2 parents 5efc218 + 80f6085 commit 9c4ca28
Show file tree
Hide file tree
Showing 10 changed files with 431 additions and 58 deletions.
61 changes: 12 additions & 49 deletions core/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use storage::database::FileStorage;
use storage::pager::allocate_page;
use storage::sqlite3_ondisk::{DatabaseHeader, DATABASE_HEADER_SIZE};
pub use storage::wal::WalFile;
use util::parse_schema_rows;

use translate::optimizer::optimize_plan;
use translate::planner::prepare_select_plan;
Expand Down Expand Up @@ -59,7 +60,7 @@ enum TransactionState {

pub struct Database {
pager: Rc<Pager>,
schema: Rc<Schema>,
schema: Rc<RefCell<Schema>>,
header: Rc<RefCell<DatabaseHeader>>,
transaction_state: RefCell<TransactionState>,
}
Expand Down Expand Up @@ -98,7 +99,7 @@ impl Database {
wal,
io.clone(),
)?);
let bootstrap_schema = Rc::new(Schema::new());
let bootstrap_schema = Rc::new(RefCell::new(Schema::new()));
let conn = Rc::new(Connection {
pager: pager.clone(),
schema: bootstrap_schema.clone(),
Expand All @@ -107,46 +108,8 @@ impl Database {
});
let mut schema = Schema::new();
let rows = conn.query("SELECT * FROM sqlite_schema")?;
if let Some(mut rows) = rows {
loop {
match rows.next_row()? {
RowResult::Row(row) => {
let ty = row.get::<&str>(0)?;
if ty != "table" && ty != "index" {
continue;
}
match ty {
"table" => {
let root_page: i64 = row.get::<i64>(3)?;
let sql: &str = row.get::<&str>(4)?;
let table = schema::BTreeTable::from_sql(sql, root_page as usize)?;
schema.add_table(Rc::new(table));
}
"index" => {
let root_page: i64 = row.get::<i64>(3)?;
match row.get::<&str>(4) {
Ok(sql) => {
let index =
schema::Index::from_sql(sql, root_page as usize)?;
schema.add_index(Rc::new(index));
}
_ => continue,
// TODO parse auto index structures
}
}
_ => continue,
}
}
RowResult::IO => {
// TODO: How do we ensure that the I/O we submitted to
// read the schema is actually complete?
io.run_once()?;
}
RowResult::Done => break,
}
}
}
let schema = Rc::new(schema);
parse_schema_rows(rows, &mut schema, io)?;
let schema = Rc::new(RefCell::new(schema));
let header = db_header;
Ok(Rc::new(Database {
pager,
Expand Down Expand Up @@ -208,7 +171,7 @@ pub fn maybe_init_database_file(file: &Rc<dyn File>, io: &Arc<dyn IO>) -> Result

pub struct Connection {
pager: Rc<Pager>,
schema: Rc<Schema>,
schema: Rc<RefCell<Schema>>,
header: Rc<RefCell<DatabaseHeader>>,
db: Weak<Database>, // backpointer to the database holding this connection
}
Expand All @@ -223,7 +186,7 @@ impl Connection {
match cmd {
Cmd::Stmt(stmt) => {
let program = Rc::new(translate::translate(
&self.schema,
&*self.schema.borrow(),
stmt,
self.header.clone(),
self.pager.clone(),
Expand All @@ -248,7 +211,7 @@ impl Connection {
match cmd {
Cmd::Stmt(stmt) => {
let program = Rc::new(translate::translate(
&self.schema,
&*self.schema.borrow(),
stmt,
self.header.clone(),
self.pager.clone(),
Expand All @@ -259,7 +222,7 @@ impl Connection {
}
Cmd::Explain(stmt) => {
let program = translate::translate(
&self.schema,
&*self.schema.borrow(),
stmt,
self.header.clone(),
self.pager.clone(),
Expand All @@ -271,7 +234,7 @@ impl Connection {
Cmd::ExplainQueryPlan(stmt) => {
match stmt {
ast::Stmt::Select(select) => {
let plan = prepare_select_plan(&self.schema, select)?;
let plan = prepare_select_plan(&*self.schema.borrow(), select)?;
let (plan, _) = optimize_plan(plan)?;
println!("{}", plan);
}
Expand All @@ -293,7 +256,7 @@ impl Connection {
match cmd {
Cmd::Explain(stmt) => {
let program = translate::translate(
&self.schema,
&*self.schema.borrow(),
stmt,
self.header.clone(),
self.pager.clone(),
Expand All @@ -304,7 +267,7 @@ impl Connection {
Cmd::ExplainQueryPlan(_stmt) => todo!(),
Cmd::Stmt(stmt) => {
let program = translate::translate(
&self.schema,
&*self.schema.borrow(),
stmt,
self.header.clone(),
self.pager.clone(),
Expand Down
4 changes: 4 additions & 0 deletions core/pseudo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,8 @@ impl Cursor for PseudoCursor {
let _ = key;
todo!()
}

fn btree_create(&mut self, _flags: usize) -> u32 {
unreachable!("Please don't.")
}
}
25 changes: 18 additions & 7 deletions core/storage/btree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ impl BTreeCursor {
pointer_area_pc_by_idx + 2,
);
}
page.write_u16(pointer_area_pc_by_idx, pc);
page.write_u16(pointer_area_pc_by_idx - page.offset, pc);

// update first byte of content area
page.write_u16(BTREE_HEADER_OFFSET_CELL_CONTENT, pc);
Expand Down Expand Up @@ -1128,17 +1128,13 @@ impl BTreeCursor {
if gap + 2 + amount > top {
// defragment
self.defragment_page(page_ref, RefCell::borrow(&self.database_header));
let buf = page_ref.as_ptr();
top = u16::from_be_bytes([buf[5], buf[6]]) as usize;
top = page_ref.read_u16(BTREE_HEADER_OFFSET_CELL_CONTENT) as usize;
}

let db_header = RefCell::borrow(&self.database_header);
top -= amount;

{
let buf = page_ref.as_ptr();
buf[5..7].copy_from_slice(&(top as u16).to_be_bytes());
}
page_ref.write_u16(BTREE_HEADER_OFFSET_CELL_CONTENT, top as u16);

let usable_space = (db_header.page_size - db_header.unused_space as u16) as usize;
assert!(top + amount <= usable_space);
Expand Down Expand Up @@ -1358,6 +1354,7 @@ impl BTreeCursor {
let id = page.id as u32;
let contents = page.contents.as_mut().unwrap();

// TODO: take into account offset here?
let buf = contents.as_ptr();
let as_bytes = id.to_be_bytes();
// update pointer to new overflow page
Expand Down Expand Up @@ -1679,6 +1676,20 @@ impl Cursor for BTreeCursor {
Ok(CursorResult::Ok(equals))
}
}

fn btree_create(&mut self, flags: usize) -> u32 {
let page_type = match flags {
1 => PageType::TableLeaf,
2 => PageType::IndexLeaf,
_ => unreachable!(
"wrong create table falgs, should be 1 for table and 2 for index, got {}",
flags,
),
};
let page = self.allocate_page(page_type);
let id = page.borrow().id;
id as u32
}
}

pub fn btree_init_page(page: &Rc<RefCell<Page>>, page_type: PageType, db_header: &DatabaseHeader) {
Expand Down
Loading

0 comments on commit 9c4ca28

Please sign in to comment.