From 2c02bc7479b2640fb22714f519ba4b12793802b1 Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Mon, 3 Jun 2024 21:36:13 +0800 Subject: [PATCH 1/4] Refactor physcal match, part1 Signed-off-by: Jin Hai --- src/executor/operator/physical_match.cpp | 44 ++++++++----------- src/executor/operator/physical_match.cppm | 8 ++++ src/executor/physical_planner.cpp | 3 ++ src/planner/bound_select_statement.cpp | 37 ++++++++++++++-- src/planner/node/logical_match.cppm | 5 +++ .../invertedindex/search/query_builder.cpp | 11 ++--- .../invertedindex/search/query_builder.cppm | 6 ++- 7 files changed, 78 insertions(+), 36 deletions(-) diff --git a/src/executor/operator/physical_match.cpp b/src/executor/operator/physical_match.cpp index 5b80f85bf9..dd37bc2a87 100644 --- a/src/executor/operator/physical_match.cpp +++ b/src/executor/operator/physical_match.cpp @@ -15,7 +15,6 @@ module; #include -#include #include #include #include @@ -50,7 +49,7 @@ import logical_type; import search_options; import status; import index_defines; -import search_driver; + import query_node; import query_builder; import doc_iterator; @@ -619,20 +618,19 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator auto execute_start_time = std::chrono::high_resolution_clock::now(); // 1. build QueryNode tree // 1.1 populate column2analyzer - Txn *txn = query_context->GetTxn(); - QueryBuilder query_builder(txn, base_table_ref_); +// Txn *txn = query_context->GetTxn(); + QueryBuilder query_builder(base_table_ref_.get()); + query_builder.Init(index_reader_); auto finish_init_query_builder_time = std::chrono::high_resolution_clock::now(); TimeDurationType query_builder_init_duration = finish_init_query_builder_time - execute_start_time; LOG_DEBUG(fmt::format("PhysicalMatch 0: Init QueryBuilder time: {} ms", query_builder_init_duration.count())); - const Map &column2analyzer = query_builder.GetColumn2Analyzer(); + // 1.2 parse options into map, populate default_field SearchOptions search_ops(match_expr_->options_text_); - const String &default_field = search_ops.options_["default_field"]; - const String &block_max_option = search_ops.options_["block_max"]; + const String &block_max_option = search_ops.options_["block_max"]; // search method => enumerate method, BMW, BMM, Naive bool use_ordinary_iter = false; bool use_block_max_iter = false; - const String &threshold = search_ops.options_["threshold"]; - const float begin_threshold = strtof(threshold.c_str(), nullptr); + EarlyTermAlg early_term_alg = EarlyTermAlg::kBMW; if (block_max_option.empty() or block_max_option == "true" or block_max_option == "bmw") { use_block_max_iter = true; @@ -650,14 +648,6 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator LOG_ERROR(status.message()); RecoverableError(status); } - // 1.3 build filter - SearchDriver driver(column2analyzer, default_field); - UniquePtr query_tree = driver.ParseSingleWithFields(match_expr_->fields_, match_expr_->matching_text_); - if (query_tree == nullptr) { - Status status = Status::ParseMatchExprFailed(match_expr_->fields_, match_expr_->matching_text_); - LOG_ERROR(status.message()); - RecoverableError(status); - } auto finish_parse_query_tree_time = std::chrono::high_resolution_clock::now(); TimeDurationType parse_query_tree_duration = finish_parse_query_tree_time - finish_init_query_builder_time; @@ -692,13 +682,13 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator TimeDurationType blockmax_duration_2 = {}; TimeDurationType blockmax_duration_3 = {}; assert(common_query_filter_); - full_text_query_context.query_tree_ = MakeUnique(common_query_filter_.get(), std::move(query_tree)); + full_text_query_context.query_tree_ = MakeUnique(common_query_filter_.get(), std::move(query_tree_)); if (use_block_max_iter) { et_iter = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_alg); // et_iter is nullptr if fulltext index is present but there's no data - if (et_iter != nullptr && begin_threshold > 0.0f) - et_iter->UpdateScoreThreshold(begin_threshold); + if (et_iter != nullptr && begin_threshold_ > 0.0f) + et_iter->UpdateScoreThreshold(begin_threshold_); } if (use_ordinary_iter) { doc_iterator = query_builder.CreateSearch(full_text_query_context); @@ -706,10 +696,10 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator if (use_block_max_iter and use_ordinary_iter) { et_iter_2 = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_alg); et_iter_3 = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_alg); - if (et_iter_2 != nullptr && begin_threshold > 0.0f) - et_iter_2->UpdateScoreThreshold(begin_threshold); - if (et_iter_3 != nullptr && begin_threshold > 0.0f) - et_iter_3->UpdateScoreThreshold(begin_threshold); + if (et_iter_2 != nullptr && begin_threshold_ > 0.0f) + et_iter_2->UpdateScoreThreshold(begin_threshold_); + if (et_iter_3 != nullptr && begin_threshold_ > 0.0f) + et_iter_3->UpdateScoreThreshold(begin_threshold_); } // 3 full text search @@ -915,11 +905,15 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator PhysicalMatch::PhysicalMatch(u64 id, SharedPtr base_table_ref, SharedPtr match_expr, + IndexReader index_reader, + UniquePtr&& query_tree, + float begin_threshold, const SharedPtr &common_query_filter, u64 match_table_index, SharedPtr> load_metas) : PhysicalOperator(PhysicalOperatorType::kMatch, nullptr, nullptr, id, load_metas), table_index_(match_table_index), - base_table_ref_(std::move(base_table_ref)), match_expr_(std::move(match_expr)), common_query_filter_(common_query_filter) {} + base_table_ref_(std::move(base_table_ref)), match_expr_(std::move(match_expr)), index_reader_(index_reader), query_tree_(std::move(query_tree)), + begin_threshold_(begin_threshold), common_query_filter_(common_query_filter) {} PhysicalMatch::~PhysicalMatch() = default; diff --git a/src/executor/operator/physical_match.cppm b/src/executor/operator/physical_match.cppm index 85c8ac6712..de640acff8 100644 --- a/src/executor/operator/physical_match.cppm +++ b/src/executor/operator/physical_match.cppm @@ -32,6 +32,8 @@ import internal_types; import data_type; import common_query_filter; import logger; +import column_index_reader; +import query_node; namespace infinity { @@ -40,6 +42,9 @@ public: explicit PhysicalMatch(u64 id, SharedPtr base_table_ref, SharedPtr match_expr, + IndexReader index_reader, + UniquePtr&& query_tree, + float begin_threshold, const SharedPtr &common_query_filter, u64 match_table_index, SharedPtr> load_metas); @@ -81,6 +86,9 @@ private: u64 table_index_ = 0; SharedPtr base_table_ref_; SharedPtr match_expr_; + IndexReader index_reader_; + UniquePtr query_tree_; + float begin_threshold_; // for filter SharedPtr common_query_filter_; diff --git a/src/executor/physical_planner.cpp b/src/executor/physical_planner.cpp index 7d23714b38..e50d3bfd34 100644 --- a/src/executor/physical_planner.cpp +++ b/src/executor/physical_planner.cpp @@ -925,6 +925,9 @@ UniquePtr PhysicalPlanner::BuildMatch(const SharedPtr(logical_match->node_id(), logical_match->base_table_ref_, logical_match->match_expr_, + logical_match->index_reader_, + std::move(logical_match->query_tree_), + logical_match->begin_threshold_, logical_match->common_query_filter_, logical_match->TableIndex(), logical_operator->load_metas()); diff --git a/src/planner/bound_select_statement.cpp b/src/planner/bound_select_statement.cpp index f47cb44b28..df3a32543e 100644 --- a/src/planner/bound_select_statement.cpp +++ b/src/planner/bound_select_statement.cpp @@ -15,6 +15,7 @@ module; #include +#include module bound_select_statement; @@ -74,6 +75,11 @@ import table_reference; import common_query_filter; import logger; +import search_options; +import search_driver; +import query_node; +import status; + namespace infinity { SharedPtr BoundSelectStatement::BuildPlan(QueryContext *query_context) { @@ -172,10 +178,33 @@ SharedPtr BoundSelectStatement::BuildPlan(QueryContext *query_conte Vector> match_knn_nodes; match_knn_nodes.reserve(num_children); for (auto &match_expr : search_expr_->match_exprs_) { - SharedPtr matchNode = MakeShared(bind_context->GetNewLogicalNodeId(), base_table_ref, match_expr); - matchNode->filter_expression_ = filter_expr; - matchNode->common_query_filter_ = common_query_filter; - match_knn_nodes.push_back(std::move(matchNode)); + SharedPtr match_node = MakeShared(bind_context->GetNewLogicalNodeId(), base_table_ref, match_expr); + match_node->filter_expression_ = filter_expr; + match_node->common_query_filter_ = common_query_filter; + match_node->index_reader_ = base_table_ref->table_entry_ptr_->GetFullTextIndexReader(query_context->GetTxn()); + + const Map &column2analyzer = match_node->index_reader_.GetColumn2Analyzer(); + SearchOptions search_ops(match_node->match_expr_->options_text_); + + const String &threshold = search_ops.options_["threshold"]; + match_node->begin_threshold_ = strtof(threshold.c_str(), nullptr); + + auto iter = search_ops.options_.find("default_field"); + String default_field; + if(iter != search_ops.options_.end()) { + default_field = iter->second; + } + + SearchDriver search_driver(column2analyzer, default_field); + UniquePtr query_tree = search_driver.ParseSingleWithFields(match_node->match_expr_->fields_, match_node->match_expr_->matching_text_); + if (query_tree.get() == nullptr) { + Status status = Status::ParseMatchExprFailed(match_node->match_expr_->fields_, match_node->match_expr_->matching_text_); + LOG_ERROR(status.message()); + RecoverableError(status); + } + + match_node->query_tree_ = std::move(query_tree); + match_knn_nodes.push_back(std::move(match_node)); } for (auto &match_tensor_expr : search_expr_->match_tensor_exprs_) { auto match_tensor_node = MakeShared(bind_context->GetNewLogicalNodeId(), base_table_ref, match_tensor_expr); diff --git a/src/planner/node/logical_match.cppm b/src/planner/node/logical_match.cppm index a1758dec60..8b5e1ad2bf 100644 --- a/src/planner/node/logical_match.cppm +++ b/src/planner/node/logical_match.cppm @@ -28,6 +28,8 @@ import table_entry; import internal_types; import data_type; import common_query_filter; +import column_index_reader; +import query_node; namespace infinity { @@ -54,6 +56,9 @@ public: SharedPtr base_table_ref_{}; SharedPtr match_expr_{}; SharedPtr filter_expression_{}; + IndexReader index_reader_; + UniquePtr query_tree_; + float begin_threshold_; SharedPtr common_query_filter_{}; }; diff --git a/src/storage/invertedindex/search/query_builder.cpp b/src/storage/invertedindex/search/query_builder.cpp index 4a64ee6f7f..70db6ab45a 100644 --- a/src/storage/invertedindex/search/query_builder.cpp +++ b/src/storage/invertedindex/search/query_builder.cpp @@ -37,10 +37,11 @@ import third_party; namespace infinity { -QueryBuilder::QueryBuilder(Txn *txn, SharedPtr &base_table_ref) - : table_entry_(base_table_ref->table_entry_ptr_), index_reader_(table_entry_->GetFullTextIndexReader(txn)) { +void QueryBuilder::Init(IndexReader index_reader) { + index_reader_ = index_reader; + u64 total_row_count = 0; - for (const auto &[segment_id, segment_info] : base_table_ref->block_index_->segment_block_index_) { + for (const auto &[segment_id, segment_info] : base_table_ref_->block_index_->segment_block_index_) { total_row_count += segment_info.segment_offset_; } @@ -55,7 +56,7 @@ UniquePtr QueryBuilder::CreateSearch(FullTextQueryContext &context) context.optimized_query_tree_ = QueryNode::GetOptimizedQueryTree(std::move(context.query_tree_)); } // Create the iterator from the query tree. - UniquePtr result = context.optimized_query_tree_->CreateSearch(table_entry_, index_reader_, &scorer_); + UniquePtr result = context.optimized_query_tree_->CreateSearch(base_table_ref_->table_entry_ptr_, index_reader_, &scorer_); #ifdef INFINITY_DEBUG { OStringStream oss; @@ -78,7 +79,7 @@ UniquePtr QueryBuilder::CreateEarlyTerminateSearch(FullT } // Create the iterator from the query tree. UniquePtr result = - context.optimized_query_tree_->CreateEarlyTerminateSearch(table_entry_, index_reader_, &scorer_, early_term_alg); + context.optimized_query_tree_->CreateEarlyTerminateSearch(base_table_ref_->table_entry_ptr_, index_reader_, &scorer_, early_term_alg); #ifdef INFINITY_DEBUG { OStringStream oss; diff --git a/src/storage/invertedindex/search/query_builder.cppm b/src/storage/invertedindex/search/query_builder.cppm index af873328f5..e1fcf6ea48 100644 --- a/src/storage/invertedindex/search/query_builder.cppm +++ b/src/storage/invertedindex/search/query_builder.cppm @@ -39,7 +39,9 @@ enum class EarlyTermAlg; export class QueryBuilder { public: - QueryBuilder(Txn *txn, SharedPtr &base_table_ref); + explicit QueryBuilder(BaseTableRef* base_table_ref) : base_table_ref_(base_table_ref) {}; + + void Init(IndexReader index_reader); ~QueryBuilder(); @@ -52,7 +54,7 @@ public: inline float Score(RowID doc_id) { return scorer_.Score(doc_id); } private: - TableEntry *table_entry_{nullptr}; + BaseTableRef* base_table_ref_{nullptr}; IndexReader index_reader_; Scorer scorer_; }; From f4502c86057fb6a4c63717523218d13238318c9b Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Mon, 3 Jun 2024 23:25:42 +0800 Subject: [PATCH 2/4] Fix ut Signed-off-by: Jin Hai --- src/storage/invertedindex/search/query_builder.cpp | 4 ++-- src/storage/invertedindex/search/query_builder.cppm | 4 +++- src/unit_test/storage/invertedindex/search/query_match.cpp | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/storage/invertedindex/search/query_builder.cpp b/src/storage/invertedindex/search/query_builder.cpp index 70db6ab45a..39f92ba841 100644 --- a/src/storage/invertedindex/search/query_builder.cpp +++ b/src/storage/invertedindex/search/query_builder.cpp @@ -56,7 +56,7 @@ UniquePtr QueryBuilder::CreateSearch(FullTextQueryContext &context) context.optimized_query_tree_ = QueryNode::GetOptimizedQueryTree(std::move(context.query_tree_)); } // Create the iterator from the query tree. - UniquePtr result = context.optimized_query_tree_->CreateSearch(base_table_ref_->table_entry_ptr_, index_reader_, &scorer_); + UniquePtr result = context.optimized_query_tree_->CreateSearch(table_entry_, index_reader_, &scorer_); #ifdef INFINITY_DEBUG { OStringStream oss; @@ -79,7 +79,7 @@ UniquePtr QueryBuilder::CreateEarlyTerminateSearch(FullT } // Create the iterator from the query tree. UniquePtr result = - context.optimized_query_tree_->CreateEarlyTerminateSearch(base_table_ref_->table_entry_ptr_, index_reader_, &scorer_, early_term_alg); + context.optimized_query_tree_->CreateEarlyTerminateSearch(table_entry_, index_reader_, &scorer_, early_term_alg); #ifdef INFINITY_DEBUG { OStringStream oss; diff --git a/src/storage/invertedindex/search/query_builder.cppm b/src/storage/invertedindex/search/query_builder.cppm index e1fcf6ea48..7e671f0a1c 100644 --- a/src/storage/invertedindex/search/query_builder.cppm +++ b/src/storage/invertedindex/search/query_builder.cppm @@ -39,7 +39,8 @@ enum class EarlyTermAlg; export class QueryBuilder { public: - explicit QueryBuilder(BaseTableRef* base_table_ref) : base_table_ref_(base_table_ref) {}; + explicit QueryBuilder(BaseTableRef* base_table_ref) + : base_table_ref_(base_table_ref), table_entry_(base_table_ref->table_entry_ptr_) {}; void Init(IndexReader index_reader); @@ -55,6 +56,7 @@ public: private: BaseTableRef* base_table_ref_{nullptr}; + TableEntry *table_entry_{nullptr}; IndexReader index_reader_; Scorer scorer_; }; diff --git a/src/unit_test/storage/invertedindex/search/query_match.cpp b/src/unit_test/storage/invertedindex/search/query_match.cpp index 78994edcc0..a576f1f62f 100644 --- a/src/unit_test/storage/invertedindex/search/query_match.cpp +++ b/src/unit_test/storage/invertedindex/search/query_match.cpp @@ -38,6 +38,7 @@ import phrase_doc_iterator; import global_resource_usage; import term_doc_iterator; import logger; +import column_index_reader; using namespace infinity; @@ -294,7 +295,9 @@ void QueryMatchTest::QueryMatch(const String& db_name, auto fake_table_ref = BaseTableRef::FakeTableRef(table_entry, txn); - QueryBuilder query_builder(txn, fake_table_ref); + QueryBuilder query_builder(fake_table_ref.get()); + IndexReader index_reader = fake_table_ref->table_entry_ptr_->GetFullTextIndexReader(txn); + query_builder.Init(index_reader); const Map &column2analyzer = query_builder.GetColumn2Analyzer(); auto match_expr = MakeShared(); From 585726fedf0abda019da047324e3d33f5e076bf7 Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Tue, 4 Jun 2024 10:12:04 +0800 Subject: [PATCH 3/4] Add error prompt of flush log and buffer Signed-off-by: Jin Hai --- src/executor/operator/physical_flush.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/executor/operator/physical_flush.cpp b/src/executor/operator/physical_flush.cpp index b90d23e510..5afa7c89d5 100644 --- a/src/executor/operator/physical_flush.cpp +++ b/src/executor/operator/physical_flush.cpp @@ -14,6 +14,8 @@ module; +module physical_flush; + import stl; import txn; import query_context; @@ -25,8 +27,7 @@ import operator_state; import logger; import bg_task; import third_party; - -module physical_flush; +import status; namespace infinity { @@ -65,10 +66,16 @@ void PhysicalFlush::FlushData(QueryContext *query_context, OperatorState *operat void PhysicalFlush::FlushLog(QueryContext *query_context, OperatorState *operator_state) { // Generate the result + Status status = Status::NotSupport("Flush log"); + LOG_ERROR(status.message()); + RecoverableError(status); } void PhysicalFlush::FlushBuffer(QueryContext *query_context, OperatorState *operator_state) { // Generate the result + Status status = Status::NotSupport("Flush buffer"); + LOG_ERROR(status.message()); + RecoverableError(status); } } // namespace infinity From ca3794c4d4c5c748c24a951e5869a5afedd254aa Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Tue, 4 Jun 2024 15:33:07 +0800 Subject: [PATCH 4/4] Refactor physical match, part2 Signed-off-by: Jin Hai --- src/executor/operator/physical_match.cpp | 104 ++++++++---------- src/executor/operator/physical_match.cppm | 5 + src/executor/physical_planner.cpp | 2 + src/planner/bound_select_statement.cpp | 36 +++++- src/planner/node/logical_match.cppm | 3 + .../early_terminate_iterator.cppm | 8 +- .../invertedindex/search/query_builder.cpp | 4 +- .../invertedindex/search/query_builder.cppm | 4 +- .../invertedindex/search/query_node.cpp | 26 ++--- src/storage/invertedindex/search/query_node.h | 16 +-- .../invertedindex/search/query_builder.cpp | 2 +- 11 files changed, 124 insertions(+), 86 deletions(-) diff --git a/src/executor/operator/physical_match.cpp b/src/executor/operator/physical_match.cpp index dd37bc2a87..3cf2dc9dc0 100644 --- a/src/executor/operator/physical_match.cpp +++ b/src/executor/operator/physical_match.cpp @@ -536,8 +536,8 @@ struct FilterQueryNode final : public QueryNode { return MakeUnique>(common_query_filter_, std::move(search_iter)); } std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const override { - auto search_iter = query_tree_->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_alg); + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const override { + auto search_iter = query_tree_->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_algo); if (!search_iter) { return nullptr; } @@ -571,12 +571,12 @@ void ASSERT_FLOAT_EQ(float bar, u32 i, float a, float b) { void ExecuteFTSearch(UniquePtr &et_iter, FullTextScoreResultHeap &result_heap, u32 &blockmax_loop_cnt, - EarlyTermAlg early_term_alg) { + EarlyTermAlgo early_term_algo) { // et_iter is nullptr if fulltext index is present but there's no data if (et_iter == nullptr) return; - switch (early_term_alg) { - case EarlyTermAlg::kBMM: { + switch (early_term_algo) { + case EarlyTermAlgo::kBMM: { while (true) { auto [id, et_score] = et_iter->BlockNextWithThreshold(result_heap.GetScoreThreshold()); if (id == INVALID_ROWID) [[unlikely]] { @@ -592,7 +592,7 @@ void ExecuteFTSearch(UniquePtr &et_iter, } break; } - case EarlyTermAlg::kBMW: + case EarlyTermAlgo::kBMW: default: { while (true) { ++blockmax_loop_cnt; @@ -626,27 +626,28 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator LOG_DEBUG(fmt::format("PhysicalMatch 0: Init QueryBuilder time: {} ms", query_builder_init_duration.count())); // 1.2 parse options into map, populate default_field - SearchOptions search_ops(match_expr_->options_text_); - const String &block_max_option = search_ops.options_["block_max"]; // search method => enumerate method, BMW, BMM, Naive bool use_ordinary_iter = false; bool use_block_max_iter = false; - EarlyTermAlg early_term_alg = EarlyTermAlg::kBMW; - if (block_max_option.empty() or block_max_option == "true" or block_max_option == "bmw") { - use_block_max_iter = true; - early_term_alg = EarlyTermAlg::kBMW; - } else if (block_max_option == "bmm") { - use_block_max_iter = true; - early_term_alg = EarlyTermAlg::kBMM; - } else if (block_max_option == "false") { - use_ordinary_iter = true; - } else if (block_max_option == "compare") { - use_ordinary_iter = true; - use_block_max_iter = true; - } else { - Status status = Status::SyntaxError("block_max option must be empty, true, false or compare"); - LOG_ERROR(status.message()); - RecoverableError(status); + switch(early_term_algo_) { + case EarlyTermAlgo::kBMM: { + use_block_max_iter = true; + break; + } + case EarlyTermAlgo::kNaive: { + use_ordinary_iter = true; + break; + } + case EarlyTermAlgo::kCompare: { + use_ordinary_iter = true; + use_block_max_iter = true; + break; + } + case EarlyTermAlgo::kBMW: + default: { + use_block_max_iter = true; + break; + } } auto finish_parse_query_tree_time = std::chrono::high_resolution_clock::now(); @@ -685,7 +686,7 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator full_text_query_context.query_tree_ = MakeUnique(common_query_filter_.get(), std::move(query_tree_)); if (use_block_max_iter) { - et_iter = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_alg); + et_iter = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_algo_); // et_iter is nullptr if fulltext index is present but there's no data if (et_iter != nullptr && begin_threshold_ > 0.0f) et_iter->UpdateScoreThreshold(begin_threshold_); @@ -694,8 +695,8 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator doc_iterator = query_builder.CreateSearch(full_text_query_context); } if (use_block_max_iter and use_ordinary_iter) { - et_iter_2 = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_alg); - et_iter_3 = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_alg); + et_iter_2 = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_algo_); + et_iter_3 = query_builder.CreateEarlyTerminateSearch(full_text_query_context, early_term_algo_); if (et_iter_2 != nullptr && begin_threshold_ > 0.0f) et_iter_2->UpdateScoreThreshold(begin_threshold_); if (et_iter_3 != nullptr && begin_threshold_ > 0.0f) @@ -703,29 +704,18 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator } // 3 full text search - u32 top_n = 0; - if (auto iter_n_option = search_ops.options_.find("topn"); iter_n_option != search_ops.options_.end()) { - int top_n_option = std::stoi(iter_n_option->second); - if (top_n_option <= 0) { - Status status = Status::SyntaxError("topn must be a positive integer"); - LOG_ERROR(status.message()); - RecoverableError(status); - } - top_n = top_n_option; - } else { - top_n = DEFAULT_FULL_TEXT_OPTION_TOP_N; - } + auto finish_query_builder_time = std::chrono::high_resolution_clock::now(); TimeDurationType query_builder_duration = finish_query_builder_time - finish_parse_query_tree_time; LOG_DEBUG(fmt::format("PhysicalMatch Part 2: Build Query iterator time: {} ms", query_builder_duration.count())); if (use_block_max_iter) { - blockmax_score_result = MakeUniqueForOverwrite(top_n); - blockmax_row_id_result = MakeUniqueForOverwrite(top_n); - FullTextScoreResultHeap result_heap(top_n, blockmax_score_result.get(), blockmax_row_id_result.get()); + blockmax_score_result = MakeUniqueForOverwrite(top_n_); + blockmax_row_id_result = MakeUniqueForOverwrite(top_n_); + FullTextScoreResultHeap result_heap(top_n_, blockmax_score_result.get(), blockmax_row_id_result.get()); #ifdef INFINITY_DEBUG auto blockmax_begin_ts = std::chrono::high_resolution_clock::now(); #endif - ExecuteFTSearch(et_iter, result_heap, blockmax_loop_cnt, early_term_alg); + ExecuteFTSearch(et_iter, result_heap, blockmax_loop_cnt, early_term_algo_); result_heap.Sort(); blockmax_result_count = result_heap.GetResultSize(); #ifdef INFINITY_DEBUG @@ -736,9 +726,9 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator if (use_ordinary_iter) { RowID iter_row_id = doc_iterator.get() == nullptr ? INVALID_ROWID : (doc_iterator->PrepareFirstDoc(), doc_iterator->Doc()); if (iter_row_id != INVALID_ROWID) [[likely]] { - ordinary_score_result = MakeUniqueForOverwrite(top_n); - ordinary_row_id_result = MakeUniqueForOverwrite(top_n); - FullTextScoreResultHeap result_heap(top_n, ordinary_score_result.get(), ordinary_row_id_result.get()); + ordinary_score_result = MakeUniqueForOverwrite(top_n_); + ordinary_row_id_result = MakeUniqueForOverwrite(top_n_); + FullTextScoreResultHeap result_heap(top_n_, ordinary_score_result.get(), ordinary_row_id_result.get()); #ifdef INFINITY_DEBUG auto ordinary_begin_ts = std::chrono::high_resolution_clock::now(); #endif @@ -759,32 +749,32 @@ bool PhysicalMatch::ExecuteInnerHomebrewed(QueryContext *query_context, Operator } } if (use_ordinary_iter and use_block_max_iter) { - blockmax_score_result_2 = MakeUniqueForOverwrite(top_n); - blockmax_row_id_result_2 = MakeUniqueForOverwrite(top_n); - FullTextScoreResultHeap result_heap(top_n, blockmax_score_result_2.get(), blockmax_row_id_result_2.get()); + blockmax_score_result_2 = MakeUniqueForOverwrite(top_n_); + blockmax_row_id_result_2 = MakeUniqueForOverwrite(top_n_); + FullTextScoreResultHeap result_heap(top_n_, blockmax_score_result_2.get(), blockmax_row_id_result_2.get()); #ifdef INFINITY_DEBUG auto blockmax_begin_ts = std::chrono::high_resolution_clock::now(); #endif - ExecuteFTSearch(et_iter_2, result_heap, blockmax_loop_cnt_2, early_term_alg); + ExecuteFTSearch(et_iter_2, result_heap, blockmax_loop_cnt_2, early_term_algo_); result_heap.Sort(); blockmax_result_count_2 = result_heap.GetResultSize(); #ifdef INFINITY_DEBUG auto blockmax_end_ts = std::chrono::high_resolution_clock::now(); blockmax_duration_2 = blockmax_end_ts - blockmax_begin_ts; { - auto blockmax_score_result_3 = MakeUniqueForOverwrite(top_n); - auto blockmax_row_id_result_3 = MakeUniqueForOverwrite(top_n); - FullTextScoreResultHeap result_heap_3(top_n, blockmax_score_result_3.get(), blockmax_row_id_result_3.get()); + auto blockmax_score_result_3 = MakeUniqueForOverwrite(top_n_); + auto blockmax_row_id_result_3 = MakeUniqueForOverwrite(top_n_); + FullTextScoreResultHeap result_heap_3(top_n_, blockmax_score_result_3.get(), blockmax_row_id_result_3.get()); auto blockmax_begin_ts_3 = std::chrono::high_resolution_clock::now(); u32 blockmax_loop_cnt_3 = 0; - ExecuteFTSearch(et_iter_3, result_heap_3, blockmax_loop_cnt_3, early_term_alg); + ExecuteFTSearch(et_iter_3, result_heap_3, blockmax_loop_cnt_3, early_term_algo_); result_heap_3.Sort(); auto blockmax_end_ts_3 = std::chrono::high_resolution_clock::now(); if (blockmax_loop_cnt_3 != blockmax_loop_cnt_2) { assert(false); } assert(result_heap_3.GetResultSize() == result_heap.GetResultSize()); - for (u32 i = 0; i < top_n; ++i) { + for (u32 i = 0; i < top_n_; ++i) { assert(blockmax_score_result_2[i] == blockmax_score_result_3[i]); assert(blockmax_row_id_result_2[i] == blockmax_row_id_result_3[i]); } @@ -908,12 +898,14 @@ PhysicalMatch::PhysicalMatch(u64 id, IndexReader index_reader, UniquePtr&& query_tree, float begin_threshold, + EarlyTermAlgo early_term_algo, + u32 top_n, const SharedPtr &common_query_filter, u64 match_table_index, SharedPtr> load_metas) : PhysicalOperator(PhysicalOperatorType::kMatch, nullptr, nullptr, id, load_metas), table_index_(match_table_index), base_table_ref_(std::move(base_table_ref)), match_expr_(std::move(match_expr)), index_reader_(index_reader), query_tree_(std::move(query_tree)), - begin_threshold_(begin_threshold), common_query_filter_(common_query_filter) {} + begin_threshold_(begin_threshold), early_term_algo_(early_term_algo), top_n_(top_n), common_query_filter_(common_query_filter) {} PhysicalMatch::~PhysicalMatch() = default; diff --git a/src/executor/operator/physical_match.cppm b/src/executor/operator/physical_match.cppm index de640acff8..cab662f51f 100644 --- a/src/executor/operator/physical_match.cppm +++ b/src/executor/operator/physical_match.cppm @@ -34,6 +34,7 @@ import common_query_filter; import logger; import column_index_reader; import query_node; +import early_terminate_iterator; namespace infinity { @@ -45,6 +46,8 @@ public: IndexReader index_reader, UniquePtr&& query_tree, float begin_threshold, + EarlyTermAlgo early_term_algo, + u32 top_n, const SharedPtr &common_query_filter, u64 match_table_index, SharedPtr> load_metas); @@ -89,6 +92,8 @@ private: IndexReader index_reader_; UniquePtr query_tree_; float begin_threshold_; + EarlyTermAlgo early_term_algo_{EarlyTermAlgo::kBMW}; + u32 top_n_{1}; // for filter SharedPtr common_query_filter_; diff --git a/src/executor/physical_planner.cpp b/src/executor/physical_planner.cpp index e50d3bfd34..e6024fb134 100644 --- a/src/executor/physical_planner.cpp +++ b/src/executor/physical_planner.cpp @@ -928,6 +928,8 @@ UniquePtr PhysicalPlanner::BuildMatch(const SharedPtrindex_reader_, std::move(logical_match->query_tree_), logical_match->begin_threshold_, + logical_match->early_term_algo_, + logical_match->top_n_, logical_match->common_query_filter_, logical_match->TableIndex(), logical_operator->load_metas()); diff --git a/src/planner/bound_select_statement.cpp b/src/planner/bound_select_statement.cpp index df3a32543e..7629c4f095 100644 --- a/src/planner/bound_select_statement.cpp +++ b/src/planner/bound_select_statement.cpp @@ -14,7 +14,7 @@ module; -#include +#include #include module bound_select_statement; @@ -79,6 +79,8 @@ import search_options; import search_driver; import query_node; import status; +import early_terminate_iterator; +import default_values; namespace infinity { @@ -186,15 +188,47 @@ SharedPtr BoundSelectStatement::BuildPlan(QueryContext *query_conte const Map &column2analyzer = match_node->index_reader_.GetColumn2Analyzer(); SearchOptions search_ops(match_node->match_expr_->options_text_); + // option: threshold const String &threshold = search_ops.options_["threshold"]; match_node->begin_threshold_ = strtof(threshold.c_str(), nullptr); + // option: default field auto iter = search_ops.options_.find("default_field"); String default_field; if(iter != search_ops.options_.end()) { default_field = iter->second; } + // option: block max + iter = search_ops.options_.find("block_max"); + if(iter == search_ops.options_.end() or iter->second == "true" or iter->second == "bmw") { + match_node->early_term_algo_ = EarlyTermAlgo::kBMW; + } else if(iter->second == "bmm") { + match_node->early_term_algo_ = EarlyTermAlgo::kBMM; + } else if(iter->second == "false") { + match_node->early_term_algo_ = EarlyTermAlgo::kNaive; + } else if(iter->second == "compare") { + match_node->early_term_algo_ = EarlyTermAlgo::kCompare; + } else { + Status status = Status::SyntaxError("block_max option must be empty, true, false or compare"); + LOG_ERROR(status.message()); + RecoverableError(status); + } + + // option: top n + iter = search_ops.options_.find("topn"); + if (iter != search_ops.options_.end()) { + i32 top_n_option = std::strtol(iter->second.c_str(), nullptr, 0); + if (top_n_option <= 0) { + Status status = Status::SyntaxError("top n must be a positive integer"); + LOG_ERROR(status.message()); + RecoverableError(status); + } + match_node->top_n_ = top_n_option; + } else { + match_node->top_n_ = DEFAULT_FULL_TEXT_OPTION_TOP_N; + } + SearchDriver search_driver(column2analyzer, default_field); UniquePtr query_tree = search_driver.ParseSingleWithFields(match_node->match_expr_->fields_, match_node->match_expr_->matching_text_); if (query_tree.get() == nullptr) { diff --git a/src/planner/node/logical_match.cppm b/src/planner/node/logical_match.cppm index 8b5e1ad2bf..b7e00d0d01 100644 --- a/src/planner/node/logical_match.cppm +++ b/src/planner/node/logical_match.cppm @@ -30,6 +30,7 @@ import data_type; import common_query_filter; import column_index_reader; import query_node; +import early_terminate_iterator; namespace infinity { @@ -59,6 +60,8 @@ public: IndexReader index_reader_; UniquePtr query_tree_; float begin_threshold_; + EarlyTermAlgo early_term_algo_{EarlyTermAlgo::kBMW}; + u32 top_n_{1}; SharedPtr common_query_filter_{}; }; diff --git a/src/storage/invertedindex/search/early_terminate_iterator/early_terminate_iterator.cppm b/src/storage/invertedindex/search/early_terminate_iterator/early_terminate_iterator.cppm index 14942bf6e2..4b4e044e79 100644 --- a/src/storage/invertedindex/search/early_terminate_iterator/early_terminate_iterator.cppm +++ b/src/storage/invertedindex/search/early_terminate_iterator/early_terminate_iterator.cppm @@ -23,9 +23,11 @@ import internal_types; namespace infinity { -export enum class EarlyTermAlg : u8 { - kBMW = 0, - kBMM = 1, +export enum class EarlyTermAlgo { + kBMW, + kBMM, + kNaive, + kCompare }; // usage: get sequence of results by calling NextWithThreshold() or BlockNextWithThreshold() diff --git a/src/storage/invertedindex/search/query_builder.cpp b/src/storage/invertedindex/search/query_builder.cpp index 39f92ba841..8fe9f52c5f 100644 --- a/src/storage/invertedindex/search/query_builder.cpp +++ b/src/storage/invertedindex/search/query_builder.cpp @@ -72,14 +72,14 @@ UniquePtr QueryBuilder::CreateSearch(FullTextQueryContext &context) return result; } -UniquePtr QueryBuilder::CreateEarlyTerminateSearch(FullTextQueryContext &context, EarlyTermAlg early_term_alg) { +UniquePtr QueryBuilder::CreateEarlyTerminateSearch(FullTextQueryContext &context, EarlyTermAlgo early_term_algo) { // Optimize the query tree. if (!context.optimized_query_tree_) { context.optimized_query_tree_ = QueryNode::GetOptimizedQueryTree(std::move(context.query_tree_)); } // Create the iterator from the query tree. UniquePtr result = - context.optimized_query_tree_->CreateEarlyTerminateSearch(table_entry_, index_reader_, &scorer_, early_term_alg); + context.optimized_query_tree_->CreateEarlyTerminateSearch(table_entry_, index_reader_, &scorer_, early_term_algo); #ifdef INFINITY_DEBUG { OStringStream oss; diff --git a/src/storage/invertedindex/search/query_builder.cppm b/src/storage/invertedindex/search/query_builder.cppm index 7e671f0a1c..be8ca22655 100644 --- a/src/storage/invertedindex/search/query_builder.cppm +++ b/src/storage/invertedindex/search/query_builder.cppm @@ -35,7 +35,7 @@ export struct FullTextQueryContext { }; class EarlyTerminateIterator; -enum class EarlyTermAlg; +enum class EarlyTermAlgo; export class QueryBuilder { public: @@ -50,7 +50,7 @@ public: UniquePtr CreateSearch(FullTextQueryContext &context); - UniquePtr CreateEarlyTerminateSearch(FullTextQueryContext &context, EarlyTermAlg early_term_alg); + UniquePtr CreateEarlyTerminateSearch(FullTextQueryContext &context, EarlyTermAlgo early_term_algo); inline float Score(RowID doc_id) { return scorer_.Score(doc_id); } diff --git a/src/storage/invertedindex/search/query_node.cpp b/src/storage/invertedindex/search/query_node.cpp index 9c66e9dfdb..4cde77498e 100644 --- a/src/storage/invertedindex/search/query_node.cpp +++ b/src/storage/invertedindex/search/query_node.cpp @@ -455,7 +455,7 @@ std::unique_ptr TermQueryNode::CreateSearch(const TableEntry *table std::unique_ptr TermQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, - EarlyTermAlg /*early_term_alg*/) const { + EarlyTermAlgo /*early_term_algo*/) const { ColumnID column_id = table_entry->GetColumnIdByName(column_); ColumnIndexReader *column_index_reader = index_reader.GetColumnIndexReader(column_id); if (!column_index_reader) { @@ -512,7 +512,7 @@ std::unique_ptr PhraseQueryNode::CreateSearch(const TableEntry *tab std::unique_ptr PhraseQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, - EarlyTermAlg /*early_term_alg*/) const { + EarlyTermAlgo /*early_term_algo*/) const { ColumnID column_id = table_entry->GetColumnIdByName(column_); ColumnIndexReader *column_index_reader = index_reader.GetColumnIndexReader(column_id); if (!column_index_reader) { @@ -567,11 +567,11 @@ std::unique_ptr AndQueryNode::CreateSearch(const TableEntry *table_ std::unique_ptr AndQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, - EarlyTermAlg early_term_alg) const { + EarlyTermAlgo early_term_algo) const { Vector> sub_doc_iters; sub_doc_iters.reserve(children_.size()); for (auto &child : children_) { - auto iter = child->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_alg); + auto iter = child->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_algo); if (iter) { sub_doc_iters.emplace_back(std::move(iter)); } @@ -612,11 +612,11 @@ std::unique_ptr AndNotQueryNode::CreateSearch(const TableEntry *tab std::unique_ptr AndNotQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, - EarlyTermAlg early_term_alg) const { + EarlyTermAlgo early_term_algo) const { Vector> sub_doc_iters; sub_doc_iters.reserve(children_.size()); // check if the first child is a valid query - auto first_iter = children_.front()->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_alg); + auto first_iter = children_.front()->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_algo); if (!first_iter) { // no need to continue if the first child is invalid return nullptr; @@ -624,7 +624,7 @@ std::unique_ptr AndNotQueryNode::CreateEarlyTerminateSea sub_doc_iters.emplace_back(std::move(first_iter)); for (u32 i = 1; i < children_.size(); ++i) { // set scorer to nullptr, because nodes under "not" should not be added to scorer - auto iter = children_[i]->CreateEarlyTerminateSearch(table_entry, index_reader, nullptr, early_term_alg); + auto iter = children_[i]->CreateEarlyTerminateSearch(table_entry, index_reader, nullptr, early_term_algo); if (iter) { sub_doc_iters.emplace_back(std::move(iter)); } @@ -655,11 +655,11 @@ std::unique_ptr OrQueryNode::CreateSearch(const TableEntry *table_e } std::unique_ptr -OrQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const { +OrQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const { Vector> sub_doc_iters; sub_doc_iters.reserve(children_.size()); for (auto &child : children_) { - auto iter = child->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_alg); + auto iter = child->CreateEarlyTerminateSearch(table_entry, index_reader, scorer, early_term_algo); if (iter) { sub_doc_iters.emplace_back(std::move(iter)); } @@ -669,10 +669,10 @@ OrQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexRead } else if (sub_doc_iters.size() == 1) { return std::move(sub_doc_iters[0]); } else { - switch (early_term_alg) { - case EarlyTermAlg::kBMM: + switch (early_term_algo) { + case EarlyTermAlgo::kBMM: return MakeUnique(std::move(sub_doc_iters)); - case EarlyTermAlg::kBMW: + case EarlyTermAlgo::kBMW: default: return MakeUnique(std::move(sub_doc_iters)); } @@ -689,7 +689,7 @@ std::unique_ptr NotQueryNode::CreateSearch(const TableEntry *table_ std::unique_ptr NotQueryNode::CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, - EarlyTermAlg early_term_alg) const { + EarlyTermAlgo early_term_algo) const { String error_message = "NOT query node should be optimized into AND_NOT query node"; LOG_CRITICAL(error_message); UnrecoverableError(error_message); diff --git a/src/storage/invertedindex/search/query_node.h b/src/storage/invertedindex/search/query_node.h index 800c5c975d..99a90a8015 100644 --- a/src/storage/invertedindex/search/query_node.h +++ b/src/storage/invertedindex/search/query_node.h @@ -51,7 +51,7 @@ struct IndexReader; class Scorer; class DocIterator; class EarlyTerminateIterator; -enum class EarlyTermAlg; +enum class EarlyTermAlgo; // step 1. get the query tree from parser // step 2. push down the weight to the leaf term node @@ -84,7 +84,7 @@ struct QueryNode { // create the iterator from the query tree, need to be called after optimization virtual std::unique_ptr CreateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer) const = 0; virtual std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const = 0; + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const = 0; // print the query tree, for debugging virtual void PrintTree(std::ostream &os, const std::string &prefix = "", bool is_final = true) const = 0; }; @@ -99,7 +99,7 @@ struct TermQueryNode final : public QueryNode { void PushDownWeight(float factor) override { MultiplyWeight(factor); } std::unique_ptr CreateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer) const override; std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const override; + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const override; void PrintTree(std::ostream &os, const std::string &prefix, bool is_final) const override; }; @@ -113,7 +113,7 @@ struct PhraseQueryNode final : public QueryNode { void PushDownWeight(float factor) override { MultiplyWeight(factor); } std::unique_ptr CreateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer) const override; std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const override; + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const override; void PrintTree(std::ostream &os, const std::string &prefix, bool is_final) const override; void AddTerm(const std::string &term) { terms_.emplace_back(term); } @@ -146,28 +146,28 @@ struct NotQueryNode final : public MultiQueryNode { std::unique_ptr InnerGetNewOptimizedQueryTree() override; std::unique_ptr CreateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer) const override; std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const override; + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const override; }; struct AndQueryNode final : public MultiQueryNode { AndQueryNode() : MultiQueryNode(QueryNodeType::AND) {} std::unique_ptr InnerGetNewOptimizedQueryTree() override; std::unique_ptr CreateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer) const override; std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const override; + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const override; }; struct AndNotQueryNode final : public MultiQueryNode { AndNotQueryNode() : MultiQueryNode(QueryNodeType::AND_NOT) {} std::unique_ptr InnerGetNewOptimizedQueryTree() override; std::unique_ptr CreateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer) const override; std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const override; + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const override; }; struct OrQueryNode final : public MultiQueryNode { OrQueryNode() : MultiQueryNode(QueryNodeType::OR) {} std::unique_ptr InnerGetNewOptimizedQueryTree() override; std::unique_ptr CreateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer) const override; std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlg early_term_alg) const override; + CreateEarlyTerminateSearch(const TableEntry *table_entry, IndexReader &index_reader, Scorer *scorer, EarlyTermAlgo early_term_algo) const override; }; // unimplemented diff --git a/src/unit_test/storage/invertedindex/search/query_builder.cpp b/src/unit_test/storage/invertedindex/search/query_builder.cpp index 5d11426003..8790d5eefc 100644 --- a/src/unit_test/storage/invertedindex/search/query_builder.cpp +++ b/src/unit_test/storage/invertedindex/search/query_builder.cpp @@ -79,7 +79,7 @@ struct MockQueryNode : public QueryNode { return MakeUnique(std::move(doc_ids_)); } std::unique_ptr - CreateEarlyTerminateSearch(const TableEntry *, IndexReader &, Scorer *, EarlyTermAlg early_term_alg) const final { + CreateEarlyTerminateSearch(const TableEntry *, IndexReader &, Scorer *, EarlyTermAlgo early_term_algo) const final { return nullptr; } void PrintTree(std::ostream &os, const std::string &prefix, bool is_final) const final {