未验证 提交 9446aba8 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

Merge pull request #48 from hnwyllmm/main

fix var len char
...@@ -14,6 +14,7 @@ See the Mulan PSL v2 for more details. */ ...@@ -14,6 +14,7 @@ See the Mulan PSL v2 for more details. */
#pragma once #pragma once
#include <string.h>
#include "storage/common/field.h" #include "storage/common/field.h"
#include "sql/expr/tuple_cell.h" #include "sql/expr/tuple_cell.h"
...@@ -79,7 +80,11 @@ class ValueExpr : public Expression ...@@ -79,7 +80,11 @@ class ValueExpr : public Expression
public: public:
ValueExpr() = default; ValueExpr() = default;
ValueExpr(const Value &value) : tuple_cell_(value.type, (char *)value.data) 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; virtual ~ValueExpr() = default;
......
...@@ -115,6 +115,7 @@ public: ...@@ -115,6 +115,7 @@ public:
const FieldMeta *field_meta = field_expr->field().meta(); const FieldMeta *field_meta = field_expr->field().meta();
cell.set_type(field_meta->type()); cell.set_type(field_meta->type());
cell.set_data(this->record_->data() + field_meta->offset()); cell.set_data(this->record_->data() + field_meta->offset());
cell.set_length(field_meta->len());
return RC::SUCCESS; return RC::SUCCESS;
} }
......
...@@ -27,7 +27,7 @@ void TupleCell::to_string(std::ostream &os) const ...@@ -27,7 +27,7 @@ void TupleCell::to_string(std::ostream &os) const
os << *(float *)data_; os << *(float *)data_;
} break; } break;
case CHARS: { 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') { if (data_[i] == '\0') {
break; break;
} }
...@@ -46,7 +46,7 @@ int TupleCell::compare(const TupleCell &other) const ...@@ -46,7 +46,7 @@ int TupleCell::compare(const TupleCell &other) const
switch (this->attr_type_) { switch (this->attr_type_) {
case INTS: return compare_int(this->data_, other.data_); case INTS: return compare_int(this->data_, other.data_);
case FLOATS: return compare_float(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: { default: {
LOG_WARN("unsupported type: %d", this->attr_type_); LOG_WARN("unsupported type: %d", this->attr_type_);
} }
......
...@@ -31,6 +31,7 @@ public: ...@@ -31,6 +31,7 @@ public:
{} {}
void set_type(AttrType type) { this->attr_type_ = type; } 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(char *data) { this->data_ = data; }
void set_data(const char *data) { this->set_data(const_cast<char *>(data)); } void set_data(const char *data) { this->set_data(const_cast<char *>(data)); }
...@@ -43,11 +44,15 @@ public: ...@@ -43,11 +44,15 @@ public:
return data_; return data_;
} }
int length() const { return length_; }
AttrType attr_type() const AttrType attr_type() const
{ {
return attr_type_; return attr_type_;
} }
private: private:
AttrType attr_type_ = UNDEFINED; AttrType attr_type_ = UNDEFINED;
int length_ = -1;
char *data_ = nullptr; // real data. no need to move to field_meta.offset char *data_ = nullptr; // real data. no need to move to field_meta.offset
}; };
...@@ -36,8 +36,8 @@ RC IndexScanOperator::open() ...@@ -36,8 +36,8 @@ RC IndexScanOperator::open()
} }
IndexScanner *index_scanner = index_->create_scanner(left_cell_.data(), left_inclusive_, IndexScanner *index_scanner = index_->create_scanner(left_cell_.data(), left_cell_.length(), left_inclusive_,
right_cell_.data(), right_inclusive_); right_cell_.data(), right_cell_.length(), right_inclusive_);
if (nullptr == index_scanner) { if (nullptr == index_scanner) {
LOG_WARN("failed to create index scanner"); LOG_WARN("failed to create index scanner");
return RC::INTERNAL; return RC::INTERNAL;
......
...@@ -66,6 +66,8 @@ public: ...@@ -66,6 +66,8 @@ public:
return comp_op_; return comp_op_;
} }
AttrType attr_type() const { return attr_type_; }
private: private:
ConDesc left_; ConDesc left_;
ConDesc right_; ConDesc right_;
......
...@@ -326,7 +326,14 @@ RC Table::make_record(int value_num, const Value *values, char *&record_out) ...@@ -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++) { for (int i = 0; i < value_num; i++) {
const FieldMeta *field = table_meta_.field(i + normal_field_start_index); const FieldMeta *field = table_meta_.field(i + normal_field_start_index);
const Value &value = values[i]; 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; record_out = record;
...@@ -775,6 +782,8 @@ IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter) ...@@ -775,6 +782,8 @@ IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
const char *left_key = nullptr; const char *left_key = nullptr;
const char *right_key = nullptr; const char *right_key = nullptr;
int left_len = 4;
int right_len = 4;
bool left_inclusive = false; bool left_inclusive = false;
bool right_inclusive = false; bool right_inclusive = false;
switch (filter.comp_op()) { switch (filter.comp_op()) {
...@@ -809,7 +818,12 @@ IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter) ...@@ -809,7 +818,12 @@ IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
return nullptr; 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) IndexScanner *Table::find_index_for_scan(const ConditionFilter *filter)
......
...@@ -29,6 +29,7 @@ class IndexScanner; ...@@ -29,6 +29,7 @@ class IndexScanner;
class RecordDeleter; class RecordDeleter;
class Trx; class Trx;
// TODO remove the routines with condition
class Table { class Table {
public: public:
Table() = default; Table() = default;
......
...@@ -295,6 +295,8 @@ RC DiskBufferPool::allocate_page(Frame **frame) ...@@ -295,6 +295,8 @@ RC DiskBufferPool::allocate_page(Frame **frame)
RC DiskBufferPool::unpin_page(Frame *frame) RC DiskBufferPool::unpin_page(Frame *frame)
{ {
assert(frame->pin_count_ >= 1);
if (--frame->pin_count_ == 0) { if (--frame->pin_count_ == 0) {
PageNum page_num = frame->page_num(); PageNum page_num = frame->page_num();
auto pages_it = disposed_pages.find(page_num); auto pages_it = disposed_pages.find(page_num);
......
...@@ -1443,10 +1443,10 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid) ...@@ -1443,10 +1443,10 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid)
return RC::SUCCESS; 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); 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) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to open scanner. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to open scanner. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
...@@ -1721,8 +1721,8 @@ BplusTreeScanner::~BplusTreeScanner() ...@@ -1721,8 +1721,8 @@ BplusTreeScanner::~BplusTreeScanner()
close(); close();
} }
RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, RC BplusTreeScanner::open(const char *left_user_key, int left_len, bool left_inclusive,
const char *right_user_key, bool right_inclusive) const char *right_user_key, int right_len, bool right_inclusive)
{ {
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
if (inited_) { if (inited_) {
...@@ -1753,10 +1753,30 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1753,10 +1753,30 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
iter_index_ = 0; iter_index_ = 0;
} else { } else {
char *left_key = nullptr; 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 { } 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_); rc = tree_handler_.find_leaf(left_key, left_frame_);
...@@ -1800,10 +1820,28 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1800,10 +1820,28 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
} else { } else {
char *right_key = nullptr; 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) { 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 { } 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_); rc = tree_handler_.find_leaf(right_key, right_frame_);
...@@ -1883,11 +1921,13 @@ RC BplusTreeScanner::next_entry(RID *rid) ...@@ -1883,11 +1921,13 @@ RC BplusTreeScanner::next_entry(RID *rid)
PageNum page_num = node.next_page(); PageNum page_num = node.next_page();
tree_handler_.disk_buffer_pool_->unpin_page(left_frame_); tree_handler_.disk_buffer_pool_->unpin_page(left_frame_);
if (page_num == BP_INVALID_PAGE_NUM) { if (page_num == BP_INVALID_PAGE_NUM) {
left_frame_ = nullptr;
LOG_WARN("got invalid next page. page num=%d", page_num); LOG_WARN("got invalid next page. page num=%d", page_num);
rc = RC::INTERNAL; rc = RC::INTERNAL;
} else { } else {
rc = tree_handler_.disk_buffer_pool_->get_this_page(page_num, &left_frame_); rc = tree_handler_.disk_buffer_pool_->get_this_page(page_num, &left_frame_);
if (rc != RC::SUCCESS) { 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)); LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", page_num, rc, strrc(rc));
return rc; return rc;
} }
...@@ -1906,12 +1946,64 @@ RC BplusTreeScanner::close() ...@@ -1906,12 +1946,64 @@ RC BplusTreeScanner::close()
{ {
if (left_frame_ != nullptr) { if (left_frame_ != nullptr) {
tree_handler_.disk_buffer_pool_->unpin_page(left_frame_); tree_handler_.disk_buffer_pool_->unpin_page(left_frame_);
left_frame_ = nullptr;
} }
if (right_frame_ != nullptr) { if (right_frame_ != nullptr) {
tree_handler_.disk_buffer_pool_->unpin_page(right_frame_); tree_handler_.disk_buffer_pool_->unpin_page(right_frame_);
right_frame_ = nullptr;
} }
end_index_ = -1; end_index_ = -1;
inited_ = false; inited_ = false;
LOG_INFO("bplus tree scanner closed"); LOG_INFO("bplus tree scanner closed");
return RC::SUCCESS; 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;
}
...@@ -118,7 +118,14 @@ public: ...@@ -118,7 +118,14 @@ public:
return std::to_string(*(float*)v); return std::to_string(*(float*)v);
} }
case CHARS: { 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:{ default:{
LOG_ERROR("unknown attr type. %d", attr_type_); LOG_ERROR("unknown attr type. %d", attr_type_);
...@@ -400,12 +407,14 @@ public: ...@@ -400,12 +407,14 @@ public:
* 此函数向IndexHandle对应的索引中插入一个索引项。 * 此函数向IndexHandle对应的索引中插入一个索引项。
* 参数user_key指向要插入的属性值,参数rid标识该索引项对应的元组, * 参数user_key指向要插入的属性值,参数rid标识该索引项对应的元组,
* 即向索引中插入一个值为(user_key,rid)的键值对 * 即向索引中插入一个值为(user_key,rid)的键值对
* @note 这里假设user_key的内存大小与attr_length 一致
*/ */
RC insert_entry(const char *user_key, const RID *rid); RC insert_entry(const char *user_key, const RID *rid);
/** /**
* 从IndexHandle句柄对应的索引中删除一个值为(*pData,rid)的索引项 * 从IndexHandle句柄对应的索引中删除一个值为(*pData,rid)的索引项
* @return RECORD_INVALID_KEY 指定值不存在 * @return RECORD_INVALID_KEY 指定值不存在
* @note 这里假设user_key的内存大小与attr_length 一致
*/ */
RC delete_entry(const char *user_key, const RID *rid); RC delete_entry(const char *user_key, const RID *rid);
...@@ -413,9 +422,10 @@ public: ...@@ -413,9 +422,10 @@ public:
/** /**
* 获取指定值的record * 获取指定值的record
* @param key_len user_key的长度
* @param rid 返回值,记录记录所在的页面号和slot * @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(); RC sync();
...@@ -493,18 +503,26 @@ public: ...@@ -493,18 +503,26 @@ public:
/** /**
* 扫描指定范围的数据 * 扫描指定范围的数据
* @param left_key 扫描范围的左边界,如果是null,则没有左边界 * @param left_user_key 扫描范围的左边界,如果是null,则没有左边界
* @param left_len left_user_key 的内存大小(只有在变长字段中才会关注)
* @param left_inclusive 左边界的值是否包含在内 * @param left_inclusive 左边界的值是否包含在内
* @param right_key 扫描范围的右边界。如果是null,则没有右边界 * @param right_user_key 扫描范围的右边界。如果是null,则没有右边界
* @param right_len right_user_key 的内存大小(只有在变长字段中才会关注)
* @param right_inclusive 右边界的值是否包含在内 * @param right_inclusive 右边界的值是否包含在内
*/ */
RC open(const char *left_user_key, bool left_inclusive, RC open(const char *left_user_key, int left_len, bool left_inclusive,
const char *right_user_key, bool right_inclusive); const char *right_user_key, int right_len, bool right_inclusive);
RC next_entry(RID *rid); RC next_entry(RID *rid);
RC close(); 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: private:
bool inited_ = false; bool inited_ = false;
BplusTreeHandler &tree_handler_; BplusTreeHandler &tree_handler_;
......
...@@ -98,11 +98,11 @@ RC BplusTreeIndex::delete_entry(const char *record, const RID *rid) ...@@ -98,11 +98,11 @@ RC BplusTreeIndex::delete_entry(const char *record, const RID *rid)
return index_handler_.delete_entry(record + field_meta_.offset(), rid); return index_handler_.delete_entry(record + field_meta_.offset(), rid);
} }
IndexScanner *BplusTreeIndex::create_scanner(const char *left_key, bool left_inclusive, IndexScanner *BplusTreeIndex::create_scanner(const char *left_key, int left_len, bool left_inclusive,
const char *right_key, bool right_inclusive) const char *right_key, int right_len, bool right_inclusive)
{ {
BplusTreeIndexScanner *index_scanner = new BplusTreeIndexScanner(index_handler_); 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) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to open index scanner. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to open index scanner. rc=%d:%s", rc, strrc(rc));
delete index_scanner; delete index_scanner;
...@@ -125,9 +125,10 @@ BplusTreeIndexScanner::~BplusTreeIndexScanner() noexcept ...@@ -125,9 +125,10 @@ BplusTreeIndexScanner::~BplusTreeIndexScanner() noexcept
tree_scanner_.close(); 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) RC BplusTreeIndexScanner::next_entry(RID *rid)
......
...@@ -33,8 +33,8 @@ public: ...@@ -33,8 +33,8 @@ public:
/** /**
* 扫描指定范围的数据 * 扫描指定范围的数据
*/ */
IndexScanner *create_scanner(const char *left_key, bool left_inclusive, IndexScanner *create_scanner(const char *left_key, int left_len, bool left_inclusive,
const char *right_key, bool right_inclusive) override; const char *right_key, int right_len, bool right_inclusive) override;
RC sync() override; RC sync() override;
...@@ -51,7 +51,8 @@ public: ...@@ -51,7 +51,8 @@ public:
RC next_entry(RID *rid) override; RC next_entry(RID *rid) override;
RC destroy() 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: private:
BplusTreeScanner tree_scanner_; BplusTreeScanner tree_scanner_;
}; };
......
...@@ -46,8 +46,8 @@ public: ...@@ -46,8 +46,8 @@ public:
virtual RC insert_entry(const char *record, const RID *rid) = 0; virtual RC insert_entry(const char *record, const RID *rid) = 0;
virtual RC delete_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, virtual IndexScanner *create_scanner(const char *left_key, int left_len, bool left_inclusive,
const char *right_key, bool right_inclusive) = 0; const char *right_key, int right_len, bool right_inclusive) = 0;
virtual RC sync() = 0; virtual RC sync() = 0;
......
...@@ -13,6 +13,7 @@ See the Mulan PSL v2 for more details. */ ...@@ -13,6 +13,7 @@ See the Mulan PSL v2 for more details. */
// //
#include <string.h> #include <string.h>
#include <algorithm>
const double epsilon = 1E-6; const double epsilon = 1E-6;
...@@ -37,9 +38,22 @@ int compare_float(void *arg1, void *arg2) ...@@ -37,9 +38,22 @@ int compare_float(void *arg1, void *arg2)
return 0; 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 *s1 = (const char *)arg1;
const char *s2 = (const char *)arg2; 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;
} }
...@@ -16,4 +16,4 @@ See the Mulan PSL v2 for more details. */ ...@@ -16,4 +16,4 @@ See the Mulan PSL v2 for more details. */
int compare_int(void *arg1, void *arg2); int compare_int(void *arg1, void *arg2);
int compare_float(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);
...@@ -31,6 +31,7 @@ using namespace common; ...@@ -31,6 +31,7 @@ using namespace common;
#define INSERT_NUM (TIMES * ORDER * ORDER * ORDER * ORDER) #define INSERT_NUM (TIMES * ORDER * ORDER * ORDER * ORDER)
#define POOL_NUM 2 #define POOL_NUM 2
BufferPoolManager bpm;
BplusTreeHandler *handler = nullptr; BplusTreeHandler *handler = nullptr;
const char *index_name = "test.btree"; const char *index_name = "test.btree";
int insert_num = INSERT_NUM; int insert_num = INSERT_NUM;
...@@ -38,6 +39,12 @@ const int page_size = 1024; ...@@ -38,6 +39,12 @@ const int page_size = 1024;
RID rid, check_rid; RID rid, check_rid;
int k = 0; int k = 0;
void init_bpm()
{
if (&BufferPoolManager::instance() == nullptr) {
BufferPoolManager::set_instance(&bpm);
}
}
void test_insert() void test_insert()
{ {
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
...@@ -148,7 +155,7 @@ void test_get() ...@@ -148,7 +155,7 @@ void test_get()
} }
rids.clear(); 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(RC::SUCCESS, rc);
ASSERT_EQ(1, rids.size()); ASSERT_EQ(1, rids.size());
...@@ -221,7 +228,7 @@ void test_delete() ...@@ -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()); LOG_INFO("Begin to get entry of index, i=%d, rid: %s", i, rid.to_string().c_str());
} }
rids.clear(); rids.clear();
rc = handler->get_entry((const char *)&i, rids); rc = handler->get_entry((const char *)&i, 4, rids);
ASSERT_EQ(RC::SUCCESS, rc); ASSERT_EQ(RC::SUCCESS, rc);
int t = i % TIMES; int t = i % TIMES;
if (t == 0 || t == 1) { if (t == 0 || t == 1) {
...@@ -458,6 +465,50 @@ TEST(test_bplus_tree, test_internal_index_node_handle) ...@@ -458,6 +465,50 @@ TEST(test_bplus_tree, test_internal_index_node_handle)
ASSERT_EQ(i, index); 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) TEST(test_bplus_tree, test_scanner)
{ {
LoggerFactory::init_default("test.log"); LoggerFactory::init_default("test.log");
...@@ -484,7 +535,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -484,7 +535,7 @@ TEST(test_bplus_tree, test_scanner)
int begin = -100; int begin = -100;
int end = -20; 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); ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid); rc = scanner.next_entry(&rid);
...@@ -494,7 +545,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -494,7 +545,7 @@ TEST(test_bplus_tree, test_scanner)
begin = -100; begin = -100;
end = 1; 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); ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid); rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::RECORD_EOF, rc); ASSERT_EQ(RC::RECORD_EOF, rc);
...@@ -503,7 +554,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -503,7 +554,7 @@ TEST(test_bplus_tree, test_scanner)
begin = -100; begin = -100;
end = 1; 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); ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid); rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::SUCCESS, rc); ASSERT_EQ(RC::SUCCESS, rc);
...@@ -514,7 +565,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -514,7 +565,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 1; begin = 1;
end = 3; 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); ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid); rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::RECORD_EOF, rc); ASSERT_EQ(RC::RECORD_EOF, rc);
...@@ -523,7 +574,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -523,7 +574,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 1; begin = 1;
end = 3; 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); ASSERT_EQ(RC::SUCCESS, rc);
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
count++; count++;
...@@ -535,7 +586,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -535,7 +586,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 0; begin = 0;
end = 3; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -548,7 +599,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -548,7 +599,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 11; begin = 11;
end = 21; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -561,7 +612,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -561,7 +612,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 11; begin = 11;
end = 91; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -574,7 +625,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -574,7 +625,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 191; begin = 191;
end = 199; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -587,7 +638,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -587,7 +638,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 191; begin = 191;
end = 201; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -600,7 +651,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -600,7 +651,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 200; begin = 200;
end = 301; 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); ASSERT_EQ(RC::SUCCESS, rc);
rc = scanner.next_entry(&rid); rc = scanner.next_entry(&rid);
ASSERT_EQ(RC::RECORD_EOF, rc); ASSERT_EQ(RC::RECORD_EOF, rc);
...@@ -609,14 +660,14 @@ TEST(test_bplus_tree, test_scanner) ...@@ -609,14 +660,14 @@ TEST(test_bplus_tree, test_scanner)
begin = 300; begin = 300;
end = 201; 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); ASSERT_EQ(RC::INVALID_ARGUMENT, rc);
scanner.close(); scanner.close();
begin = 300; begin = 300;
end = 201; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -629,7 +680,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -629,7 +680,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 300; begin = 300;
end = 10; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -642,7 +693,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -642,7 +693,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 190; begin = 190;
end = 10; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -655,7 +706,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -655,7 +706,7 @@ TEST(test_bplus_tree, test_scanner)
begin = 190; begin = 190;
end = 10; 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); ASSERT_EQ(RC::SUCCESS, rc);
count = 0; count = 0;
while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) { while ((rc = scanner.next_entry(&rid)) == RC::SUCCESS) {
...@@ -695,6 +746,7 @@ int main(int argc, char **argv) ...@@ -695,6 +746,7 @@ int main(int argc, char **argv)
// 调用RUN_ALL_TESTS()运行所有测试用例 // 调用RUN_ALL_TESTS()运行所有测试用例
// main函数返回RUN_ALL_TESTS()的运行结果 // main函数返回RUN_ALL_TESTS()的运行结果
init_bpm();
int rc = RUN_ALL_TESTS(); int rc = RUN_ALL_TESTS();
return rc; return rc;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册