From 9a21923dbf54c9a20ccd2b1870df8f78e7e8c34e Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Wed, 8 Nov 2017 20:58:10 -0800 Subject: [PATCH] wip --- db.c | 50 +++++++++++++++++++++++++++++++---------------- spec/main_spec.rb | 33 +++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/db.c b/db.c index d5d8ab2..83dd079 100644 --- a/db.c +++ b/db.c @@ -132,8 +132,12 @@ const uint32_t INTERNAL_NODE_CELL_SIZE = */ const uint32_t LEAF_NODE_NUM_CELLS_SIZE = sizeof(uint32_t); const uint32_t LEAF_NODE_NUM_CELLS_OFFSET = COMMON_NODE_HEADER_SIZE; -const uint32_t LEAF_NODE_HEADER_SIZE = - COMMON_NODE_HEADER_SIZE + LEAF_NODE_NUM_CELLS_SIZE; +const uint32_t LEAF_NODE_NEXT_LEAF_SIZE = sizeof(uint32_t); +const uint32_t LEAF_NODE_NEXT_LEAF_OFFSET = + LEAF_NODE_NUM_CELLS_OFFSET + LEAF_NODE_NUM_CELLS_SIZE; +const uint32_t LEAF_NODE_HEADER_SIZE = COMMON_NODE_HEADER_SIZE + + LEAF_NODE_NUM_CELLS_SIZE + + LEAF_NODE_NEXT_LEAF_SIZE; /* * Leaf Node Body Layout @@ -203,6 +207,10 @@ uint32_t* leaf_node_num_cells(void* node) { return node + LEAF_NODE_NUM_CELLS_OFFSET; } +uint32_t* leaf_node_next_leaf(void* node) { + return node + LEAF_NODE_NEXT_LEAF_OFFSET; +} + void* leaf_node_cell(void* node, uint32_t cell_num) { return node + LEAF_NODE_HEADER_SIZE + cell_num * LEAF_NODE_CELL_SIZE; } @@ -322,6 +330,7 @@ void initialize_leaf_node(void* node) { set_node_type(node, NODE_LEAF); set_node_root(node, false); *leaf_node_num_cells(node) = 0; + *leaf_node_next_leaf(node) = 0; // 0 represents no sibling } void initialize_internal_node(void* node) { @@ -330,19 +339,6 @@ void initialize_internal_node(void* node) { *internal_node_num_keys(node) = 0; } -Cursor* table_start(Table* table) { - Cursor* cursor = malloc(sizeof(Cursor)); - cursor->table = table; - cursor->page_num = table->root_page_num; - cursor->cell_num = 0; - - void* root_node = get_page(table->pager, table->root_page_num); - uint32_t num_cells = *leaf_node_num_cells(root_node); - cursor->end_of_table = (num_cells == 0); - - return cursor; -} - Cursor* leaf_node_find(Table* table, uint32_t page_num, uint32_t key) { void* node = get_page(table->pager, page_num); uint32_t num_cells = *leaf_node_num_cells(node); @@ -350,6 +346,7 @@ Cursor* leaf_node_find(Table* table, uint32_t page_num, uint32_t key) { Cursor* cursor = malloc(sizeof(Cursor)); cursor->table = table; cursor->page_num = page_num; + cursor->end_of_table = false; // Binary search uint32_t min_index = 0; @@ -369,6 +366,11 @@ Cursor* leaf_node_find(Table* table, uint32_t page_num, uint32_t key) { } cursor->cell_num = min_index; + + if (cursor->cell_num == num_cells) { + cursor->end_of_table = true; + } + return cursor; } @@ -416,6 +418,8 @@ Cursor* table_find(Table* table, uint32_t key) { } } +Cursor* table_start(Table* table) { return table_find(table, 0); } + void* cursor_value(Cursor* cursor) { uint32_t page_num = cursor->page_num; void* page = get_page(cursor->table->pager, page_num); @@ -428,7 +432,15 @@ void cursor_advance(Cursor* cursor) { cursor->cell_num += 1; if (cursor->cell_num >= (*leaf_node_num_cells(node))) { - cursor->end_of_table = true; + /* Advance to next leaf node */ + uint32_t next_page_num = *leaf_node_next_leaf(node); + if (next_page_num == 0) { + /* This was rightmost leaf */ + cursor->end_of_table = true; + } else { + cursor->page_num = next_page_num; + cursor->cell_num = 0; + } } } @@ -659,6 +671,8 @@ void leaf_node_split_and_insert(Cursor* cursor, uint32_t key, Row* value) { uint32_t new_page_num = get_unused_page_num(cursor->table->pager); void* new_node = get_page(cursor->table->pager, new_page_num); initialize_leaf_node(new_node); + *leaf_node_next_leaf(new_node) = *leaf_node_next_leaf(old_node); + *leaf_node_next_leaf(old_node) = new_page_num; /* All existing keys plus new key should should be divided @@ -676,7 +690,9 @@ void leaf_node_split_and_insert(Cursor* cursor, uint32_t key, Row* value) { void* destination = leaf_node_cell(destination_node, index_within_node); if (i == cursor->cell_num) { - serialize_row(value, destination); + serialize_row(value, + leaf_node_value(destination_node, index_within_node)); + *leaf_node_key(destination_node, index_within_node) = key; } else if (i > cursor->cell_num) { memcpy(destination, leaf_node_cell(old_node, i - 1), LEAF_NODE_CELL_SIZE); } else { diff --git a/spec/main_spec.rb b/spec/main_spec.rb index e736f44..eed4dab 100644 --- a/spec/main_spec.rb +++ b/spec/main_spec.rb @@ -188,6 +188,35 @@ def run_script(commands) ]) end + it 'prints all rows in a multi-level tree' do + script = [] + (1..15).each do |i| + script << "insert #{i} user#{i} person#{i}@example.com" + end + script << "select" + script << ".exit" + result = run_script(script) + + expect(result[15...result.length]).to eq([ + "db > (1, user1, person1@example.com)", + "(2, user2, person2@example.com)", + "(3, user3, person3@example.com)", + "(4, user4, person4@example.com)", + "(5, user5, person5@example.com)", + "(6, user6, person6@example.com)", + "(7, user7, person7@example.com)", + "(8, user8, person8@example.com)", + "(9, user9, person9@example.com)", + "(10, user10, person10@example.com)", + "(11, user11, person11@example.com)", + "(12, user12, person12@example.com)", + "(13, user13, person13@example.com)", + "(14, user14, person14@example.com)", + "(15, user15, person15@example.com)", + "Executed.", "db > ", + ]) + end + it 'prints constants' do script = [ ".constants", @@ -199,9 +228,9 @@ def run_script(commands) "db > Constants:", "ROW_SIZE: 293", "COMMON_NODE_HEADER_SIZE: 6", - "LEAF_NODE_HEADER_SIZE: 10", + "LEAF_NODE_HEADER_SIZE: 14", "LEAF_NODE_CELL_SIZE: 297", - "LEAF_NODE_SPACE_FOR_CELLS: 4086", + "LEAF_NODE_SPACE_FOR_CELLS: 4082", "LEAF_NODE_MAX_CELLS: 13", "db > ", ])