diff --git a/1.patch b/1.patch deleted file mode 100644 index 5eb5986fd0a2f0c958df3f5cd0848d579998e598..0000000000000000000000000000000000000000 --- a/1.patch +++ /dev/null @@ -1,797 +0,0 @@ -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 - #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(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 &rids) -+RC BplusTreeHandler::get_entry(const char *user_key, int key_len, std::list &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(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(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(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 &rids); -+ RC get_entry(const char *user_key, int key_len, std::list &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 -+#include - - 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;