bugs fixed and less recursive calls
This commit is contained in:
parent
555b2091c0
commit
149a7a7110
3 changed files with 48 additions and 75 deletions
105
src/database.rs
105
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> {
|
pub fn write<W: Write>(database: Database, mut writer: BufWriter<W>) -> Result<(), Error> {
|
||||||
let mut current_top_layer = database.leaf_pages;
|
let mut current_top_layer = database.leaf_pages;
|
||||||
let mut n_pages = current_top_layer.len();
|
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();
|
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
|
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_childrefs_write(table_root_page, &mut writer, 3)
|
||||||
set_page_references(table_root_page);
|
|
||||||
write_pages(&mut writer, table_root_page)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_pagenumbers(page: &mut Page, page_counter: u32) {
|
fn set_childrefs_write<W: Write>(page: &mut Page, writer: &mut BufWriter<W>, mut page_counter: u32) -> Result<(), Error> {
|
||||||
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) {
|
|
||||||
if let PageType::Interior = page.page_type {
|
if let PageType::Interior = page.page_type {
|
||||||
page.fw_position = page::POSITION_CELL_COUNT;
|
page.fw_position = page::POSITION_CELL_COUNT;
|
||||||
page.put_u16((page.children.len() - 1) as u16);
|
page.put_u16((page.children.len() - 1) as u16);
|
||||||
|
|
||||||
page.fw_position = page::POSITION_RIGHTMOST_POINTER_LEAFPAGES;
|
for index in 0..page.children.len() - 1 {
|
||||||
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::START_OF_INTERIOR_PAGE + (index as u16) * 2;
|
||||||
page.fw_position = page.get_u16();
|
page.fw_position = page.get_u16();
|
||||||
page.put_u32(*child_page_number);
|
page.put_u32(page_counter);
|
||||||
}
|
page_counter += 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for child in &mut page.children {
|
page.fw_position = page::POSITION_RIGHTMOST_POINTER_LEAFPAGES;
|
||||||
set_page_references(child);
|
page.put_u32(page_counter);
|
||||||
}
|
page_counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_pages<W: Write>(writer: &mut BufWriter<W>, page: &Page) -> Result<(), Error> {
|
|
||||||
writer.write_all(&page.data)?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -139,18 +101,17 @@ fn create_interior_pages(child_pages: Vec<Page>) -> Vec<Page> {
|
||||||
interior_page.fw_position = page::START_OF_INTERIOR_PAGE;
|
interior_page.fw_position = page::START_OF_INTERIOR_PAGE;
|
||||||
let children_length = child_pages.len();
|
let children_length = child_pages.len();
|
||||||
let mut last_leaf: Page = Page::new_leaf(); // have to assign :(
|
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 child_count < children_length - 1 {
|
||||||
if interior_page.bw_position <= interior_page.fw_position + 15 {
|
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.fw_position = page::START_OF_CONTENT_AREA;
|
||||||
interior_page.put_u16(interior_page.bw_position);
|
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_pages.push(mem::replace(&mut interior_page, Page::new_interior()));
|
||||||
interior_page.fw_position = page::START_OF_INTERIOR_PAGE;
|
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);
|
interior_page.add_child(leaf_page);
|
||||||
} else {
|
} else {
|
||||||
last_leaf = leaf_page;
|
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.fw_position = page::START_OF_CONTENT_AREA;
|
||||||
interior_page.put_u16(interior_page.bw_position);
|
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_page.add_child(last_leaf);
|
||||||
interior_pages.push(interior_page);
|
interior_pages.push(interior_page);
|
||||||
interior_pages
|
interior_pages
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_cell(page: &mut Page) {
|
fn create_cell(interior_page: &mut Page, child_page: &Page) {
|
||||||
let mut cell: Vec<u8> = vec![0, 0, 0, 0]; // not an expensive call right?
|
let mut cell: Vec<u8> = vec![0; 5];
|
||||||
cell.append(&mut varint::write(page.key));
|
cell.append(&mut varint::write(child_page.key));
|
||||||
page.put_bytes_bw(&cell);
|
|
||||||
page.put_u16(page.bw_position);
|
interior_page.put_bytes_bw(&cell);
|
||||||
|
interior_page.put_u16(interior_page.bw_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_header(rootpage: &mut Page, n_pages: u32) {
|
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
|
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] = [
|
const MAGIC_HEADER: [u8; 16] = [
|
||||||
0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00,
|
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;
|
pub const TABLE_INTERIOR_PAGE: u8 = 0x05;
|
||||||
const INDEX_LEAF_PAGE: u8 = 0x0a;
|
const INDEX_LEAF_PAGE: u8 = 0x0a;
|
||||||
const INDEX_INTERIOR_PAGE: u8 = 0x02;
|
const INDEX_INTERIOR_PAGE: u8 = 0x02;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ mod tests {
|
||||||
fn test_build() -> Result<(), Error> {
|
fn test_build() -> Result<(), Error> {
|
||||||
let mut builder = DatabaseBuilder::new();
|
let mut builder = DatabaseBuilder::new();
|
||||||
builder.schema("foo", "create table foo(bar varchar(10))");
|
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);
|
let mut record = Record::new(i);
|
||||||
record.add_value(values::string("helloworld"));
|
record.add_value(values::string("helloworld"));
|
||||||
builder.add_record(record);
|
builder.add_record(record);
|
||||||
|
|
|
||||||
12
src/page.rs
12
src/page.rs
|
|
@ -20,7 +20,6 @@ pub struct Page {
|
||||||
pub bw_position: u16,
|
pub bw_position: u16,
|
||||||
pub key: u64,
|
pub key: u64,
|
||||||
pub children: Vec<Page>,
|
pub children: Vec<Page>,
|
||||||
pub number: u32,
|
|
||||||
pub page_type: PageType,
|
pub page_type: PageType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +31,6 @@ impl Page {
|
||||||
bw_position: size,
|
bw_position: size,
|
||||||
key: 0,
|
key: 0,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
number: 0,
|
|
||||||
page_type,
|
page_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -44,13 +42,12 @@ impl Page {
|
||||||
bw_position: size as u16,
|
bw_position: size as u16,
|
||||||
key: 0,
|
key: 0,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
number: 0,
|
|
||||||
page_type: PageType::Other,
|
page_type: PageType::Other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_root() -> Self {
|
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 {
|
pub fn new_leaf() -> Self {
|
||||||
|
|
@ -61,7 +58,7 @@ impl Page {
|
||||||
|
|
||||||
pub fn new_interior() -> Self {
|
pub fn new_interior() -> Self {
|
||||||
let mut page = Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Interior);
|
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
|
page
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,11 +106,6 @@ impl Page {
|
||||||
self.put_bytes_bw(&u32_to_bytes(value));
|
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 {
|
pub fn get_u16(&self) -> u16 {
|
||||||
let position = self.fw_position as usize;
|
let position = self.fw_position as usize;
|
||||||
(u16::from(self.data[position]) << 8) + u16::from(self.data[position + 1])
|
(u16::from(self.data[position]) << 8) + u16::from(self.data[position + 1])
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue