diff --git a/src/database.rs b/src/database.rs index 1245717..ba0cb41 100644 --- a/src/database.rs +++ b/src/database.rs @@ -33,24 +33,6 @@ impl From for Database { } } -pub struct SchemaRecord { - pub rowid: u64, - pub table_name: String, - pub root_page: u32, - pub sql: String, -} - -impl SchemaRecord { - pub fn new(rowid: u64, table_name: &str, root_page: u32, sql: &str) -> Self { - Self { - rowid, - table_name: table_name.to_owned(), - root_page, - sql: sql.to_owned(), - } - } -} - pub fn write(database: Database, mut writer: BufWriter) -> Result<(), Error> { let mut current_top_layer = database.leaf_pages; let mut n_pages = current_top_layer.len(); @@ -63,50 +45,30 @@ pub fn write(database: Database, mut writer: BufWriter) -> Result<( let table_root_page = current_top_layer.get_mut(0).unwrap(); writer.write_all(&create_header_page((n_pages + 1) as u32, database.schema).data)?; // 1 for header page - assign_pagenumbers(table_root_page, 2); - set_page_references(table_root_page); - write_pages(&mut writer, table_root_page)?; - - Ok(()) + set_childrefs_write(table_root_page, &mut writer, 3) } -fn assign_pagenumbers(page: &mut Page, page_counter: u32) { - page.number = page_counter; - let mut counter = page_counter; - for child in &mut page.children { - counter += 1; - assign_pagenumbers(child, counter); - } -} - -fn set_page_references(page: &mut Page) { +fn set_childrefs_write(page: &mut Page, writer: &mut BufWriter, mut page_counter: u32) -> Result<(), Error> { if let PageType::Interior = page.page_type { page.fw_position = page::POSITION_CELL_COUNT; page.put_u16((page.children.len() - 1) as u16); - page.fw_position = page::POSITION_RIGHTMOST_POINTER_LEAFPAGES; - page.put_u32(page.get_page_nr_last_child()); - - let before_last = page.children.len() - 1; - let child_numbers: Vec = page.children.iter().map(|child| child.number).collect(); - - for (index, child_page_number) in child_numbers.iter().enumerate() { - if index < before_last { - page.fw_position = page::START_OF_INTERIOR_PAGE + (index as u16) * 2; - page.fw_position = page.get_u16(); - page.put_u32(*child_page_number); - } + for index in 0..page.children.len() - 1 { + page.fw_position = page::START_OF_INTERIOR_PAGE + (index as u16) * 2; + page.fw_position = page.get_u16(); + page.put_u32(page_counter); + page_counter += 1; } - } - for child in &mut page.children { - set_page_references(child); - } -} -fn write_pages(writer: &mut BufWriter, page: &Page) -> Result<(), Error> { + page.fw_position = page::POSITION_RIGHTMOST_POINTER_LEAFPAGES; + page.put_u32(page_counter); + page_counter += 1; + } + writer.write_all(&page.data)?; - for child in &page.children { - write_pages(writer, child)?; + + for child in page.children.iter_mut() { + set_childrefs_write(child, writer, page_counter)?; } Ok(()) } @@ -139,18 +101,17 @@ fn create_interior_pages(child_pages: Vec) -> Vec { interior_page.fw_position = page::START_OF_INTERIOR_PAGE; let children_length = child_pages.len(); let mut last_leaf: Page = Page::new_leaf(); // have to assign :( - for (child_count, mut leaf_page) in child_pages.into_iter().enumerate() { + for (child_count, leaf_page) in child_pages.into_iter().enumerate() { if child_count < children_length - 1 { if interior_page.bw_position <= interior_page.fw_position + 15 { - // 15 is somewhat arbitrary + // 15 is somewhat arbitrary, but safe interior_page.fw_position = page::START_OF_CONTENT_AREA; interior_page.put_u16(interior_page.bw_position); - interior_page.put_bytes(&[0, 0, 0, 0, 0]); - + interior_page.fw_position += 5; interior_pages.push(mem::replace(&mut interior_page, Page::new_interior())); interior_page.fw_position = page::START_OF_INTERIOR_PAGE; } - create_cell(&mut leaf_page); + create_cell(&mut interior_page, &leaf_page); interior_page.add_child(leaf_page); } else { last_leaf = leaf_page; @@ -159,17 +120,18 @@ fn create_interior_pages(child_pages: Vec) -> Vec { interior_page.fw_position = page::START_OF_CONTENT_AREA; interior_page.put_u16(interior_page.bw_position); - interior_page.put_bytes(&[0, 0, 0, 0, 0]); + interior_page.fw_position += 5; interior_page.add_child(last_leaf); interior_pages.push(interior_page); interior_pages } -fn create_cell(page: &mut Page) { - let mut cell: Vec = vec![0, 0, 0, 0]; // not an expensive call right? - cell.append(&mut varint::write(page.key)); - page.put_bytes_bw(&cell); - page.put_u16(page.bw_position); +fn create_cell(interior_page: &mut Page, child_page: &Page) { + let mut cell: Vec = vec![0; 5]; + cell.append(&mut varint::write(child_page.key)); + + interior_page.put_bytes_bw(&cell); + interior_page.put_u16(interior_page.bw_position); } fn write_header(rootpage: &mut Page, n_pages: u32) { @@ -201,6 +163,24 @@ fn write_header(rootpage: &mut Page, n_pages: u32) { rootpage.put_u16(1); // the number of cells on this page } +pub struct SchemaRecord { + pub rowid: u64, + pub table_name: String, + pub root_page: u32, + pub sql: String, +} + +impl SchemaRecord { + pub fn new(rowid: u64, table_name: &str, root_page: u32, sql: &str) -> Self { + Self { + rowid, + table_name: table_name.to_owned(), + root_page, + sql: sql.to_owned(), + } + } +} + const MAGIC_HEADER: [u8; 16] = [ 0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00, ]; @@ -233,3 +213,4 @@ pub const TABLE_LEAF_PAGE: u8 = 0x0d; pub const TABLE_INTERIOR_PAGE: u8 = 0x05; const INDEX_LEAF_PAGE: u8 = 0x0a; const INDEX_INTERIOR_PAGE: u8 = 0x02; + diff --git a/src/lib.rs b/src/lib.rs index f6bfc2a..c6ba83b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ mod tests { fn test_build() -> Result<(), Error> { let mut builder = DatabaseBuilder::new(); builder.schema("foo", "create table foo(bar varchar(10))"); - for i in 0..100 { + for i in 0..10000 { let mut record = Record::new(i); record.add_value(values::string("helloworld")); builder.add_record(record); diff --git a/src/page.rs b/src/page.rs index 4bccb26..585b15f 100644 --- a/src/page.rs +++ b/src/page.rs @@ -20,7 +20,6 @@ pub struct Page { pub bw_position: u16, pub key: u64, pub children: Vec, - pub number: u32, pub page_type: PageType, } @@ -32,7 +31,6 @@ impl Page { bw_position: size, key: 0, children: Vec::new(), - number: 0, page_type, } } @@ -44,13 +42,12 @@ impl Page { bw_position: size as u16, key: 0, children: Vec::new(), - number: 0, page_type: PageType::Other, } } pub fn new_root() -> Self { - Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Leaf) + Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Other) } pub fn new_leaf() -> Self { @@ -61,7 +58,7 @@ impl Page { pub fn new_interior() -> Self { let mut page = Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Interior); - page.put_u8(database::TABLE_LEAF_PAGE); + page.put_u8(database::TABLE_INTERIOR_PAGE); page } @@ -109,11 +106,6 @@ impl Page { self.put_bytes_bw(&u32_to_bytes(value)); } - // may panic - pub fn get_page_nr_last_child(&self) -> u32 { - self.children[self.children.len() - 1].number - } - pub fn get_u16(&self) -> u16 { let position = self.fw_position as usize; (u16::from(self.data[position]) << 8) + u16::from(self.data[position + 1])