20230220rewrite_sqlite

Feb 20, 2023

重写sqlite遇到的问题

记录注意点

stat返回问题

#include <sys/stat.h>

stat(filename, &st) 当成功时 = 0, 否则 = -1

fopen模式为a+时的问题

fopen模式为a+时,fseek失效,其会继续从后面补充。

解决方法: stat判断文件是否存在,不存在使用 w+; 存在使用 r+;

fwrite

每次要写入时,都需要重置位置坐标: fseek到指定位置后写入。

fgets/fread

在方法 get_page 时,误将fread 写成fgets。

fread 为将内容读取到指针内存中;fgets 为将内容通过文本文件读取到指针内存中。

当内容出现uint32_t = 10,也就是0A,fgets 识别为\n,并且接下来的内存都置为\0

根据断点查看对比hex16进制内容时 po *(uint32_t*)((char*)node+6) 内容都是对应得上的,并且文本文件也是能看到数据是存在的。但是一读取到0A数据时,就发现之后的内存都为\0了。所以直接断定为读取方式为文本方式读取。\
fopen使用rb+/wb+ 仍然没有作用,写入fwrite没有错误,那么就是写入发生了错误!

插入算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const uint32_t LEAF_NODE_RIGHT_SPLIT_COUNT = (LEAF_NODE_MAX_COUNT+1) / 2;
const uint32_t LEAF_NODE_LEFT_SPLIT_COUNT = (LEAF_NODE_MAX_COUNT+1) - LEAF_NODE_RIGHT_SPLIT_COUNT;

void leaf_node_split_and_insert(Cursor* cursor, uint32_t key, Row* value) {
...
for (int32_t i = LEAF_NODE_MAX_COUNT; 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 = i % LEAF_NODE_LEFT_SPLIT_COUNT;
void* destination = leaf_node_cell(destination_node, index);
if (i == cursor->row_num) {
serializedData(leaf_node_value(destination_node), index);
*leaf_node_key(destination_node, index) = key;
} else if (i > cursor->row_num) {
memcpy(destination, leaf_node_cell(old_node, i-1), PAGE_SIZE);
} else {
memcpy(destination, leaf_node_cell(old_node, i), PAGE_SIZE);
}
}
...
}