1
0
mirror of https://github.com/fumiama/fumidb.git synced 2026-06-05 00:32:44 +08:00

add some funcs of table

This commit is contained in:
源文雨
2022-05-03 21:14:30 +08:00
parent 19e09bc630
commit d17f36b255
7 changed files with 174 additions and 16 deletions

View File

@@ -8,16 +8,16 @@
│ table name length │ name of the table ( variable length ) │
├─────────────────────┼──────────┬──────────┬──────────┬──────────┬──────────┬──────────┤
│ │ type of │ type of │ type of │ type of │ type of │ type of │
│ table column length │ column │ column │ column │ column │ column │ column
table row length row │ row │ row │ row │ row │ row
│ │ No.1 │ No.2 │ No.3 │ No.4 │ No... │ No.N │
├─────────────────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┤
│ index pointer of pk ( this pointer will never be zero ) │
├───────────────────────────────────────────────────────────────────────────────────────┤
│ index pointer of column No.2 ( if it's zero, there is no index for this column )
index pointer of row No.2 ( if it's zero, there is no index for this row )
├───────────────────────────────────────────────────────────────────────────────────────┤
│ index pointer of column No... ( if it's zero, there is no index for this column )
index pointer of row No... ( if it's zero, there is no index for this row )
├───────────────────────────────────────────────────────────────────────────────────────┤
│ index pointer of column No.N ( if it's zero, there is no index for this column )
index pointer of row No.N ( if it's zero, there is no index for this row )
├───────────────────────────────────────────────────────────────────────────────────────┤
│ index pointer of first foreign key ( if available ) │
├───────────────────────────────────────────────────────────────────────────────────────┤
@@ -31,7 +31,7 @@
> 区块长度固定,但是不同索引类型有所不同
详见[索引格式](/api/index.md)。
### 表项
> 区块长度固定,为`8+len(column1)+len(column2)+...+len(columnN)`字节
> 区块长度固定,为`8+len(row 1)+len(row 2)+...+len(row N)`字节
为方便遍历数据表项以uint64的指针开头代表下一项的地址。接下来按照[数据类型](/api/types.md)中规定的存储格式依次附加第一项、第二项直到第N项的值。
#### 表项的增加
优先附加到上一个表项末尾。如无法实现,则从空区块选取一个,或附加到整个文件末尾。

View File

@@ -25,6 +25,8 @@ int set_first_unused_block(int fd, uint64_t ptr);
// 获得 ptr of unused blk 字段
uint64_t get_first_unused_block(int fd);
uint64_t get_next_unused_block(int fd, uint64_t ptr);
// 设置 ptr of next table 字段
// 返回:
// 0 成功
@@ -35,4 +37,6 @@ int set_first_table(int fd, uint64_t ptr);
// 获得 ptr of next table 字段
uint64_t get_first_table(int fd);
uint64_t get_next_table(int fd, uint64_t ptr);
#endif

View File

@@ -7,16 +7,18 @@
// 创建表,可变参数为本表的一行的 types详见 types.h
// 如果 types 为外键,需要紧跟一个 uint64_t ptr
// 指示外键链接到的表位置
// len(buf) >= 4096+8+2=4106
// 返回:
// NULL 失败,详见 errno
// table 指向表头的指针
void* create_table(int fd, const char* name, ...);
void* create_table(int fd, char* buf, const char* name, uint16_t row_len, ...);
// 加载 ptr 位置的表
// len(buf) >= 4096+8+2=4106
// 返回:
// NULL 失败,详见 errno
// table 指向表头的指针
void* load_table(int fd, uint64_t ptr);
void* load_table(int fd, char* buf, uint64_t ptr);
// 获得表名长度包含结尾0
uint16_t get_table_name_length(void* table);
@@ -45,7 +47,7 @@ int remove_table_index(int fd, void* table, uint16_t pos);
// 返回:
// 0 失败,详见 errno
// ptr 本行插入的位置
uint64_t insert_row(int fd, void* table, ...);
uint64_t insert_row(int fd, void* table, uint16_t row_len, ...);
// 根据主键的匹配值查找行
// 如果主键不为 stringk 直接装填其值
@@ -63,7 +65,7 @@ uint64_t find_row_by_pk(int fd, void* table, key_t k);
// 返回:
// 非 0 失败,详见 errno
// 0 成功
int find_row_by(int fd, void* table, int (*f)(uint64_t), ...);
int find_row_by(int fd, void* table, int (*f)(uint64_t), uint16_t row_len, ...);
// 根据主键的匹配值删除行
// 如果主键不为 stringk 直接装填其值
@@ -80,6 +82,6 @@ int remove_row_by_pk(int fd, void* table, key_t k);
// 返回:
// 非 0 失败,详见 errno
// 0 成功
int remove_row_by(int fd, void* table, ...);
int remove_row_by(int fd, void* table, uint16_t row_len, ...);
#endif

View File

@@ -21,6 +21,9 @@
typedef uint8_t type_t;
typedef uint64_t key_t;
// 获得本类型 index 相对于 buffer 头的偏移
int type_offset(type_t t);
// 为类型 type 创建索引
// 返回:索引头节点的指针 index
void* create_index(int fd, type_t t, void* buf);

View File

@@ -37,6 +37,12 @@ uint64_t get_first_unused_block(int fd) {
return ptr;
}
uint64_t get_next_unused_block(int fd, uint64_t ptr) {
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
readle64(fd, ptr);
return ptr;
}
int set_first_table(int fd, uint64_t ptr) {
uint8_t buf[8];
if(lseek(fd, 16, SEEK_SET) < 0) return EOF;
@@ -50,3 +56,9 @@ uint64_t get_first_table(int fd) {
readle64(fd, ptr);
return ptr;
}
uint64_t get_next_table(int fd, uint64_t ptr) {
if(lseek(fd, ptr, SEEK_SET) < 0) return EOF;
readle64(fd, ptr);
return ptr;
}

View File

@@ -1,23 +1,142 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "../include/binary.h"
#include "../include/file.h"
#include "../include/page.h"
#include "../include/table.h"
#include "../include/types.h"
#include "../include/types/int8.h"
#include "../include/types/int16.h"
// 计算索引需要的内存
static int _calc_index_size(type_t t) {
switch(t&7) {
case TYPE_INT8:
return INT8_INDEX_SZ+10;
case TYPE_INT16:
return INT16_INDEX_SZ+10 + INT16_BITMAP_SZ+8*2;
case TYPE_INT32:
case TYPE_FLOAT:
case TYPE_INT64:
case TYPE_DOUBLE:
case TYPE_STRING:
return PAGESZ+8;
case TYPE_BINARY: // 不能创建索引
default:
return EOF;
}
}
// 为 t 类型创建索引,写入 index_ptr
// 返回:
// 1 失败,详见 errno
// 0 成功
static void* _add_index_type(int fd, uint64_t* index_ptr, type_t t) {
int sz = _calc_index_size(t);
if(sz <= 0) {
errno = EINVAL;
return EINVAL;
}
void* buf = malloc(sz);
if(buf == NULL) return 1;
void* index = create_index(fd, t, buf);
*index_ptr = le64(buf);
free(buf);
return 0;
}
// 创建表,可变参数为本表的一行的 types详见 types.h
// 如果 types 为外键,需要紧跟一个 uint64_t ptr
// 指示外键链接到的表位置
// len(buf) >= 4096+8+2=4106
// 返回:
// NULL 失败,详见 errno
// table 指向表头的指针
void* create_table(int fd, const char* name, ...) {
return NULL;
void* create_table(int fd, char* buf, const char* name, uint16_t row_len, ...) {
va_list list;
if(!row_len || row_len > 128) {
errno = EINVAL;
return NULL;
}
int len = strlen(name);
if(len <= 0 || len >= UINT16_MAX) {
errno = EINVAL;
return NULL;
}
void* table = alloc_page(fd, buf+2);
if(table == NULL) return NULL;
memset(table, 0, PAGESZ);
putle16(table+8, len);
memcpy(table+8+2, name, len);
len += 8+2;
uint64_t ptr = get_first_table(fd);
while(ptr > 0) ptr = get_next_table(fd, ptr); // 结束时fd位于最后一个表头+8
if(ptr) return NULL; // 发生错误
lseek(fd, -8, SEEK_CUR);
if(write(fd, buf+2, 8) != 8) return NULL; // 写入新表位置
putle16(table+len, row_len);
len += 2;
int foreign_cnt = 0;
va_start(list, row_len);
type_t t = va_arg(list, type_t); // 是主键,检查是否有 unique + nonnull 类型修饰符
if(!(t&EXTYPE_NONNULL) || !(t&EXTYPE_UNIQUE)) {
errno = EINVAL;
return NULL;
}
((type_t*)table)[len] = t; // 填充 type of row No.0
if(t & EXTYPE_FOREIGNKEY) { // 是外键,还有一个参数
ptr = va_arg(list, uint64_t);
putle64(table+len+(int)row_len*(8+1)+8*(foreign_cnt++), ptr);
}
// 为 pk 创建索引
if(_add_index_type(fd, table+len+(int)row_len, t)) return NULL;
for(int i = 1; i < (int)row_len; i++) {
t = va_arg(list, type_t);
((type_t*)table)[len+i] = t; // 填充 type of row No.i
if(t & EXTYPE_FOREIGNKEY) { // 是外键,还有一个参数
ptr = va_arg(list, uint64_t);
putle64(table+len+(int)row_len*(8+1)+8*(foreign_cnt++), ptr);
}
}
va_end(list);
len += (int)row_len*(8+1) + 8*foreign_cnt;
if(len > PAGESZ-2) {
errno = EFBIG;
return NULL;
}
// 写回文件
if(sync_page(fd, table)) return NULL;
// 回收剩余空间
ptr = le64(buf+2);
if(PAGESZ - len > 10) add_block(fd, PAGESZ - len, ptr+(uint64_t)len);
// 将 page 变为 block
putle64(buf, ptr);
putle16(buf+8, len);
return buf+10;
}
// 加载 ptr 位置的表
// len(buf) >= 4096+8+2=4106
// 返回:
// NULL 失败,详见 errno
// table 指向表头的指针
void* load_table(int fd, uint64_t ptr) {
void* load_table(int fd, char* buf, uint64_t ptr) {
return NULL;
}
@@ -59,7 +178,7 @@ int remove_table_index(int fd, void* table, uint16_t pos) {
// 返回:
// 0 失败,详见 errno
// ptr 本行插入的位置
uint64_t insert_row(int fd, void* table, ...) {
uint64_t insert_row(int fd, void* table, uint16_t row_len, ...) {
return 0;
}
@@ -81,7 +200,7 @@ uint64_t find_row_by_pk(int fd, void* table, key_t k) {
// 返回:
// 非 0 失败,详见 errno
// 0 成功
int find_row_by(int fd, void* table, int (*f)(uint64_t), ...) {
int find_row_by(int fd, void* table, int (*f)(uint64_t), uint16_t row_len, ...) {
return 1;
}
@@ -102,6 +221,6 @@ int remove_row_by_pk(int fd, void* table, key_t k) {
// 返回:
// 非 0 失败,详见 errno
// 0 成功
int remove_row_by(int fd, void* table, ...) {
int remove_row_by(int fd, void* table, uint16_t row_len, ...) {
return 1;
}

View File

@@ -1,3 +1,4 @@
#include "../include/binary.h"
#include "../include/types.h"
#include "../include/types/int8.h"
#include "../include/types/int16.h"
@@ -129,6 +130,23 @@ static _remove_by_key_t _remove_item_by_key[] = {
remove_item_by_not_impl_key
};
int type_offset(type_t t) {
switch(t&7) {
case TYPE_INT8:
case TYPE_INT16:
return -10; // block
case TYPE_INT32:
case TYPE_FLOAT:
case TYPE_INT64:
case TYPE_DOUBLE:
case TYPE_STRING:
return -8; // page
case TYPE_BINARY: // 不能创建索引
default:
return 0;
}
}
void* create_index(int fd, type_t t, void* buf) {
return _types_init[t&7](fd, buf);
}