diff --git a/src/server/include/storage_engine/recorder/record_manager.h b/src/server/include/storage_engine/recorder/record_manager.h index 2dcc994..07bb03f 100644 --- a/src/server/include/storage_engine/recorder/record_manager.h +++ b/src/server/include/storage_engine/recorder/record_manager.h @@ -3,6 +3,7 @@ #include "include/storage_engine/buffer/buffer_pool.h" #include "include/storage_engine/recorder/record.h" #include "include/storage_engine/recorder/condition_filter.h" +#include "include/query_engine/structor/expression/expression.h" #include "common/lang/bitmap.h" class ConditionFilter; @@ -323,6 +324,7 @@ class RecordFileScanner * @param condition_filter 做一些初步过滤操作 */ RC open_scan(Table *table, FileBufferPool &buffer_pool, Trx *trx, bool readonly, ConditionFilter *condition_filter); + RC open_scan(Table *table, FileBufferPool &buffer_pool, Trx *trx, bool readonly, std::vector> predicate_exprs); /** * @brief 关闭一个文件扫描,释放相应的资源 @@ -367,4 +369,6 @@ class RecordFileScanner RecordPageHandler record_page_handler_; // 处理文件某页面的记录 RecordPageIterator record_page_iterator_; // 遍历某个页面上的所有record Record next_record_; // 获取的记录放在这里缓存起来 + std::vector> predicates_; // 过滤的谓词 + }; \ No newline at end of file diff --git a/src/server/include/storage_engine/recorder/table.h b/src/server/include/storage_engine/recorder/table.h index a79e13b..5e00adc 100644 --- a/src/server/include/storage_engine/recorder/table.h +++ b/src/server/include/storage_engine/recorder/table.h @@ -90,6 +90,8 @@ class Table RC get_record_scanner(RecordFileScanner &scanner, Trx *trx, bool readonly); + RC get_record_scanner(RecordFileScanner &scanner, Trx *trx, bool readonly, std::vector> predicate_exprs); + RecordFileHandler *record_handler() const { return record_handler_; diff --git a/src/server/query_engine/planner/operator/table_scan_physical_operator.cpp b/src/server/query_engine/planner/operator/table_scan_physical_operator.cpp index c6150e8..d16722b 100644 --- a/src/server/query_engine/planner/operator/table_scan_physical_operator.cpp +++ b/src/server/query_engine/planner/operator/table_scan_physical_operator.cpp @@ -5,7 +5,8 @@ using namespace std; RC TableScanPhysicalOperator::open(Trx *trx) { - RC rc = table_->get_record_scanner(record_scanner_, trx, readonly_); + // 将predicates_传下去,让record_scanner_做过滤 + RC rc = table_->get_record_scanner(record_scanner_, trx, readonly_,std::move(predicates_)); if (rc == RC::SUCCESS) { tuple_.set_schema(table_, table_alias_, table_->table_meta().field_metas()); } diff --git a/src/server/storage_engine/recorder/record_manager.cpp b/src/server/storage_engine/recorder/record_manager.cpp index d6668a7..868b105 100644 --- a/src/server/storage_engine/recorder/record_manager.cpp +++ b/src/server/storage_engine/recorder/record_manager.cpp @@ -1,6 +1,9 @@ #include "include/storage_engine/recorder/record_manager.h" #include "include/storage_engine/recorder/table.h" #include "include/storage_engine/transaction/trx.h" +#include "include/query_engine/structor/expression/comparison_expression.h" +#include "include/query_engine/structor/expression/field_expression.h" +#include "include/query_engine/structor/expression/value_expression.h" using namespace common; @@ -473,6 +476,31 @@ RC RecordFileScanner::open_scan( return rc; } +RC RecordFileScanner::open_scan( + Table *table, FileBufferPool &buffer_pool, Trx *trx, bool readonly, + std::vector> predicate_exprs) { + close_scan(); + + table_ = table; + file_buffer_pool_ = &buffer_pool; + trx_ = trx; + readonly_ = readonly; + + RC rc = bp_iterator_.init(buffer_pool); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to init bp iterator. rc=%d:%s", rc, strrc(rc)); + return rc; + } + + predicates_ = std::move(predicate_exprs); + + rc = fetch_next_record(); + if (rc == RC::RECORD_EOF) { + rc = RC::SUCCESS; + } + return rc; +} + /** * @brief 从当前位置开始找到下一条有效的记录 * @@ -538,6 +566,81 @@ RC RecordFileScanner::fetch_next_record_in_page() continue; } + bool pass = false; + if (!predicates_.empty()) { + ValueExpr *value_expression = nullptr; + for (auto &predicate : predicates_) { + if (predicate->type() == ExprType::COMPARISON) { + /** + * 例如 where id = 1 + */ + auto comp_expr = dynamic_cast(predicate.get()); + + Expression *left_expr = comp_expr->left().get(); // 即id + Expression *right_expr = comp_expr->right().get(); // 即1 + + Value right_value; // 1 + rc = right_expr->try_get_value(right_value); + bool left_value_is_field = true; // 默认左边是字段 + // 有可能是 1 = id 的情况 + if (rc != RC::SUCCESS) { + left_value_is_field = false; + } + + // 获取左边的字段 + std::vector query_fields; + if (left_value_is_field) + left_expr->getFields(query_fields); + else + right_expr->getFields(query_fields); + + for (auto field : query_fields) { + const char *record = field->get_data(next_record_); + char *recordNonConst = const_cast(record); + + Value left_value; + // id=1的情况 + if (left_value_is_field) { + // 获取左边的值 + left_value = + Value(field->attr_type(), recordNonConst, field->len()); + } + // 1=id的情况 + else { + left_expr->try_get_value(left_value); + right_value = + Value(field->attr_type(), recordNonConst, field->len()); + } + + // 比较左右两边的值 + bool compare_result = false; + rc = comp_expr->compare_value(left_value, right_value, + compare_result); + + if (rc != RC::SUCCESS) { + LOG_WARN("failed to compare value. rc=%s", strrc(rc)); + return rc; + } + + // 不相等则过滤掉 + if (!compare_result) { + pass = true; + break; + } + } + + if (pass) { + break; + } + } + } + } + + // 不满足过滤条件,就继续找下一条记录,不需要进行事务探测 + if (pass) { + continue; + } + // 如果是某个事务上遍历数据,还要看看事务访问是否有冲突 if (trx_ == nullptr) { return rc; diff --git a/src/server/storage_engine/recorder/table.cpp b/src/server/storage_engine/recorder/table.cpp index 0308efc..7d388a2 100644 --- a/src/server/storage_engine/recorder/table.cpp +++ b/src/server/storage_engine/recorder/table.cpp @@ -2,6 +2,8 @@ #include "include/storage_engine/recorder/record_manager.h" #include "include/storage_engine/schema/schema_util.h" #include "include/storage_engine/index/bplus_tree_index.h" +#include "include/storage_engine/transaction/mvcc_trx.h" +#include "include/storage_engine/transaction/trx.h" #include @@ -490,6 +492,18 @@ RC Table::get_record_scanner(RecordFileScanner &scanner, Trx *trx, bool readonly return rc; } +RC Table::get_record_scanner( + RecordFileScanner &scanner, Trx *trx, bool readonly, + std::vector> predicate_exprs) { + + RC rc = scanner.open_scan(this, *data_buffer_pool_, trx, readonly, + std::move(predicate_exprs)); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to open scanner. rc=%s", strrc(rc)); + } + return rc; +} + Index *Table::find_index(const char *index_name) const {