简单数据库实现——Part10 - 分裂叶节点

简单数据库实现——Part10 - 分裂叶节点我们的B树现在只有一个节点,这看起来不像是一棵树。所以,我们需要一个将叶节点一分为二的函数,同时创建一个内部节点作为两个新的叶节点的父节点。我们的目标是从:转变为:这时我们不再需要叶节点已满的错误,先删去。 void leaf_node_insert(Cursor* cursor, uint32_t key, Row* value) {...
摘要由CSDN通过智能技术生成

简单数据库实现——Part10 - 分裂叶节点

我们的B树现在只有一个节点,这看起来不像是一棵树。所以,我们需要一个将叶节点一分为二的函数,同时创建一个内部节点作为两个新的叶节点的父节点。

我们的目标是从:
one-node btree
转变为:
two-level btree

这时我们不再需要叶节点已满的错误,先删去。

 void leaf_node_insert(Cursor* cursor, uint32_t key, Row* value) {
   
   void* node = get_page(cursor->table->pager, cursor->page_num);
 
   uint32_t num_cells = *leaf_node_num_cells(node);
   if (num_cells >= LEAF_NODE_MAX_CELLS) {
   
     // Node full
-    printf("Need to implement splitting a leaf node.\n");
-    exit(EXIT_FAILURE);
+    leaf_node_split_and_insert(cursor, key, value);
+    return;
   }
ExecuteResult execute_insert(Statement* statement, Table* table) {
   
   void* node = get_page(table->pager, table->root_page_num);
   uint32_t num_cells = (*leaf_node_num_cells(node));
-  if (num_cells >= LEAF_NODE_MAX_CELLS) {
   
-    return EXECUTE_TABLE_FULL;
-  }
 
   Row* row_to_insert = &(statement->row_to_insert);
   uint32_t key_to_insert = row_to_insert->id;

分裂程序

首先获取旧节点并创建新节点。

+void leaf_node_split_and_insert(Cursor* cursor, uint32_t key, Row* value) {
   
+  /*
+  Create a new node and move half the cells over.
+  Insert the new value in one of the two nodes.
+  Update parent or create a new parent.
+  */
+
+  void* old_node = get_page(cursor->table->pager, cursor->page_num);
+  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);

然后将所有的键值对复制到新节点中。

+  /*
+  All existing keys plus new key should be divided
+  evenly between old (left) and new (right) nodes.
+  Starting from the right, move each key to correct position.
+  */
+  for (int32_t i = LEAF_NODE_MAX_CELLS; i >= 0; i--) {
   
+    void* destination_node;
+    if (i >= LEAF_NODE_LEFT_SPLIT_COUNT) {
   
+      destination_node = new_node;
+    } else {
   
+      destination_node = old_node;
+    }
+    uint32_t index_within_node = i % LEAF_NODE_LEFT_SPLIT_COUNT;
+    void* destination = leaf_node_cell(destination_node, index_within_node);
+
+    if (i == cursor->cell_num) {
   
+      serialize_row(value, destination);
+    } else if (i > cursor->cell_num) {
   
+      memcpy(destination, leaf_node_cell(old_node, i - 1), LEAF_NODE_CELL_SIZE);
+    } else {
   
+      memcpy(destination, leaf_node_cell(old_node, i), LEAF_NODE_CELL_SIZE);
+    }
+  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值