OceanBase2021数据库比赛开发日记part3

目录

在完成 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

Image

Image

看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

Image

一万多行日志,这苦有谁懂。。。

Image

10/22 更新

Image

目前做的功能测试都过了,开心

感觉目前进度也没比别人慢多少呀

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦