Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
oceanbase
miniob
提交
db181edb
M
miniob
项目概览
oceanbase
/
miniob
1 年多 前同步成功
通知
74
Star
1521
Fork
537
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
分析
仓库
DevOps
项目成员
Pages
M
miniob
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Pages
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
提交
提交
db181edb
编写于
8月 12, 2022
作者:
羽飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix var len char
上级
2500a791
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
1058 addition
and
53 deletion
+1058
-53
1.patch
1.patch
+797
-0
src/observer/sql/expr/expression.h
src/observer/sql/expr/expression.h
+6
-1
src/observer/sql/expr/tuple.h
src/observer/sql/expr/tuple.h
+1
-0
src/observer/sql/expr/tuple_cell.cpp
src/observer/sql/expr/tuple_cell.cpp
+2
-2
src/observer/sql/expr/tuple_cell.h
src/observer/sql/expr/tuple_cell.h
+5
-0
src/observer/sql/operator/index_scan_operator.cpp
src/observer/sql/operator/index_scan_operator.cpp
+2
-2
src/observer/storage/common/condition_filter.h
src/observer/storage/common/condition_filter.h
+2
-0
src/observer/storage/common/table.cpp
src/observer/storage/common/table.cpp
+16
-2
src/observer/storage/common/table.h
src/observer/storage/common/table.h
+1
-0
src/observer/storage/default/disk_buffer_pool.cpp
src/observer/storage/default/disk_buffer_pool.cpp
+2
-0
src/observer/storage/index/bplus_tree.cpp
src/observer/storage/index/bplus_tree.cpp
+101
-9
src/observer/storage/index/bplus_tree.h
src/observer/storage/index/bplus_tree.h
+24
-6
src/observer/storage/index/bplus_tree_index.cpp
src/observer/storage/index/bplus_tree_index.cpp
+6
-5
src/observer/storage/index/bplus_tree_index.h
src/observer/storage/index/bplus_tree_index.h
+4
-3
src/observer/storage/index/index.h
src/observer/storage/index/index.h
+2
-2
src/observer/util/comparator.cpp
src/observer/util/comparator.cpp
+16
-2
src/observer/util/comparator.h
src/observer/util/comparator.h
+1
-1
unitest/bplus_tree_test.cpp
unitest/bplus_tree_test.cpp
+70
-18
未找到文件。
1.patch
0 → 100644
浏览文件 @
db181edb
diff --git a/src/observer/sql/expr/expression.h b/src/observer/sql/expr/expression.h
index c586bf2..59b1750 100644
--- a/src/observer/sql/expr/expression.h
+++ b/src/observer/sql/expr/expression.h
@@ -14,6 +14,7 @@
See the Mulan PSL v2 for more details. */
#pragma once
+#include <string.h>
#include "storage/common/field.h"
#include "sql/expr/tuple_cell.h"
@@ -79,7 +80,11 @@
class ValueExpr : public Expression
public:
ValueExpr() = default;
ValueExpr(const Value &value) : tuple_cell_(value.type, (char *)value.data)
- {}
+ {
+ if (value.type == CHARS) {
+ tuple_cell_.set_length(strlen((const char *)value.data));
+ }
+ }
virtual ~ValueExpr() = default;
diff --git a/src/observer/sql/expr/tuple.h b/src/observer/sql/expr/tuple.h
index 07c33c7..7efed51 100644
--- a/src/observer/sql/expr/tuple.h
+++ b/src/observer/sql/expr/tuple.h
@@ -115,6 +115,7 @@
public:
const FieldMeta *field_meta = field_expr->field().meta();
cell.set_type(field_meta->type());
cell.set_data(this->record_->data() + field_meta->offset());
+ cell.set_length(field_meta->len());
return RC::SUCCESS;
}
diff --git a/src/observer/sql/expr/tuple_cell.cpp b/src/observer/sql/expr/tuple_cell.cpp
index 9ccd3d3..c878b31 100644
--- a/src/observer/sql/expr/tuple_cell.cpp
+++ b/src/observer/sql/expr/tuple_cell.cpp
@@ -27,7 +27,7 @@
void TupleCell::to_string(std::ostream &os) const
os << *(float *)data_;
} break;
case CHARS: {
- for (int i = 0; i < 4; i++) { // the max length of CHARS is 4
+ for (int i = 0; i < length_; i++) {
if (data_[i] == '\0') {
break;
}
@@ -46,7 +46,7 @@
int TupleCell::compare(const TupleCell &other) const
switch (this->attr_type_) {
case INTS: return compare_int(this->data_, other.data_);
case FLOATS: return compare_float(this->data_, other.data_);
- case CHARS: return compare_string(this->data_, other.data_, 4);
+ case CHARS: return compare_string(this->data_, this->length_, other.data_, other.length_);
default: {
LOG_WARN("unsupported type: %d", this->attr_type_);
}
diff --git a/src/observer/sql/expr/tuple_cell.h b/src/observer/sql/expr/tuple_cell.h
index 89170f2..faf3996 100644
--- a/src/observer/sql/expr/tuple_cell.h
+++ b/src/observer/sql/expr/tuple_cell.h
@@ -31,6 +31,7 @@
public:
{}
void set_type(AttrType type) { this->attr_type_ = type; }
+ void set_length(int length) { this->length_ = length; }
void set_data(char *data) { this->data_ = data; }
void set_data(const char *data) { this->set_data(const_cast<char *>(data)); }
@@ -43,11 +44,15 @@
public:
return data_;
}
+ int length() const { return length_; }
+
AttrType attr_type() const
{
return attr_type_;
}
+
private:
AttrType attr_type_ = UNDEFINED;
+ int length_ = -1;
char *data_ = nullptr; // real data. no need to move to field_meta.offset
};
diff --git a/src/observer/sql/operator/index_scan_operator.cpp b/src/observer/sql/operator/index_scan_operator.cpp
index 1be1a37..2aad13b 100644
--- a/src/observer/sql/operator/index_scan_operator.cpp
+++ b/src/observer/sql/operator/index_scan_operator.cpp
@@ -36,8 +36,8 @@
RC IndexScanOperator::open()
}
- IndexScanner *index_scanner = index_->create_scanner(left_cell_.data(), left_inclusive_,
- right_cell_.data(), right_inclusive_);
+ IndexScanner *index_scanner = index_->create_scanner(left_cell_.data(), left_cell_.length(), left_inclusive_,
+ right_cell_.data(), right_cell_.length(), right_inclusive_);
if (nullptr == index_scanner) {
LOG_WARN("failed to create index scanner");
return RC::INTERNAL;
diff --git a/src/observer/storage/common/condition_filter.h b/src/observer/storage/common/condition_filter.h
index 890195a..e4b7f98 100644
--- a/src/observer/storage/common/condition_filter.h
+++ b/src/observer/storage/common/condition_filter.h
@@ -66,6 +66,8 @@
public:
return comp_op_;
}
+ AttrType attr_type() const { return attr_type_; }
+
private:
ConDesc left_;
ConDesc right_;
diff --git a/src/observer/storage/common/table.cpp b/src/observer/storage/common/table.cpp
index 7ff43ca..f53be21 100644
--- a/src/observer/storage/common/table.cpp
+++ b/src/observer/storage/common/table.cpp
@@ -326,7 +326,14 @@
RC Table::make_record(int value_num, const Value *values, char *&record_out)
for (int i = 0; i < value_num; i++) {
const FieldMeta *field = table_meta_.field(i + normal_field_start_index);
const Value &value = values[i];
- memcpy(record + field->offset(), value.data, field->len());
+ size_t copy_len = field->len();
+ if (field->type() == CHARS) {
+ const size_t data_len = strlen((const char *)value.data);
+ if (copy_len > data_len) {
+ copy_len = data_len + 1;
+ }
+ }
+ memcpy(record + field->offset(), value.data, copy_len);
}
record_out = record;
@@ -775,6 +782,8 @@
IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
const char *left_key = nullptr;
const char *right_key = nullptr;
+ int left_len = 4;
+ int right_len = 4;
bool left_inclusive = false;
bool right_inclusive = false;
switch (filter.comp_op()) {
@@ -809,7 +818,12 @@
IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
return nullptr;
}
}
- return index->create_scanner(left_key, left_inclusive, right_key, right_inclusive);
+
+ if (filter.attr_type() == CHARS) {
+ left_len = left_key != nullptr ? strlen(left_key) : 0;
+ right_len = right_key != nullptr ? strlen(right_key) : 0;
+ }
+ return index->create_scanner(left_key, left_len, left_inclusive, right_key, right_len, right_inclusive);
}
IndexScanner *Table::find_index_for_scan(const ConditionFilter *filter)
diff --git a/src/observer/storage/common/table.h b/src/observer/storage/common/table.h
index a185535..7075537 100644
--- a/src/observer/storage/common/table.h
+++ b/src/observer/storage/common/table.h
@@ -29,6 +29,7 @@
class IndexScanner;
class RecordDeleter;
class Trx;
+// TODO remove the routines with condition
class Table {
public:
Table() = default;
diff --git a/src/observer/storage/default/disk_buffer_pool.cpp b/src/observer/storage/default/disk_buffer_pool.cpp
index e3953ae..18a2450 100644
--- a/src/observer/storage/default/disk_buffer_pool.cpp
+++ b/src/observer/storage/default/disk_buffer_pool.cpp
@@ -295,6 +295,8 @@
RC DiskBufferPool::allocate_page(Frame **frame)
RC DiskBufferPool::unpin_page(Frame *frame)
{
+ assert(frame->pin_count_ >= 1);
+
if (--frame->pin_count_ == 0) {
PageNum page_num = frame->page_num();
auto pages_it = disposed_pages.find(page_num);
diff --git a/src/observer/storage/index/bplus_tree.cpp b/src/observer/storage/index/bplus_tree.cpp
index 50e49f1..0e7a62d 100644
--- a/src/observer/storage/index/bplus_tree.cpp
+++ b/src/observer/storage/index/bplus_tree.cpp
@@ -1443,10 +1443,10 @@
RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid)
return RC::SUCCESS;
}
-RC BplusTreeHandler::get_entry(const char *user_key, std::list<RID> &rids)
+RC BplusTreeHandler::get_entry(const char *user_key, int key_len, std::list<RID> &rids)
{
BplusTreeScanner scanner(*this);
- RC rc = scanner.open(user_key, true/*left_inclusive*/, user_key, true/*right_inclusive*/);
+ RC rc = scanner.open(user_key, key_len, true/*left_inclusive*/, user_key, key_len, true/*right_inclusive*/);
if (rc != RC::SUCCESS) {
LOG_WARN("failed to open scanner. rc=%d:%s", rc, strrc(rc));
return rc;
@@ -1721,8 +1721,8 @@
BplusTreeScanner::~BplusTreeScanner()
close();
}
-RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
- const char *right_user_key, bool right_inclusive)
+RC BplusTreeScanner::open(const char *left_user_key, int left_len, bool left_inclusive,
+ const char *right_user_key, int right_len, bool right_inclusive)
{
RC rc = RC::SUCCESS;
if (inited_) {
@@ -1753,10 +1753,30 @@
RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
iter_index_ = 0;
} else {
char *left_key = nullptr;
- if (left_inclusive) {
- left_key = tree_handler_.make_key(left_user_key, *RID::min());
+
+ char *fixed_left_key = const_cast<char *>(left_user_key);
+ if (tree_handler_.file_header_.attr_type == CHARS) {
+ bool should_inclusive_after_fix = false;
+ rc = fix_user_key(left_user_key, left_len, true/*greater*/, &fixed_left_key, &should_inclusive_after_fix);
+ if (rc != RC::SUCCESS) {
+ LOG_WARN("failed to fix left user key. rc=%s", strrc(rc));
+ return rc;
+ }
+
+ if (should_inclusive_after_fix) {
+ left_inclusive = true;
+ }
+ }
+
+ if (left_inclusive) {
+ left_key = tree_handler_.make_key(fixed_left_key, *RID::min());
} else {
- left_key = tree_handler_.make_key(left_user_key, *RID::max());
+ left_key = tree_handler_.make_key(fixed_left_key, *RID::max());
+ }
+
+ if (fixed_left_key != left_user_key) {
+ delete[] fixed_left_key;
+ fixed_left_key = nullptr;
}
rc = tree_handler_.find_leaf(left_key, left_frame_);
@@ -1800,10 +1820,28 @@
RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
} else {
char *right_key = nullptr;
+ char *fixed_right_key = const_cast<char *>(right_user_key);
+ bool should_include_after_fix = false;
+ if (tree_handler_.file_header_.attr_type == CHARS) {
+ rc = fix_user_key(right_user_key, right_len, false/*want_greater*/, &fixed_right_key, &should_include_after_fix);
+ if (rc != RC::SUCCESS) {
+ LOG_WARN("failed to fix right user key. rc=%s", strrc(rc));
+ return rc;
+ }
+
+ if (should_include_after_fix) {
+ right_inclusive = true;
+ }
+ }
if (right_inclusive) {
- right_key = tree_handler_.make_key(right_user_key, *RID::max());
+ right_key = tree_handler_.make_key(fixed_right_key, *RID::max());
} else {
- right_key = tree_handler_.make_key(right_user_key, *RID::min());
+ right_key = tree_handler_.make_key(fixed_right_key, *RID::min());
+ }
+
+ if (fixed_right_key != right_user_key) {
+ delete[] fixed_right_key;
+ fixed_right_key = nullptr;
}
rc = tree_handler_.find_leaf(right_key, right_frame_);
@@ -1883,11 +1921,13 @@
RC BplusTreeScanner::next_entry(RID *rid)
PageNum page_num = node.next_page();
tree_handler_.disk_buffer_pool_->unpin_page(left_frame_);
if (page_num == BP_INVALID_PAGE_NUM) {
+ left_frame_ = nullptr;
LOG_WARN("got invalid next page. page num=%d", page_num);
rc = RC::INTERNAL;
} else {
rc = tree_handler_.disk_buffer_pool_->get_this_page(page_num, &left_frame_);
if (rc != RC::SUCCESS) {
+ left_frame_ = nullptr;
LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", page_num, rc, strrc(rc));
return rc;
}
@@ -1906,12 +1946,64 @@
RC BplusTreeScanner::close()
{
if (left_frame_ != nullptr) {
tree_handler_.disk_buffer_pool_->unpin_page(left_frame_);
+ left_frame_ = nullptr;
}
if (right_frame_ != nullptr) {
tree_handler_.disk_buffer_pool_->unpin_page(right_frame_);
+ right_frame_ = nullptr;
}
end_index_ = -1;
inited_ = false;
LOG_INFO("bplus tree scanner closed");
return RC::SUCCESS;
}
+
+RC BplusTreeScanner::fix_user_key(const char *user_key, int key_len, bool want_greater,
+ char **fixed_key, bool *should_inclusive)
+{
+ if (nullptr == fixed_key || nullptr == should_inclusive) {
+ return RC::INVALID_ARGUMENT;
+ }
+
+ // 这里很粗暴,变长字段才需要做调整,其它默认都不需要做调整
+ assert(tree_handler_.file_header_.attr_type == CHARS);
+ assert(strlen(user_key) >= static_cast<size_t>(key_len));
+
+ *should_inclusive = false;
+
+ int32_t attr_length = tree_handler_.file_header_.attr_length;
+ char *key_buf = new (std::nothrow)char [attr_length];
+ if (nullptr == key_buf) {
+ return RC::NOMEM;
+ }
+
+ if (key_len <= attr_length) {
+ memcpy(key_buf, user_key, key_len);
+ memset(key_buf + key_len, 0, attr_length - key_len);
+
+ *fixed_key = key_buf;
+ return RC::SUCCESS;
+ }
+
+ // key_len > attr_length
+ memcpy(key_buf, user_key, attr_length);
+
+ char c = user_key[attr_length];
+ if (c == 0) {
+ *fixed_key = key_buf;
+ return RC::SUCCESS;
+ }
+
+ // 扫描 >=/> user_key 的数据
+ // 示例:>=/> ABCD1 的数据,attr_length=4,
+ // 等价于扫描 >= ABCE 的数据
+ // 如果是扫描 <=/< user_key的数据
+ // 示例:<=/< ABCD1 <==> <= ABCD (attr_length=4)
+ *should_inclusive = true;
+ if (want_greater) {
+ key_buf[attr_length - 1]++;
+ }
+
+ *fixed_key = key_buf;
+ return RC::SUCCESS;
+}
diff --git a/src/observer/storage/index/bplus_tree.h b/src/observer/storage/index/bplus_tree.h
index 91d9d48..7a09b1b 100644
--- a/src/observer/storage/index/bplus_tree.h
+++ b/src/observer/storage/index/bplus_tree.h
@@ -118,7 +118,14 @@
public:
return std::to_string(*(float*)v);
}
case CHARS: {
- return std::string(v, attr_length_);
+ std::string str;
+ for (int i = 0; i < attr_length_; i++) {
+ if (v[i] == 0) {
+ break;
+ }
+ str.push_back(v[i]);
+ }
+ return str;
}
default:{
LOG_ERROR("unknown attr type. %d", attr_type_);
@@ -400,12 +407,14 @@
public:
* 此函数向IndexHandle对应的索引中插入一个索引项。
* 参数user_key指向要插入的属性值,参数rid标识该索引项对应的元组,
* 即向索引中插入一个值为(user_key,rid)的键值对
+ * @note 这里假设user_key的内存大小与attr_length 一致
*/
RC insert_entry(const char *user_key, const RID *rid);
/**
* 从IndexHandle句柄对应的索引中删除一个值为(*pData,rid)的索引项
* @return RECORD_INVALID_KEY 指定值不存在
+ * @note 这里假设user_key的内存大小与attr_length 一致
*/
RC delete_entry(const char *user_key, const RID *rid);
@@ -413,9 +422,10 @@
public:
/**
* 获取指定值的record
+ * @param key_len user_key的长度
* @param rid 返回值,记录记录所在的页面号和slot
*/
- RC get_entry(const char *user_key, std::list<RID> &rids);
+ RC get_entry(const char *user_key, int key_len, std::list<RID> &rids);
RC sync();
@@ -493,18 +503,26 @@
public:
/**
* 扫描指定范围的数据
- * @param left_key 扫描范围的左边界,如果是null,则没有左边界
+ * @param left_user_key 扫描范围的左边界,如果是null,则没有左边界
+ * @param left_len left_user_key 的内存大小(只有在变长字段中才会关注)
* @param left_inclusive 左边界的值是否包含在内
- * @param right_key 扫描范围的右边界。如果是null,则没有右边界
+ * @param right_user_key 扫描范围的右边界。如果是null,则没有右边界
+ * @param right_len right_user_key 的内存大小(只有在变长字段中才会关注)
* @param right_inclusive 右边界的值是否包含在内
*/
- RC open(const char *left_user_key, bool left_inclusive,
- const char *right_user_key, bool right_inclusive);
+ RC open(const char *left_user_key, int left_len, bool left_inclusive,
+ const char *right_user_key, int right_len, bool right_inclusive);
RC next_entry(RID *rid);
RC close();
+private:
+ /**
+ * 如果key的类型是CHARS, 扩展或缩减user_key的大小刚好是schema中定义的大小
+ */
+ RC fix_user_key(const char *user_key, int key_len, bool want_greater,
+ char **fixed_key, bool *should_inclusive);
private:
bool inited_ = false;
BplusTreeHandler &tree_handler_;
diff --git a/src/observer/storage/index/bplus_tree_index.cpp b/src/observer/storage/index/bplus_tree_index.cpp
index ea69bcc..cbaef5c 100644
--- a/src/observer/storage/index/bplus_tree_index.cpp
+++ b/src/observer/storage/index/bplus_tree_index.cpp
@@ -98,11 +98,11 @@
RC BplusTreeIndex::delete_entry(const char *record, const RID *rid)
return index_handler_.delete_entry(record + field_meta_.offset(), rid);
}
-IndexScanner *BplusTreeIndex::create_scanner(const char *left_key, bool left_inclusive,
- const char *right_key, bool right_inclusive)
+IndexScanner *BplusTreeIndex::create_scanner(const char *left_key, int left_len, bool left_inclusive,
+ const char *right_key, int right_len, bool right_inclusive)
{
BplusTreeIndexScanner *index_scanner = new BplusTreeIndexScanner(index_handler_);
- RC rc = index_scanner->open(left_key, left_inclusive, right_key, right_inclusive);
+ RC rc = index_scanner->open(left_key, left_len, left_inclusive, right_key, right_len, right_inclusive);
if (rc != RC::SUCCESS) {
LOG_WARN("failed to open index scanner. rc=%d:%s", rc, strrc(rc));
delete index_scanner;
@@ -125,9 +125,10 @@
BplusTreeIndexScanner::~BplusTreeIndexScanner() noexcept
tree_scanner_.close();
}
-RC BplusTreeIndexScanner::open(const char *left_key, bool left_inclusive, const char *right_key, bool right_inclusive)
+RC BplusTreeIndexScanner::open(const char *left_key, int left_len, bool left_inclusive,
+ const char *right_key, int right_len, bool right_inclusive)
{
- return tree_scanner_.open(left_key, left_inclusive, right_key, right_inclusive);
+ return tree_scanner_.open(left_key, left_len, left_inclusive, right_key, right_len, right_inclusive);
}
RC BplusTreeIndexScanner::next_entry(RID *rid)
diff --git a/src/observer/storage/index/bplus_tree_index.h b/src/observer/storage/index/bplus_tree_index.h
index 1c3ff92..c2e66f1 100644
--- a/src/observer/storage/index/bplus_tree_index.h
+++ b/src/observer/storage/index/bplus_tree_index.h
@@ -33,8 +33,8 @@
public:
/**
* 扫描指定范围的数据
*/
- IndexScanner *create_scanner(const char *left_key, bool left_inclusive,
- const char *right_key, bool right_inclusive) override;
+ IndexScanner *create_scanner(const char *left_key, int left_len, bool left_inclusive,
+ const char *right_key, int right_len, bool right_inclusive) override;
RC sync() override;
@@ -51,7 +51,8 @@
public:
RC next_entry(RID *rid) override;
RC destroy() override;
- RC open(const char *left_key, bool left_inclusive, const char *right_key, bool right_inclusive);
+ RC open(const char *left_key, int left_len, bool left_inclusive,
+ const char *right_key, int right_len, bool right_inclusive);
private:
BplusTreeScanner tree_scanner_;
};
diff --git a/src/observer/storage/index/index.h b/src/observer/storage/index/index.h
index d66a093..4f04fb4 100644
--- a/src/observer/storage/index/index.h
+++ b/src/observer/storage/index/index.h
@@ -46,8 +46,8 @@
public:
virtual RC insert_entry(const char *record, const RID *rid) = 0;
virtual RC delete_entry(const char *record, const RID *rid) = 0;
- virtual IndexScanner *create_scanner(const char *left_key, bool left_inclusive,
- const char *right_key, bool right_inclusive) = 0;
+ virtual IndexScanner *create_scanner(const char *left_key, int left_len, bool left_inclusive,
+ const char *right_key, int right_len, bool right_inclusive) = 0;
virtual RC sync() = 0;
diff --git a/src/observer/util/comparator.cpp b/src/observer/util/comparator.cpp
index f7e6a8e..1c8615f 100644
--- a/src/observer/util/comparator.cpp
+++ b/src/observer/util/comparator.cpp
@@ -13,6 +13,7 @@
See the Mulan PSL v2 for more details. */
//
#include <string.h>
+#include <algorithm>
const double epsilon = 1E-6;
@@ -37,9 +38,22 @@
int compare_float(void *arg1, void *arg2)
return 0;
}
-int compare_string(void *arg1, void *arg2, int maxlen)
+int compare_string(void *arg1, int arg1_max_length, void *arg2, int arg2_max_length)
{
const char *s1 = (const char *)arg1;
const char *s2 = (const char *)arg2;
- return strncmp(s1, s2, maxlen);
+ int maxlen = std::min(arg1_max_length, arg2_max_length);
+ int result = strncmp(s1, s2, maxlen);
+ if (0 != result) {
+ return result;
+ }
+
+ if (arg1_max_length > maxlen) {
+ return s1[maxlen] - 0;
+ }
+
+ if (arg2_max_length > maxlen) {
+ return 0 - s2[maxlen];
+ }
+ return 0;
}
diff --git a/src/observer/util/comparator.h b/src/observer/util/comparator.h
index c80e9f2..18ab99f 100644
--- a/src/observer/util/comparator.h
+++ b/src/observer/util/comparator.h
@@ -16,4 +16,4 @@
See the Mulan PSL v2 for more details. */
int compare_int(void *arg1, void *arg2);
int compare_float(void *arg1, void *arg2);
-int compare_string(void *arg1, void *arg2, int max_length);
+int compare_string(void *arg1, int arg1_max_length, void *arg2, int arg2_max_length);
diff --git a/unitest/bplus_tree_test.cpp b/unitest/bplus_tree_test.cpp
index 5fa48fd..dabfe08 100644
--- a/unitest/bplus_tree_test.cpp
+++ b/unitest/bplus_tree_test.cpp
@@ -31,6 +31,7 @@
using namespace common;
#define INSERT_NUM (TIMES * ORDER * ORDER * ORDER * ORDER)
#define POOL_NUM 2
+BufferPoolManager bpm;
BplusTreeHandler *handler = nullptr;
const char *index_name = "test.btree";
int insert_num = INSERT_NUM;
@@ -38,6 +39,12 @@
const int page_size = 1024;
RID rid, check_rid;
int k = 0;
+void init_bpm()
+{
+ if (&BufferPoolManager::instance() == nullptr) {
+ BufferPoolManager::set_instance(&bpm);
+ }
+}
void test_insert()
{
RC rc = RC::SUCCESS;
@@ -148,7 +155,7 @@
void test_get()
}
rids.clear();
- RC rc = handler->get_entry((const char *)&i, rids);
+ RC rc = handler->get_entry((const char *)&i, 4, rids);
ASSERT_EQ(RC::SUCCESS, rc);
ASSERT_EQ(1, rids.size());
@@ -221,7 +228,7 @@
void test_delete()
LOG_INFO("Begin to get entry of index, i=%d, rid: %s", i, rid.to_string().c_str());
}
rids.clear();
- rc = handler->get_entry((const char *)&i, rids);
+ rc = handler->get_entry((const char *)&i, 4, rids);
ASSERT_EQ(RC::SUCCESS, rc);
int t = i % TIMES;
if (t == 0 || t == 1) {
@@ -458,6 +465,50 @@
TEST(test_bplus_tree, test_internal_index_node_handle)
ASSERT_EQ(i, index);
}
}
+
+TEST(test_bplus_tree, test_chars)
+{
+ LoggerFactory::init_default("test_chars.log");
+
+ const char *index_name = "chars.btree";
+ ::remove(index_name);
+ handler = new BplusTreeHandler();
+ handler->create(index_name, CHARS, 8, ORDER, ORDER);
+
+ char keys[][9] = {
+ "abcdefg",
+ "12345678",
+ "12345678",
+ "abcdefg",
+ "abcdefga"
+ };
+
+ RID rid;
+ RC rc = RC::SUCCESS;
+ for (size_t i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
+ rid.page_num = 0;
+ rid.slot_num = i;
+ rc = handler->insert_entry(keys[i], &rid);
+ ASSERT_EQ(RC::SUCCESS, rc);
+ }
+
+ LOG_INFO("begin to print bplus tree of chars");
+ handler->print_tree();
+ LOG_INFO("end to print bplus tree of chars");
+
+ BplusTreeScanner scanner(*handler);
+ const char *key = "abcdefg";
+ rc = scanner.open(key, strlen(key), true, key, strlen(key), true);
+ ASSERT_EQ(rc, RC::SUCCESS);
+
+ int count = 0;
+ while (RC::SUCCESS == (rc = scanner.next_entry(&rid))) {
+ count++;
+ }
+ scanner.close();
+ ASSERT_EQ(2, count);
+}
+
TEST(test_bplus_tree, test_scanner)
{
LoggerFactory::init_default("test.log");
@@ -484,7 +535,7 @@
TEST(test_bplus_tree, test_scanner)
int begin = -100;
int end = -20;
- rc = scanner.open((const char *)&begin, false, (const char *)&end, false);
+ rc = scanner.open((const char *)&begin, 4, false, (const char *)&end, 4, false);
ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid);
@@ -494,7 +545,7 @@
TEST(test_bplus_tree, test_scanner)
begin = -100;
end = 1;
- rc = scanner.open((const char *)&begin, false, (const char *)&end, false);
+ rc = scanner.open((const char *)&begin, 4, false, (const char *)&end, 4, false);
ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::RECORD_EOF, rc);
@@ -503,7 +554,7 @@
TEST(test_bplus_tree, test_scanner)
begin = -100;
end = 1;
- rc = scanner.open((const char *)&begin, false, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, false, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::SUCCESS, rc);
@@ -514,7 +565,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 1;
end = 3;
- rc = scanner.open((const char *)&begin, false, (const char *)&end, false/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, false, (const char *)&end, 4, false/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::RECORD_EOF, rc);
@@ -523,7 +574,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 1;
end = 3;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
count++;
@@ -535,7 +586,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 0;
end = 3;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -548,7 +599,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 11;
end = 21;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -561,7 +612,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 11;
end = 91;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -574,7 +625,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 191;
end = 199;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -587,7 +638,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 191;
end = 201;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -600,7 +651,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 200;
end = 301;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::RECORD_EOF, rc);
@@ -609,14 +660,14 @@
TEST(test_bplus_tree, test_scanner)
begin = 300;
end = 201;
- rc = scanner.open((const char *)&begin, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::INVALID_ARGUMENT, rc);
scanner.close();
begin = 300;
end = 201;
- rc = scanner.open(nullptr, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open(nullptr, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -629,7 +680,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 300;
end = 10;
- rc = scanner.open(nullptr, true, (const char *)&end, true/*inclusive*/);
+ rc = scanner.open(nullptr, 4, true, (const char *)&end, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -642,7 +693,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 190;
end = 10;
- rc = scanner.open((const char *)&begin, true, nullptr, true/*inclusive*/);
+ rc = scanner.open((const char *)&begin, 4, true, nullptr, 4, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -655,7 +706,7 @@
TEST(test_bplus_tree, test_scanner)
begin = 190;
end = 10;
- rc = scanner.open(nullptr, true, nullptr, true/*inclusive*/);
+ rc = scanner.open(nullptr, 0, true, nullptr, 0, true/*inclusive*/);
ASSERT_EQ(RC::SUCCESS, rc);
count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
@@ -695,6 +746,7 @@
int main(int argc, char **argv)
// 调用RUN_ALL_TESTS()运行所有测试用例
// main函数返回RUN_ALL_TESTS()的运行结果
+ init_bpm();
int rc = RUN_ALL_TESTS();
return rc;
src/observer/sql/expr/expression.h
浏览文件 @
db181edb
...
...
@@ -14,6 +14,7 @@ See the Mulan PSL v2 for more details. */
#pragma once
#include <string.h>
#include "storage/common/field.h"
#include "sql/expr/tuple_cell.h"
...
...
@@ -79,7 +80,11 @@ class ValueExpr : public Expression
public:
ValueExpr
()
=
default
;
ValueExpr
(
const
Value
&
value
)
:
tuple_cell_
(
value
.
type
,
(
char
*
)
value
.
data
)
{}
{
if
(
value
.
type
==
CHARS
)
{
tuple_cell_
.
set_length
(
strlen
((
const
char
*
)
value
.
data
));
}
}
virtual
~
ValueExpr
()
=
default
;
...
...
src/observer/sql/expr/tuple.h
浏览文件 @
db181edb
...
...
@@ -115,6 +115,7 @@ public:
const
FieldMeta
*
field_meta
=
field_expr
->
field
().
meta
();
cell
.
set_type
(
field_meta
->
type
());
cell
.
set_data
(
this
->
record_
->
data
()
+
field_meta
->
offset
());
cell
.
set_length
(
field_meta
->
len
());
return
RC
::
SUCCESS
;
}
...
...
src/observer/sql/expr/tuple_cell.cpp
浏览文件 @
db181edb
...
...
@@ -27,7 +27,7 @@ void TupleCell::to_string(std::ostream &os) const
os
<<
*
(
float
*
)
data_
;
}
break
;
case
CHARS
:
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
// the max length of CHARS is 4
for
(
int
i
=
0
;
i
<
length_
;
i
++
)
{
if
(
data_
[
i
]
==
'\0'
)
{
break
;
}
...
...
@@ -46,7 +46,7 @@ int TupleCell::compare(const TupleCell &other) const
switch
(
this
->
attr_type_
)
{
case
INTS
:
return
compare_int
(
this
->
data_
,
other
.
data_
);
case
FLOATS
:
return
compare_float
(
this
->
data_
,
other
.
data_
);
case
CHARS
:
return
compare_string
(
this
->
data_
,
other
.
data_
,
4
);
case
CHARS
:
return
compare_string
(
this
->
data_
,
this
->
length_
,
other
.
data_
,
other
.
length_
);
default:
{
LOG_WARN
(
"unsupported type: %d"
,
this
->
attr_type_
);
}
...
...
src/observer/sql/expr/tuple_cell.h
浏览文件 @
db181edb
...
...
@@ -31,6 +31,7 @@ public:
{}
void
set_type
(
AttrType
type
)
{
this
->
attr_type_
=
type
;
}
void
set_length
(
int
length
)
{
this
->
length_
=
length
;
}
void
set_data
(
char
*
data
)
{
this
->
data_
=
data
;
}
void
set_data
(
const
char
*
data
)
{
this
->
set_data
(
const_cast
<
char
*>
(
data
));
}
...
...
@@ -43,11 +44,15 @@ public:
return
data_
;
}
int
length
()
const
{
return
length_
;
}
AttrType
attr_type
()
const
{
return
attr_type_
;
}
private:
AttrType
attr_type_
=
UNDEFINED
;
int
length_
=
-
1
;
char
*
data_
=
nullptr
;
// real data. no need to move to field_meta.offset
};
src/observer/sql/operator/index_scan_operator.cpp
浏览文件 @
db181edb
...
...
@@ -36,8 +36,8 @@ RC IndexScanOperator::open()
}
IndexScanner
*
index_scanner
=
index_
->
create_scanner
(
left_cell_
.
data
(),
left_inclusive_
,
right_cell_
.
data
(),
right_inclusive_
);
IndexScanner
*
index_scanner
=
index_
->
create_scanner
(
left_cell_
.
data
(),
left_
cell_
.
length
(),
left_
inclusive_
,
right_cell_
.
data
(),
right_cell_
.
length
(),
right_inclusive_
);
if
(
nullptr
==
index_scanner
)
{
LOG_WARN
(
"failed to create index scanner"
);
return
RC
::
INTERNAL
;
...
...
src/observer/storage/common/condition_filter.h
浏览文件 @
db181edb
...
...
@@ -66,6 +66,8 @@ public:
return
comp_op_
;
}
AttrType
attr_type
()
const
{
return
attr_type_
;
}
private:
ConDesc
left_
;
ConDesc
right_
;
...
...
src/observer/storage/common/table.cpp
浏览文件 @
db181edb
...
...
@@ -326,7 +326,14 @@ RC Table::make_record(int value_num, const Value *values, char *&record_out)
for
(
int
i
=
0
;
i
<
value_num
;
i
++
)
{
const
FieldMeta
*
field
=
table_meta_
.
field
(
i
+
normal_field_start_index
);
const
Value
&
value
=
values
[
i
];
memcpy
(
record
+
field
->
offset
(),
value
.
data
,
field
->
len
());
size_t
copy_len
=
field
->
len
();
if
(
field
->
type
()
==
CHARS
)
{
const
size_t
data_len
=
strlen
((
const
char
*
)
value
.
data
);
if
(
copy_len
>
data_len
)
{
copy_len
=
data_len
+
1
;
}
}
memcpy
(
record
+
field
->
offset
(),
value
.
data
,
copy_len
);
}
record_out
=
record
;
...
...
@@ -775,6 +782,8 @@ IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
const
char
*
left_key
=
nullptr
;
const
char
*
right_key
=
nullptr
;
int
left_len
=
4
;
int
right_len
=
4
;
bool
left_inclusive
=
false
;
bool
right_inclusive
=
false
;
switch
(
filter
.
comp_op
())
{
...
...
@@ -809,7 +818,12 @@ IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
return
nullptr
;
}
}
return
index
->
create_scanner
(
left_key
,
left_inclusive
,
right_key
,
right_inclusive
);
if
(
filter
.
attr_type
()
==
CHARS
)
{
left_len
=
left_key
!=
nullptr
?
strlen
(
left_key
)
:
0
;
right_len
=
right_key
!=
nullptr
?
strlen
(
right_key
)
:
0
;
}
return
index
->
create_scanner
(
left_key
,
left_len
,
left_inclusive
,
right_key
,
right_len
,
right_inclusive
);
}
IndexScanner
*
Table
::
find_index_for_scan
(
const
ConditionFilter
*
filter
)
...
...
src/observer/storage/common/table.h
浏览文件 @
db181edb
...
...
@@ -29,6 +29,7 @@ class IndexScanner;
class
RecordDeleter
;
class
Trx
;
// TODO remove the routines with condition
class
Table
{
public:
Table
()
=
default
;
...
...
src/observer/storage/default/disk_buffer_pool.cpp
浏览文件 @
db181edb
...
...
@@ -295,6 +295,8 @@ RC DiskBufferPool::allocate_page(Frame **frame)
RC
DiskBufferPool
::
unpin_page
(
Frame
*
frame
)
{
assert
(
frame
->
pin_count_
>=
1
);
if
(
--
frame
->
pin_count_
==
0
)
{
PageNum
page_num
=
frame
->
page_num
();
auto
pages_it
=
disposed_pages
.
find
(
page_num
);
...
...
src/observer/storage/index/bplus_tree.cpp
浏览文件 @
db181edb
...
...
@@ -1443,10 +1443,10 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid)
return
RC
::
SUCCESS
;
}
RC
BplusTreeHandler
::
get_entry
(
const
char
*
user_key
,
std
::
list
<
RID
>
&
rids
)
RC
BplusTreeHandler
::
get_entry
(
const
char
*
user_key
,
int
key_len
,
std
::
list
<
RID
>
&
rids
)
{
BplusTreeScanner
scanner
(
*
this
);
RC
rc
=
scanner
.
open
(
user_key
,
true
/*left_inclusive*/
,
user_key
,
true
/*right_inclusive*/
);
RC
rc
=
scanner
.
open
(
user_key
,
key_len
,
true
/*left_inclusive*/
,
user_key
,
key_len
,
true
/*right_inclusive*/
);
if
(
rc
!=
RC
::
SUCCESS
)
{
LOG_WARN
(
"failed to open scanner. rc=%d:%s"
,
rc
,
strrc
(
rc
));
return
rc
;
...
...
@@ -1721,8 +1721,8 @@ BplusTreeScanner::~BplusTreeScanner()
close
();
}
RC
BplusTreeScanner
::
open
(
const
char
*
left_user_key
,
bool
left_inclusive
,
const
char
*
right_user_key
,
bool
right_inclusive
)
RC
BplusTreeScanner
::
open
(
const
char
*
left_user_key
,
int
left_len
,
bool
left_inclusive
,
const
char
*
right_user_key
,
int
right_len
,
bool
right_inclusive
)
{
RC
rc
=
RC
::
SUCCESS
;
if
(
inited_
)
{
...
...
@@ -1753,10 +1753,30 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
iter_index_
=
0
;
}
else
{
char
*
left_key
=
nullptr
;
if
(
left_inclusive
)
{
left_key
=
tree_handler_
.
make_key
(
left_user_key
,
*
RID
::
min
());
char
*
fixed_left_key
=
const_cast
<
char
*>
(
left_user_key
);
if
(
tree_handler_
.
file_header_
.
attr_type
==
CHARS
)
{
bool
should_inclusive_after_fix
=
false
;
rc
=
fix_user_key
(
left_user_key
,
left_len
,
true
/*greater*/
,
&
fixed_left_key
,
&
should_inclusive_after_fix
);
if
(
rc
!=
RC
::
SUCCESS
)
{
LOG_WARN
(
"failed to fix left user key. rc=%s"
,
strrc
(
rc
));
return
rc
;
}
if
(
should_inclusive_after_fix
)
{
left_inclusive
=
true
;
}
}
if
(
left_inclusive
)
{
left_key
=
tree_handler_
.
make_key
(
fixed_left_key
,
*
RID
::
min
());
}
else
{
left_key
=
tree_handler_
.
make_key
(
left_user_key
,
*
RID
::
max
());
left_key
=
tree_handler_
.
make_key
(
fixed_left_key
,
*
RID
::
max
());
}
if
(
fixed_left_key
!=
left_user_key
)
{
delete
[]
fixed_left_key
;
fixed_left_key
=
nullptr
;
}
rc
=
tree_handler_
.
find_leaf
(
left_key
,
left_frame_
);
...
...
@@ -1800,10 +1820,28 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
}
else
{
char
*
right_key
=
nullptr
;
char
*
fixed_right_key
=
const_cast
<
char
*>
(
right_user_key
);
bool
should_include_after_fix
=
false
;
if
(
tree_handler_
.
file_header_
.
attr_type
==
CHARS
)
{
rc
=
fix_user_key
(
right_user_key
,
right_len
,
false
/*want_greater*/
,
&
fixed_right_key
,
&
should_include_after_fix
);
if
(
rc
!=
RC
::
SUCCESS
)
{
LOG_WARN
(
"failed to fix right user key. rc=%s"
,
strrc
(
rc
));
return
rc
;
}
if
(
should_include_after_fix
)
{
right_inclusive
=
true
;
}
}
if
(
right_inclusive
)
{
right_key
=
tree_handler_
.
make_key
(
right_user
_key
,
*
RID
::
max
());
right_key
=
tree_handler_
.
make_key
(
fixed_right
_key
,
*
RID
::
max
());
}
else
{
right_key
=
tree_handler_
.
make_key
(
right_user_key
,
*
RID
::
min
());
right_key
=
tree_handler_
.
make_key
(
fixed_right_key
,
*
RID
::
min
());
}
if
(
fixed_right_key
!=
right_user_key
)
{
delete
[]
fixed_right_key
;
fixed_right_key
=
nullptr
;
}
rc
=
tree_handler_
.
find_leaf
(
right_key
,
right_frame_
);
...
...
@@ -1883,11 +1921,13 @@ RC BplusTreeScanner::next_entry(RID *rid)
PageNum
page_num
=
node
.
next_page
();
tree_handler_
.
disk_buffer_pool_
->
unpin_page
(
left_frame_
);
if
(
page_num
==
BP_INVALID_PAGE_NUM
)
{
left_frame_
=
nullptr
;
LOG_WARN
(
"got invalid next page. page num=%d"
,
page_num
);
rc
=
RC
::
INTERNAL
;
}
else
{
rc
=
tree_handler_
.
disk_buffer_pool_
->
get_this_page
(
page_num
,
&
left_frame_
);
if
(
rc
!=
RC
::
SUCCESS
)
{
left_frame_
=
nullptr
;
LOG_WARN
(
"failed to fetch next page. page num=%d, rc=%d:%s"
,
page_num
,
rc
,
strrc
(
rc
));
return
rc
;
}
...
...
@@ -1906,12 +1946,64 @@ RC BplusTreeScanner::close()
{
if
(
left_frame_
!=
nullptr
)
{
tree_handler_
.
disk_buffer_pool_
->
unpin_page
(
left_frame_
);
left_frame_
=
nullptr
;
}
if
(
right_frame_
!=
nullptr
)
{
tree_handler_
.
disk_buffer_pool_
->
unpin_page
(
right_frame_
);
right_frame_
=
nullptr
;
}
end_index_
=
-
1
;
inited_
=
false
;
LOG_INFO
(
"bplus tree scanner closed"
);
return
RC
::
SUCCESS
;
}
RC
BplusTreeScanner
::
fix_user_key
(
const
char
*
user_key
,
int
key_len
,
bool
want_greater
,
char
**
fixed_key
,
bool
*
should_inclusive
)
{
if
(
nullptr
==
fixed_key
||
nullptr
==
should_inclusive
)
{
return
RC
::
INVALID_ARGUMENT
;
}
// 这里很粗暴,变长字段才需要做调整,其它默认都不需要做调整
assert
(
tree_handler_
.
file_header_
.
attr_type
==
CHARS
);
assert
(
strlen
(
user_key
)
>=
static_cast
<
size_t
>
(
key_len
));
*
should_inclusive
=
false
;
int32_t
attr_length
=
tree_handler_
.
file_header_
.
attr_length
;
char
*
key_buf
=
new
(
std
::
nothrow
)
char
[
attr_length
];
if
(
nullptr
==
key_buf
)
{
return
RC
::
NOMEM
;
}
if
(
key_len
<=
attr_length
)
{
memcpy
(
key_buf
,
user_key
,
key_len
);
memset
(
key_buf
+
key_len
,
0
,
attr_length
-
key_len
);
*
fixed_key
=
key_buf
;
return
RC
::
SUCCESS
;
}
// key_len > attr_length
memcpy
(
key_buf
,
user_key
,
attr_length
);
char
c
=
user_key
[
attr_length
];
if
(
c
==
0
)
{
*
fixed_key
=
key_buf
;
return
RC
::
SUCCESS
;
}
// 扫描 >=/> user_key 的数据
// 示例:>=/> ABCD1 的数据,attr_length=4,
// 等价于扫描 >= ABCE 的数据
// 如果是扫描 <=/< user_key的数据
// 示例:<=/< ABCD1 <==> <= ABCD (attr_length=4)
*
should_inclusive
=
true
;
if
(
want_greater
)
{
key_buf
[
attr_length
-
1
]
++
;
}
*
fixed_key
=
key_buf
;
return
RC
::
SUCCESS
;
}
src/observer/storage/index/bplus_tree.h
浏览文件 @
db181edb
...
...
@@ -118,7 +118,14 @@ public:
return
std
::
to_string
(
*
(
float
*
)
v
);
}
case
CHARS
:
{
return
std
::
string
(
v
,
attr_length_
);
std
::
string
str
;
for
(
int
i
=
0
;
i
<
attr_length_
;
i
++
)
{
if
(
v
[
i
]
==
0
)
{
break
;
}
str
.
push_back
(
v
[
i
]);
}
return
str
;
}
default:
{
LOG_ERROR
(
"unknown attr type. %d"
,
attr_type_
);
...
...
@@ -400,12 +407,14 @@ public:
* 此函数向IndexHandle对应的索引中插入一个索引项。
* 参数user_key指向要插入的属性值,参数rid标识该索引项对应的元组,
* 即向索引中插入一个值为(user_key,rid)的键值对
* @note 这里假设user_key的内存大小与attr_length 一致
*/
RC
insert_entry
(
const
char
*
user_key
,
const
RID
*
rid
);
/**
* 从IndexHandle句柄对应的索引中删除一个值为(*pData,rid)的索引项
* @return RECORD_INVALID_KEY 指定值不存在
* @note 这里假设user_key的内存大小与attr_length 一致
*/
RC
delete_entry
(
const
char
*
user_key
,
const
RID
*
rid
);
...
...
@@ -413,9 +422,10 @@ public:
/**
* 获取指定值的record
* @param key_len user_key的长度
* @param rid 返回值,记录记录所在的页面号和slot
*/
RC
get_entry
(
const
char
*
user_key
,
std
::
list
<
RID
>
&
rids
);
RC
get_entry
(
const
char
*
user_key
,
int
key_len
,
std
::
list
<
RID
>
&
rids
);
RC
sync
();
...
...
@@ -493,18 +503,26 @@ public:
/**
* 扫描指定范围的数据
* @param left_key 扫描范围的左边界,如果是null,则没有左边界
* @param left_user_key 扫描范围的左边界,如果是null,则没有左边界
* @param left_len left_user_key 的内存大小(只有在变长字段中才会关注)
* @param left_inclusive 左边界的值是否包含在内
* @param right_key 扫描范围的右边界。如果是null,则没有右边界
* @param right_user_key 扫描范围的右边界。如果是null,则没有右边界
* @param right_len right_user_key 的内存大小(只有在变长字段中才会关注)
* @param right_inclusive 右边界的值是否包含在内
*/
RC
open
(
const
char
*
left_user_key
,
bool
left_inclusive
,
const
char
*
right_user_key
,
bool
right_inclusive
);
RC
open
(
const
char
*
left_user_key
,
int
left_len
,
bool
left_inclusive
,
const
char
*
right_user_key
,
int
right_len
,
bool
right_inclusive
);
RC
next_entry
(
RID
*
rid
);
RC
close
();
private:
/**
* 如果key的类型是CHARS, 扩展或缩减user_key的大小刚好是schema中定义的大小
*/
RC
fix_user_key
(
const
char
*
user_key
,
int
key_len
,
bool
want_greater
,
char
**
fixed_key
,
bool
*
should_inclusive
);
private:
bool
inited_
=
false
;
BplusTreeHandler
&
tree_handler_
;
...
...
src/observer/storage/index/bplus_tree_index.cpp
浏览文件 @
db181edb
...
...
@@ -98,11 +98,11 @@ RC BplusTreeIndex::delete_entry(const char *record, const RID *rid)
return
index_handler_
.
delete_entry
(
record
+
field_meta_
.
offset
(),
rid
);
}
IndexScanner
*
BplusTreeIndex
::
create_scanner
(
const
char
*
left_key
,
bool
left_inclusive
,
const
char
*
right_key
,
bool
right_inclusive
)
IndexScanner
*
BplusTreeIndex
::
create_scanner
(
const
char
*
left_key
,
int
left_len
,
bool
left_inclusive
,
const
char
*
right_key
,
int
right_len
,
bool
right_inclusive
)
{
BplusTreeIndexScanner
*
index_scanner
=
new
BplusTreeIndexScanner
(
index_handler_
);
RC
rc
=
index_scanner
->
open
(
left_key
,
left_
inclusive
,
right_key
,
right_inclusive
);
RC
rc
=
index_scanner
->
open
(
left_key
,
left_
len
,
left_inclusive
,
right_key
,
right_len
,
right_inclusive
);
if
(
rc
!=
RC
::
SUCCESS
)
{
LOG_WARN
(
"failed to open index scanner. rc=%d:%s"
,
rc
,
strrc
(
rc
));
delete
index_scanner
;
...
...
@@ -125,9 +125,10 @@ BplusTreeIndexScanner::~BplusTreeIndexScanner() noexcept
tree_scanner_
.
close
();
}
RC
BplusTreeIndexScanner
::
open
(
const
char
*
left_key
,
bool
left_inclusive
,
const
char
*
right_key
,
bool
right_inclusive
)
RC
BplusTreeIndexScanner
::
open
(
const
char
*
left_key
,
int
left_len
,
bool
left_inclusive
,
const
char
*
right_key
,
int
right_len
,
bool
right_inclusive
)
{
return
tree_scanner_
.
open
(
left_key
,
left_
inclusive
,
right_key
,
right_inclusive
);
return
tree_scanner_
.
open
(
left_key
,
left_
len
,
left_inclusive
,
right_key
,
right_len
,
right_inclusive
);
}
RC
BplusTreeIndexScanner
::
next_entry
(
RID
*
rid
)
...
...
src/observer/storage/index/bplus_tree_index.h
浏览文件 @
db181edb
...
...
@@ -33,8 +33,8 @@ public:
/**
* 扫描指定范围的数据
*/
IndexScanner
*
create_scanner
(
const
char
*
left_key
,
bool
left_inclusive
,
const
char
*
right_key
,
bool
right_inclusive
)
override
;
IndexScanner
*
create_scanner
(
const
char
*
left_key
,
int
left_len
,
bool
left_inclusive
,
const
char
*
right_key
,
int
right_len
,
bool
right_inclusive
)
override
;
RC
sync
()
override
;
...
...
@@ -51,7 +51,8 @@ public:
RC
next_entry
(
RID
*
rid
)
override
;
RC
destroy
()
override
;
RC
open
(
const
char
*
left_key
,
bool
left_inclusive
,
const
char
*
right_key
,
bool
right_inclusive
);
RC
open
(
const
char
*
left_key
,
int
left_len
,
bool
left_inclusive
,
const
char
*
right_key
,
int
right_len
,
bool
right_inclusive
);
private:
BplusTreeScanner
tree_scanner_
;
};
...
...
src/observer/storage/index/index.h
浏览文件 @
db181edb
...
...
@@ -46,8 +46,8 @@ public:
virtual
RC
insert_entry
(
const
char
*
record
,
const
RID
*
rid
)
=
0
;
virtual
RC
delete_entry
(
const
char
*
record
,
const
RID
*
rid
)
=
0
;
virtual
IndexScanner
*
create_scanner
(
const
char
*
left_key
,
bool
left_inclusive
,
const
char
*
right_key
,
bool
right_inclusive
)
=
0
;
virtual
IndexScanner
*
create_scanner
(
const
char
*
left_key
,
int
left_len
,
bool
left_inclusive
,
const
char
*
right_key
,
int
right_len
,
bool
right_inclusive
)
=
0
;
virtual
RC
sync
()
=
0
;
...
...
src/observer/util/comparator.cpp
浏览文件 @
db181edb
...
...
@@ -13,6 +13,7 @@ See the Mulan PSL v2 for more details. */
//
#include <string.h>
#include <algorithm>
const
double
epsilon
=
1E-6
;
...
...
@@ -37,9 +38,22 @@ int compare_float(void *arg1, void *arg2)
return
0
;
}
int
compare_string
(
void
*
arg1
,
void
*
arg2
,
int
maxlen
)
int
compare_string
(
void
*
arg1
,
int
arg1_max_length
,
void
*
arg2
,
int
arg2_max_length
)
{
const
char
*
s1
=
(
const
char
*
)
arg1
;
const
char
*
s2
=
(
const
char
*
)
arg2
;
return
strncmp
(
s1
,
s2
,
maxlen
);
int
maxlen
=
std
::
min
(
arg1_max_length
,
arg2_max_length
);
int
result
=
strncmp
(
s1
,
s2
,
maxlen
);
if
(
0
!=
result
)
{
return
result
;
}
if
(
arg1_max_length
>
maxlen
)
{
return
s1
[
maxlen
]
-
0
;
}
if
(
arg2_max_length
>
maxlen
)
{
return
0
-
s2
[
maxlen
];
}
return
0
;
}
src/observer/util/comparator.h
浏览文件 @
db181edb
...
...
@@ -16,4 +16,4 @@ See the Mulan PSL v2 for more details. */
int
compare_int
(
void
*
arg1
,
void
*
arg2
);
int
compare_float
(
void
*
arg1
,
void
*
arg2
);
int
compare_string
(
void
*
arg1
,
void
*
arg2
,
int
max_length
);
int
compare_string
(
void
*
arg1
,
int
arg1_max_length
,
void
*
arg2
,
int
arg2_
max_length
);
unitest/bplus_tree_test.cpp
浏览文件 @
db181edb
...
...
@@ -31,6 +31,7 @@ using namespace common;
#define INSERT_NUM (TIMES * ORDER * ORDER * ORDER * ORDER)
#define POOL_NUM 2
BufferPoolManager
bpm
;
BplusTreeHandler
*
handler
=
nullptr
;
const
char
*
index_name
=
"test.btree"
;
int
insert_num
=
INSERT_NUM
;
...
...
@@ -38,6 +39,12 @@ const int page_size = 1024;
RID
rid
,
check_rid
;
int
k
=
0
;
void
init_bpm
()
{
if
(
&
BufferPoolManager
::
instance
()
==
nullptr
)
{
BufferPoolManager
::
set_instance
(
&
bpm
);
}
}
void
test_insert
()
{
RC
rc
=
RC
::
SUCCESS
;
...
...
@@ -148,7 +155,7 @@ void test_get()
}
rids
.
clear
();
RC
rc
=
handler
->
get_entry
((
const
char
*
)
&
i
,
rids
);
RC
rc
=
handler
->
get_entry
((
const
char
*
)
&
i
,
4
,
rids
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
ASSERT_EQ
(
1
,
rids
.
size
());
...
...
@@ -221,7 +228,7 @@ void test_delete()
LOG_INFO
(
"Begin to get entry of index, i=%d, rid: %s"
,
i
,
rid
.
to_string
().
c_str
());
}
rids
.
clear
();
rc
=
handler
->
get_entry
((
const
char
*
)
&
i
,
rids
);
rc
=
handler
->
get_entry
((
const
char
*
)
&
i
,
4
,
rids
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
int
t
=
i
%
TIMES
;
if
(
t
==
0
||
t
==
1
)
{
...
...
@@ -458,6 +465,50 @@ TEST(test_bplus_tree, test_internal_index_node_handle)
ASSERT_EQ
(
i
,
index
);
}
}
TEST
(
test_bplus_tree
,
test_chars
)
{
LoggerFactory
::
init_default
(
"test_chars.log"
);
const
char
*
index_name
=
"chars.btree"
;
::
remove
(
index_name
);
handler
=
new
BplusTreeHandler
();
handler
->
create
(
index_name
,
CHARS
,
8
,
ORDER
,
ORDER
);
char
keys
[][
9
]
=
{
"abcdefg"
,
"12345678"
,
"12345678"
,
"abcdefg"
,
"abcdefga"
};
RID
rid
;
RC
rc
=
RC
::
SUCCESS
;
for
(
size_t
i
=
0
;
i
<
sizeof
(
keys
)
/
sizeof
(
keys
[
0
]);
i
++
)
{
rid
.
page_num
=
0
;
rid
.
slot_num
=
i
;
rc
=
handler
->
insert_entry
(
keys
[
i
],
&
rid
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
}
LOG_INFO
(
"begin to print bplus tree of chars"
);
handler
->
print_tree
();
LOG_INFO
(
"end to print bplus tree of chars"
);
BplusTreeScanner
scanner
(
*
handler
);
const
char
*
key
=
"abcdefg"
;
rc
=
scanner
.
open
(
key
,
strlen
(
key
),
true
,
key
,
strlen
(
key
),
true
);
ASSERT_EQ
(
rc
,
RC
::
SUCCESS
);
int
count
=
0
;
while
(
RC
::
SUCCESS
==
(
rc
=
scanner
.
next_entry
(
&
rid
)))
{
count
++
;
}
scanner
.
close
();
ASSERT_EQ
(
2
,
count
);
}
TEST
(
test_bplus_tree
,
test_scanner
)
{
LoggerFactory
::
init_default
(
"test.log"
);
...
...
@@ -484,7 +535,7 @@ TEST(test_bplus_tree, test_scanner)
int
begin
=
-
100
;
int
end
=
-
20
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
false
,
(
const
char
*
)
&
end
,
false
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
false
,
(
const
char
*
)
&
end
,
4
,
false
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
rc
=
scanner
.
next_entry
(
&
rid
);
...
...
@@ -494,7 +545,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
-
100
;
end
=
1
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
false
,
(
const
char
*
)
&
end
,
false
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
false
,
(
const
char
*
)
&
end
,
4
,
false
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
rc
=
scanner
.
next_entry
(
&
rid
);
ASSERT_EQ
(
RC
::
RECORD_EOF
,
rc
);
...
...
@@ -503,7 +554,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
-
100
;
end
=
1
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
false
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
false
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
rc
=
scanner
.
next_entry
(
&
rid
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
...
...
@@ -514,7 +565,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
1
;
end
=
3
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
false
,
(
const
char
*
)
&
end
,
false
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
false
,
(
const
char
*
)
&
end
,
4
,
false
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
rc
=
scanner
.
next_entry
(
&
rid
);
ASSERT_EQ
(
RC
::
RECORD_EOF
,
rc
);
...
...
@@ -523,7 +574,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
1
;
end
=
3
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
count
++
;
...
...
@@ -535,7 +586,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
0
;
end
=
3
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -548,7 +599,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
11
;
end
=
21
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -561,7 +612,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
11
;
end
=
91
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -574,7 +625,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
191
;
end
=
199
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -587,7 +638,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
191
;
end
=
201
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -600,7 +651,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
200
;
end
=
301
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
rc
=
scanner
.
next_entry
(
&
rid
);
ASSERT_EQ
(
RC
::
RECORD_EOF
,
rc
);
...
...
@@ -609,14 +660,14 @@ TEST(test_bplus_tree, test_scanner)
begin
=
300
;
end
=
201
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
INVALID_ARGUMENT
,
rc
);
scanner
.
close
();
begin
=
300
;
end
=
201
;
rc
=
scanner
.
open
(
nullptr
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
(
nullptr
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -629,7 +680,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
300
;
end
=
10
;
rc
=
scanner
.
open
(
nullptr
,
true
,
(
const
char
*
)
&
end
,
true
/*inclusive*/
);
rc
=
scanner
.
open
(
nullptr
,
4
,
true
,
(
const
char
*
)
&
end
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -642,7 +693,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
190
;
end
=
10
;
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
true
,
nullptr
,
true
/*inclusive*/
);
rc
=
scanner
.
open
((
const
char
*
)
&
begin
,
4
,
true
,
nullptr
,
4
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -655,7 +706,7 @@ TEST(test_bplus_tree, test_scanner)
begin
=
190
;
end
=
10
;
rc
=
scanner
.
open
(
nullptr
,
true
,
nullptr
,
true
/*inclusive*/
);
rc
=
scanner
.
open
(
nullptr
,
0
,
true
,
nullptr
,
0
,
true
/*inclusive*/
);
ASSERT_EQ
(
RC
::
SUCCESS
,
rc
);
count
=
0
;
while
((
rc
=
scanner
.
next_entry
(
&
rid
))
==
RC
::
SUCCESS
)
{
...
...
@@ -695,6 +746,7 @@ int main(int argc, char **argv)
// 调用RUN_ALL_TESTS()运行所有测试用例
// main函数返回RUN_ALL_TESTS()的运行结果
init_bpm
();
int
rc
=
RUN_ALL_TESTS
();
return
rc
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录