diff --git a/src/observer/sql/expr/expression.h b/src/observer/sql/expr/expression.h index c586bf2d2193d0c7c439dff6f2dea93481ccebca..59b1750d8173c7950ec6aa59084fe7bec9e5c3fc 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 07c33c793e17a61f9f2cd4bb1cf01ca90fc7f06c..7efed51faf976edab5419b983b6107732d5c6708 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 9ccd3d393cb27aa0df6923d1b33df298216baf29..c878b31c632307da84b4bf3c28a0ff843d9f65fc 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 89170f2ed28d17b325889a8bcf05aa5c85b6e9a6..faf39964c07549817c043aaa97c02146d91b67ac 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 1be1a3723a8cc48d6f7765022d7994fb7c038e9d..2aad13be19ab13d6068be1b765ce90d27478b09a 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 890195af05b586daafeaed3c7a0edb35b49f5f7f..e4b7f98fceb7682903d415535cdf951216904825 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 7ff43cab5cc255c2aa937b7805a392a3553a1d9f..f53be21701492c6603fef6ffc600187e02481364 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 a185535be223653dae5735bc50202fae1d12968f..707553724fd7a14b9dc157a87ad92e989be0649a 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 e3953aee84d496ccaa929345db651ebf53eb3862..18a24508acb486e2aa9b9d2c5d0dea977bb63a20 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 50e49f19ecca7e1b78c357025a2558a41bc3758d..0e7a62d68cf3eb69273195fdee001b972ea30935 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 91d9d483fbf13598f147dc36349e79ce3144e90d..7a09b1b25e5ef49a72864371aa5c9f62649958a4 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 ea69bcc0746872317ef583b05d3d1b707a5ccbb7..cbaef5cdefc04aaa253c69763f3bd0e03bf62e81 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 1c3ff920f9269c320660621a24ccd934984033dc..c2e66f18227d9f4378287bb2b649a2dd805b7623 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 d66a09327de2559047fa510db59e143d1a7cca4b..4f04fb4d3c2bf5d96409c670f11ff48ee98c66d8 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 f7e6a8ee44735f196a59b13897203ff03dcd2b7b..1c8615fdc34e8e87876b6459ae5d3922ba66cacf 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 c80e9f2237c6fb9a90602a0176f09587d819db86..18ab99fddd08874d6e59d9b615501b4be78fcd13 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 5fa48fd2c90c4cf43a54f98eec9b11cfa3392795..dabfe08ee6d5815955b97560c94ce56dad5177b6 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;