在完成 drop_table 功能之后,看官方给出的 check 信息里面并没有通过 drop 的测试,爬了半天钉钉群,发现应该是没有做元数据校验导致的
元数据校验主要是查询语句中是否存在不存在的列名、表名等,需要返回失败。需要检查代码,判断是否需要返回错误的地方都返回错误了。
现在没有元数据校验,在 drop table 之后,虽然 show tables
并没有这个表的信息了,但是如果 select *
来查询这个表,会返回 No data
而正常情况下应该是要返回 FAILURE 的
找到 RC ExecuteStage::do_select(const char *db, Query *sql, SessionEvent *session_event)
,这个函数主要是解析 select 数据结构并放到 create_selection_executor
里面返回查询结果
因为现在没有什么头绪,所以我直接把 rc 返回值不是 SUCCESS 的所有 case 的 response 都设置成 FAILURE 了
然后还有会报 core dump
错误直接服务端和客户端崩溃的情况
select * from;
select *, id from t;
select id fromt;
上面几种情况都会导致 core dump 情况的发生
通过打断点加观察日志,定位到程序运行到 parse_stage 时停止,猜测应该是在解析 select 的时候因为语句错误导致的。但是对于如何改正我现在依然是一点头绪都没有。。。尝试把传给 event 的 error 信息注释掉,直接set_response("FAILURE\n");
强制全返回一个 FAILURE (和上面一样的操作2333)
至少现在看起来查询结果倒是正常的2333
看21号下午官方拉取测试情况咋样了,有问题再说吧
先把 update 做了
总体方法还是和 drop table 差不多的操作,一路改过来直到 table.cpp ,加一个 RC Table::update_record(Trx *trx, const char *attribute_name, const Value *value, ConditionFilter *filter, int *updated_count)
函数,大概思路应该就是在对应的 table 里面找到条件对应的 record ,找到attribute_name
相同的列并把值改成 value
然后再存回去。注意最后一个参数 update_count
,这个应该是保存修改的 record 的个数的
table 类中提供了 scan_record 可以让我们直接调用
scan_record(Trx *trx, ConditionFilter *filter, int limit, void *context, RC (*record_reader)(Record *record, void *context))
。。。此处省略八百字。。。
这个东西,比我想象的还要复杂。。。
首先,根据条件筛选出来的 record 可能不止一条,所以还需要在 scan 的时候扫到一条就 update 一条。那还有什么也是需要一次操作多条 record 的呢? 啊是 delete。 所以我参考了 delete 的做法(真的不明觉厉)创建了一个 RecordUpdate 类,在这里存放需要更新的表名,字段,更新值(这些是固定的所以没有必要当作函数参数每次更新都调用一遍)以及更新函数
又写了一个 adapter 函数,主要是为了适配 scan_record 的最后一个参数,并将其用于在每次 scan 到一个适配的参数的时候,调用 RecordUpdate 类的更新函数对这个 record 进行更新。
static RC record_reader_update_adapter(Record *record, void *context) {
RecordUpdater &record_updater = *(RecordUpdater *)context;
return record_updater.update_record(record);
}
然后,怎么更新 record 里面相应字段的值又成了一个问题。我又是一通找啊,终于爬到了一个 FieldMeta 类,和 TableMeta 相对应,这个类主要存放了 field 的元数据,包括列名,数据类型,偏移量(应该是表数据存放地址的偏移量吧)还有长度,通过调用 tablemeta 的 field(列名)就能找到相应的 field 了
最后一步就是如何更新字段的值了,record 的数据结构是这样的
struct Record
{
// bool valid; // false means the record hasn't been load
RID rid; // record's rid
char *data; // record's data
};
数据是以字符数组的形式来存放的,我们又知道这个 field 的 offset 和 len ,那直接修改 data 数组对应这一段的值不就完事了
一开始我是准备这么搞的
for(int i = 0; i < field->len();i++){
record->data[i + field->offset()] = value->data[i];
}
一编译我傻了,value 的 data 是一个 void* ,还不能用下标来访问。。。好家伙
还能咋办呢,再整一个字符数组分三段来 copy 吧,copy 完之后再赋给 record->data 完成覆盖(虽然很傻但是只能想到这种操作了55)
激动的心,颤抖的手,从白天坐到黑夜的努力终于收获回报了5555
一万多行日志,这苦有谁懂。。。
10/22 更新
目前做的功能测试都过了,开心
感觉目前进度也没比别人慢多少呀