bugs fixed and less recursive calls
This commit is contained in:
parent
555b2091c0
commit
149a7a7110
3 changed files with 48 additions and 75 deletions
109
src/database.rs
109
src/database.rs
|
|
@ -33,24 +33,6 @@ impl From<DatabaseBuilder> 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<W: Write>(database: Database, mut writer: BufWriter<W>) -> 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<W: Write>(database: Database, mut writer: BufWriter<W>) -> 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<W: Write>(page: &mut Page, writer: &mut BufWriter<W>, 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<u32> = 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<W: Write>(writer: &mut BufWriter<W>, 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<Page>) -> Vec<Page> {
|
|||
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<Page>) -> Vec<Page> {
|
|||
|
||||
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<u8> = 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<u8> = 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
12
src/page.rs
12
src/page.rs
|
|
@ -20,7 +20,6 @@ pub struct Page {
|
|||
pub bw_position: u16,
|
||||
pub key: u64,
|
||||
pub children: Vec<Page>,
|
||||
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])
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue