题目
https://github.com/OceanBase-Partner/lectures-on-dbms-implementation/blob/main/miniob-topics.md
少记录
breakpoint set --file condition_filter.cpp --line 388
breakpoint set --file condition_filter.cpp --line 270
breakpoint set --file bplus_tree.cpp --line 2467
查询索引
IndexScanner *Table::find_index_for_scan
IndexScanner *BplusTreeIndex::create_scanner
BplusTreeScanner::open
find_first_index_satisfied
breakpoint set --file bplus_tree.cpp --line 190
}
Table::scan_record
scan_record_by_index
next_entry
get_next_idx_in_memory
filter->filter
bool BplusTreeScanner::satisfy_condition
breakpoint set --file bplus_tree.cpp --line 2283
breakpoint set --file tuple.cpp --line 531
breakpoint set --file tuple.cpp --line 602
breakpoint set --file bplus_tree.cpp --line 2274
breakpoint set --file bplus_tree.cpp --line 2309
breakpoint set --file bplus_tree.cpp --line 190
breakpoint set --file tuple.cpp --line 531
breakpoint set --file condition_filter.cpp --line 105
breakpoint set --file execute_stage.cpp --line 811
breakpoint set --file execute_stage.cpp --line 722
case SCF_INSERT:
breakpoint set --file default_storage_stage.cpp --line 180
breakpoint set --file execute_stage.cpp --line 340
breakpoint set --file tuple.cpp --line 586
breakpoint set --file condition_filter.cpp --line 143
breakpoint set --file condition_filter.cpp --line 105
breakpoint set --file execute_stage.cpp --line 811
breakpoint set --file execute_stage.cpp --line 722
IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
breakpoint set --file bplus_tree.cpp --line 190
breakpoint set --file table.cpp --line 1006
bool BplusTreeScanner::satisfy_condition(const char *pkey)
breakpoint set --file bplus_tree.cpp --line 2270
breakpoint set --file bplus_tree.cpp --line 1991
问:多表查询,case:select t12.num,t13.num,t12.birthday from t12,t13 where t12.num=t13.num; 显示时候 select t12.num,t13.num,t12.birthday 你们思路怎么处理的,默认代码 按照表过滤字段显示的?
f7327f5bb81fada1d222df3b9e8a82e6.png
提示1:如果更快 全集搜索 之前运算符是怎么解决的 case LESS_EQUAL: || case NOT_EQUAL: ||
提示2:比较运算符的差异 select * from t12 where num =14; select * from t12 where num is null;
查询索引
IndexScanner *Table::find_index_for_scan
IndexScanner *BplusTreeIndex::create_scanner
BplusTreeScanner::open
find_first_index_satisfied
breakpoint set --file bplus_tree.cpp --line 190
}
Table::scan_record
scan_record_by_index
next_entry
get_next_idx_in_memory
filter->filter
bool BplusTreeScanner::satisfy_condition
breakpoint set --file bplus_tree.cpp --line 2283
我gdb跟踪错误 :数据为什么不对。结果发现:
breakpoint set --file condition_filter.cpp --line 388
breakpoint set --file condition_filter.cpp --line 270
breakpoint set --file bplus_tree.cpp --line 2467
bool DefaultConditionFilter::filter(const Record &rec) const
void TupleRecordConverter::add_record(const char *record)
潜台词:这三个函数 干什么的,
bool DefaultConditionFilter::filter(const Record &rec) const
execute_stage.cpp
breakpoint set --file execute_stage.cpp --line 342
breakpoint set --file condition_filter.cpp --line 388
breakpoint set --file condition_filter.cpp --line 388
breakpoint set --file condition_filter.cpp --line 270
breakpoint set --file bplus_tree.cpp --line 2467
8c2f3f2f0768518da9706a4dcf8cac6d.png
breakpoint set --file bplus_tree.cpp --line 2467
查询无记录 select * from NULL_TABLE3;
自己开始认为null ,不需要查询出来【错误】
select * from NULL_TABLE3;
breakpoint set --file execute_stage.cpp --line 342
breakpoint set --file tuple.cpp --line 355
breakpoint set --file tuple.cpp --line 834
839
SELECT NUM FROM NULL_TABLE3;
null: result file difference(`-` is yours and `+` is base)
CREATE TABLE NULL_TABLE3(ID INT, NUM INT NULLABLE);
SUCCESS
INSERT INTO NULL_TABLE3 VALUES (1, NULL);
SUCCESS
INSERT INTO NULL_TABLE3 VALUES (2, NULL);
SUCCESS
SELECT COUNT(NUM) FROM NULL_TABLE3;
COUNT(NUM)
0
SELECT MIN(NUM) FROM NULL_TABLE3;
+MIN(NUM)
+NULL
+SELECT max(num) FROM null_table3;
+MAX(NUM)
+NULL
+SELECT avg(num) FROM null_table3;
+AVG(NUM)
+NULL
8f306a2f07ef2203d29b6045fdb169ad.png
2359ac666e468f2b549276eeb91efa28.png
insert into t13 values(1,20,"2021-01-30");
insert into t12 values(2,20,"2021-01-01");
select t12.num,t13.num,t12.birthday from t12,t13 where t12.num=t13.num;
breakpoint set --file execute_stage.cpp --line 308
selects
[0] = (relation_name = "t12", attribute_name = "birthday", funtype = FUN_NO) [1] = (relation_name = "t13", attribute_name = "num", funtype = FUN_NO) [2] = (relation_name = "t12", attribute_name = "num", funtype = FUN_NO)
问:多表查询,case:select t12.num,t13.num,t12.birthday from t12,t13 where t12.num=t13.num;
显示时候 select t12.num,t13.num,t12.birthday 你们思路怎么处理的,默认代码 按照表过滤字段显示的?
select t12.num,t13.num,t12.birthday from t12,t13 where t12.num=t13.num;
4f12ecdddfc3c75ec196989c93fe0313.png
breakpoint set --file execute_stage.cpp --line 307
breakpoint set --file execute_stage.cpp --line 270
breakpoint set --file execute_stage.cpp --line 340
breakpoint set --file execute_stage.cpp --line 362
1fdce6189431146436486957ee986a74.png
schema_ = {
fields_ = size=2 {
[0] = {
type_ = INTS
table_name_ = "t12"
field_name_ = "num"
visible_ = true
function_type = FUN_NO
nullable_ = 1
field_name_count_number_ = ""
}
[1] = {
type_ = DATES
table_name_ = "t12"
field_name_ = "birthday"
visible_ = true
function_type = FUN_NO
nullable_ = 1
field_name_count_number_ = ""
}
}
realTabeNumber = -1
}
[0] = {
tuples_ = size=1 {
[0] = {
values_ = size=1 {
[0] = std::__1::shared_ptr<TupleValue>::element_type @ 0x00007fc448604080 strong=1 weak=1 {
__ptr_ = 0x00007fc448604080
}
}
sp1 = nullptr {
__ptr_ = nullptr
}
sp2 = nullptr {
__ptr_ = nullptr
}
sp3 = nullptr {
__ptr_ = nullptr
}
selectComareIndex = -1
}
}
schema_ = {
fields_ = size=1 {
[0] = {
type_ = INTS
table_name_ = "t13"
field_name_ = "num"
visible_ = true
function_type = FUN_NO
nullable_ = 1
field_name_count_number_ = ""
}
}
realTabeNumber = -1
}
select t12.num,t13.num,t12.birthday from t12,t13 where t12.num=t13.num;
create_selection_executor
null: result file difference(`-` is yours and `+` is base)
SELECT NULL_TABLE.NUM,NULL_TABLE2.NUM,NULL_TABLE.BIRTHDAY FROM NULL_TABLE,NULL_TABLE2 WHERE NULL_TABLE.NUM=NULL_TABLE2.NUM;
-18 | 2020-01-01 | 18
-NULL_TABLE.NUM | NULL_TABLE.BIRTHDAY | NULL_TABLE2.NUM
+18 | 18 | 2020-01-01
+NULL_TABLE.NUM | NULL_TABLE2.NUM | NULL_TABLE.BIRTHDAY
insert into t12 values(6,null,null); //0k
select * from t12 where num =14; select * from t12 where num is null; select * from t12 where num is not null;
普通类型和int 如何比较
breakpoint set --file execute_stage.cpp --line 270
breakpoint set --file execute_stage.cpp --line 397
select * from t12 where num is not null;
1 | 2 | 2020-01-01 缺少记录呢
void TupleRecordConverter::add_record(const char *record)
索引查询:
1999行
tmp = CompareKey(node->keys + i * file_header_.key_length, key, file_header_.attr_type, file_header_.attr_length);
case LESS_THAN:
switch (attr_type)
{
case INTS:
flag = (i1 < i2);
break;
case FLOATS:
flag = (f1 < f2);
break;
case CHARS:
flag = (strncmp(s1, s2, attr_length) < 0);
break;
case DATES:
flag = (i1 < i2);
break;
default:
LOG_PANIC("Unknown attr type: %d", attr_type);
}
break;
int CompareKey(const char *pdata, const char *pkey, AttrType attr_type, int attr_length)
* thread #9, stop reason = breakpoint 1.1
* frame #0: 0x0000000109e572e4 observer`CompareKey(pdata="\U00000002", pkey="999", attr_type=INTS, attr_length=4) at bplus_tree.cpp:191:3 [opt]
frame #1: 0x0000000109e5d05a observer`BplusTreeHandler::find_first_index_satisfied(this=0x00007ff5b1407788, compop=IS_NULL, key="\xff\xff\xff\xff", page_num=<unavailable>, rididx=0x00007ff5b2b04804) at bplus_tree.cpp:1955:13 [opt]
frame #2: 0x0000000109e5d3cf observer`BplusTreeScanner::open(this=0x00007ff5b2b044c0, comp_op=IS_NULL, value=<unavailable>) at bplus_tree.cpp:2081:23 [opt]
frame #3: 0x0000000109e60445 observer`BplusTreeIndex::create_scanner(this=0x00007ff5b14076e0, comp_op=IS_NULL, value="999") at bplus_tree_index.cpp:98:31 [opt]
frame #4: 0x0000000109e76550 observer`Table::find_index_for_scan(this=0x00007ff5b1605160, filter=<unavailable>) at table.cpp:1067:31 [opt]
frame #5: 0x0000000109e75f54 observer`Table::scan_record(this=0x00007ff5b1605160, trx=0x00007ff5b1606eb0, filter=0x00007000065b1818, limit=2147483647, context=0x00007000065b17e0, record_reader=(observer`scan_record_reader_adapter(Record*, void*) at table.cpp:502))(Record*, void*)) at table.cpp:531:33 [opt]
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/sql/parser/parse.cpp condition_init 195]>>left_is_attr ...........
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/storage/common/bplus_tree.cpp CompareKey 197]>>CompareKey int >>>: 1=2,2=3750201
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/storage/common/bplus_tree.cpp CompareKey 197]>>CompareKey int >>>: 1=2,2=3750201
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/storage/common/bplus_tree.cpp CompareKey 197]>>CompareKey int >>>: 1=2,2=3750201
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/storage/common/bplus_tree.cpp CompareKey 197]>>CompareKey int >>>: 1=3750201,2=3750201
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/storage/common/bplus_tree.cpp CompareKey 197]>>CompareKey int >>>: 1=3750201,2=3750201
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/storage/common/bplus_tree.cpp CompareKey 197]>>CompareKey int >>>: 1=3750201,2=3750201
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/storage/common/bplus_tree.cpp CompareKey 197]>>CompareKey int >>>: 1=3750201,2=3750201
[2021-11-13 18:44:3 pid:18738 tid:7000065b5000 INFO: /Users/wangchuanyi/code/miniob/src/observer/sql/executor/execute_stage.cpp do_select 681]>> query resault. id | num | birthday
//比较2个key 大小
int CompareKey(const char *pdata, const char *pkey, AttrType attr_type, int attr_length)
bool DefaultConditionFilter::filter(const Record &rec) const
不对呀 比较从哪里跌
根据索引查找:
RC Table::scan_record(
null 用 999 表示
IndexScanner *index_scanner = find_index_for_scan(filter);
if (index_scanner != nullptr)
{
return scan_record_by_index(trx, index_scanner, filter, limit, context, record_reader);
}
1faecc37091dddb49caa28920dbbaaf6.png
bool DefaultConditionFilter::filter(const Record &rec) const
题目:支持NULL类型
sql:select * from t where null is null; -- 注意 = 与 is 的区别
问题:null is null 这个是true 还是false呀?
测试结果不对
d4eb03443d80d58b67138d2bab9c486f.png
e9f6fd4ac322baa76fb9d1189723bc41.png
right_is_attr = 1 right_attr = (relation_name = 0x0000000000000000, attribute_name = "NULLL", funtype = FUN_MAX | 0xe2f300a8)
24d1a4919d6dbd8c241f423396d1bf3d.png
select * from t12 WHERE NULL IS NULLL;
right.is_attr = true;
const FieldMeta *field_right = table_meta.field(condition.right_attr.attribute_name);
if (nullptr == field_right)
{
LOG_WARN("No such field in condition. %s.%s", table.name(), condition.right_attr.attribute_name);
return RC::SCHEMA_FIELD_MISSING;
}
void condition_init(Condition *condition, CompOp comp,
int left_is_attr, RelAttr *left_attr, Value *left_value,
int right_is_attr, RelAttr *right_attr, Value *right_value) {
Comparison Functions and Operators
https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html
https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal
https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
You cannot use arithmetic comparison operators such as =, <, or <> to test for NULL. To demonstrate this for yourself, try the following query:
Because the result of any arithmetic comparison with NULL is also NULL, you cannot obtain any meaningful results from such comparisons. https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html
画外音:
代码:
select * from t12 where 1<>NULL; select * from t12 where NULL<>1;
RC Table::scan_record_by_index(
class ConditionFilter {
public:
virtual ~ConditionFilter();
/**
* Filter one record
* @param rec
* @return true means match condition, false means failed to match.
*/
virtual bool filter(const Record &rec) const = 0;
};
do_select->create_selection_executor->
class DefaultConditionFilter : public ConditionFilter
execute
//sql执行
RC SelectExeNode::execute(TupleSet &tuple_set) {
CompositeConditionFilter condition_filter;
condition_filter.init((const ConditionFilter **)condition_filters_.data(), condition_filters_.size());
tuple_set.clear();
tuple_set.set_schema(tuple_schema_);
tuple_set.old_schema =old_tuple_schema;
TupleRecordConverter converter(table_, tuple_set);
return table_->scan_record(trx_, &condition_filter, -1, (void *)&converter, record_reader);
}
总结:
任何 值(保留运算符)与NULL做对比,结果都是FALSE
https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html
AttrType attr_type = index_handler_.file_header_.attr_type;
case IS_NULL:
{
flag =false;
}
break;
case IS_NOT_NULL:
{
flag =true;
}
break;
select * from t12 where id is null; select * from t12 where id is not null;
select * from t12 where 1<>NULL; select * from t12 where 1 IS NOT NULL;
任务:RC DefaultConditionFilter::init(Table &table, const Condition &condition)
bool DefaultConditionFilter::filter(const Record &rec) const
1 IS NOT NULL; //true case IS_NOT_NULL: return cmp_result != 0;
select * from t12 where id is null;
std::vector<DefaultConditionFilter *> condition_filters;
RC DefaultConditionFilter::init(Table &table, const Condition &condition)
private:
ConDesc left_;
ConDesc right_;
AttrType attr_type_ = UNDEFINED;
CompOp comp_op_ = NO_OP;
};
任务:调整RC DefaultConditionFilter::init函数
where:
condition:
bool TupleSet::avg_print(std::ostream &os) const
RC DefaultConditionFilter::init(Table &table, const Condition &condition)
private:
ConDesc left_;
ConDesc right_;
AttrType attr_type_ = UNDEFINED;
CompOp comp_op_ = NO_OP;
};
bool BplusTreeScanner::satisfy_condition(const char *pkey)
comOp:
EQ { CONTEXT->comp = EQUAL_TO; }
| LT { CONTEXT->comp = LESS_THAN; }
| GT { CONTEXT->comp = GREAT_THAN; }
| LE { CONTEXT->comp = LESS_EQUAL; }
| GE { CONTEXT->comp = GREAT_EQUAL; }
| NE { CONTEXT->comp = NOT_EQUAL; }
;
void TupleRecordConverter::add_record(const char *record)
null: result file difference(`-` is yours and `+` is base)
3. SELECT WITH CONSTANT
SELECT * FROM NULL_TABLE WHERE 1 IS NULL;
-FAILURE
+ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1 IS NOT NULL;
-FAILURE
+1 | 18 | 10 | 2020-01-01
+2 | NULL | 20 | 2010-01-11
+3 | 12 | 30 | NULL
+4 | 15 | 30 | 2021-01-31
+ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE NULL=1;
-FAILURE
+ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1=NULL;
-FAILURE
+ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1<>NULL;
-FAILURE
+ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1<NULL;
-FAILURE
+ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1>NULL;
-FAILURE
+ID | NUM | PRICE | BIRTHDAY
CREATE TABLE NULL_TABLE(ID INT, NUM INT NULLABLE, PRICE FLOAT NOT NULL, BIRTHDAY DATE NULLABLE);
CREATE TABLE NULL_TABLE2(ID INT, NUM INT NULLABLE, PRICE FLOAT NOT NULL, BIRTHDAY DATE NULLABLE);
CREATE INDEX INDEX_NUM ON NULL_TABLE(NUM);
CREATE TABLE NULL_TABLE(ID INT, NUM INT NULLABLE, PRICE FLOAT NOT NULL, BIRTHDAY DATE NULLABLE);
-FAILURE
+SUCCESS
CREATE TABLE NULL_TABLE2(ID INT, NUM INT NULLABLE, PRICE FLOAT NOT NULL, BIRTHDAY DATE NULLABLE);
-FAILURE
+SUCCESS
CREATE INDEX INDEX_NUM ON NULL_TABLE(NUM);
-FAILURE
+SUCCESS
3298bb857adc370ead1071015fc2060b.png
: line 1: 1355 Segmentation fault: 11 ./observer -f ./observer.ini
0x0000000107d8ef8d Table::make_record(int, _Value const*, char*&) + 1357 (table.cpp:430)
f93af99ea8021b6cb8df592825469889.png
null: result file difference(`-` is yours and `+` is base)
3. SELECT WITH CONSTANT
SELECT * FROM NULL_TABLE WHERE 1 IS NULL;
ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1 IS NOT NULL;
1 | 18 | 10 | 2020-01-01
2 | NULL | 20 | 2010-01-11
3 | 12 | 30 | NULL
4 | 15 | 30 | 2021-01-31
ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE NULL=1;
-FAILURE
+ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1=NULL;
ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1<>NULL;
-1 | 18 | 10 | 2020-01-01
-2 | NULL | 20 | 2010-01-11
-3 | 12 | 30 | NULL
-4 | 15 | 30 | 2021-01-31
ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1<NULL;
-1 | 18 | 10 | 2020-01-01
-2 | NULL | 20 | 2010-01-11
-3 | 12 | 30 | NULL
-4 | 15 | 30 | 2021-01-31
ID | NUM | PRICE | BIRTHDAY
SELECT * FROM NULL_TABLE WHERE 1>NULL;
ID | NUM | PRICE | BIRTHDAY