Skip to content

Commit 4422547

Browse files
test(p3): add topn check (#530)
1 parent af80e8b commit 4422547

File tree

6 files changed

+137
-1
lines changed

6 files changed

+137
-1
lines changed

src/execution/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ add_library(
1919
seq_scan_executor.cpp
2020
sort_executor.cpp
2121
topn_executor.cpp
22+
topn_check_executor.cpp
2223
update_executor.cpp
2324
values_executor.cpp
2425
)

src/execution/executor_factory.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "execution/executors/projection_executor.h"
3131
#include "execution/executors/seq_scan_executor.h"
3232
#include "execution/executors/sort_executor.h"
33+
#include "execution/executors/topn_check_executor.h"
3334
#include "execution/executors/topn_executor.h"
3435
#include "execution/executors/update_executor.h"
3536
#include "execution/executors/values_executor.h"
@@ -46,6 +47,7 @@ namespace bustub {
4647

4748
auto ExecutorFactory::CreateExecutor(ExecutorContext *exec_ctx, const AbstractPlanNodeRef &plan)
4849
-> std::unique_ptr<AbstractExecutor> {
50+
auto check_options_set = exec_ctx->GetCheckOptions()->check_options_set_;
4951
switch (plan->GetType()) {
5052
// Create a new sequential scan executor
5153
case PlanType::SeqScan: {
@@ -97,7 +99,6 @@ auto ExecutorFactory::CreateExecutor(ExecutorContext *exec_ctx, const AbstractPl
9799
auto nested_loop_join_plan = dynamic_cast<const NestedLoopJoinPlanNode *>(plan.get());
98100
auto left = ExecutorFactory::CreateExecutor(exec_ctx, nested_loop_join_plan->GetLeftPlan());
99101
auto right = ExecutorFactory::CreateExecutor(exec_ctx, nested_loop_join_plan->GetRightPlan());
100-
auto check_options_set = exec_ctx->GetCheckOptions()->check_options_set_;
101102
if (check_options_set.find(CheckOption::ENABLE_NLJ_CHECK) != check_options_set.end()) {
102103
auto left_init_check_plan = dynamic_cast<const InitCheckPlanNode *>(nested_loop_join_plan->GetLeftPlan().get());
103104
auto right_init_check_plan =
@@ -164,6 +165,12 @@ auto ExecutorFactory::CreateExecutor(ExecutorContext *exec_ctx, const AbstractPl
164165
case PlanType::TopN: {
165166
const auto *topn_plan = dynamic_cast<const TopNPlanNode *>(plan.get());
166167
auto child = ExecutorFactory::CreateExecutor(exec_ctx, topn_plan->GetChildPlan());
168+
if (check_options_set.find(CheckOption::ENABLE_TOPN_CHECK) != check_options_set.end()) {
169+
auto topn_executor = std::make_unique<TopNExecutor>(exec_ctx, topn_plan, nullptr);
170+
auto check = std::make_unique<TopNCheckExecutor>(exec_ctx, topn_plan, std::move(child), topn_executor.get());
171+
topn_executor->SetChildExecutor(std::move(check));
172+
return topn_executor;
173+
}
167174
return std::make_unique<TopNExecutor>(exec_ctx, topn_plan, std::move(child));
168175
}
169176

src/execution/topn_check_executor.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// BusTub
4+
//
5+
// topn_check_executor.cpp
6+
//
7+
// Identification: src/execution/topn_check_executor.cpp
8+
//
9+
// Copyright (c) 2015-2021, Carnegie Mellon University Database Group
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "execution/executors/topn_check_executor.h"
14+
#include "execution/executors/topn_executor.h"
15+
16+
namespace bustub {
17+
18+
TopNCheckExecutor::TopNCheckExecutor(ExecutorContext *exec_ctx, const TopNPlanNode *plan,
19+
std::unique_ptr<AbstractExecutor> &&child_executor, TopNExecutor *topn_executor)
20+
: AbstractExecutor{exec_ctx},
21+
plan_(plan),
22+
child_executor_{std::move(child_executor)},
23+
topn_executor_(topn_executor) {}
24+
25+
void TopNCheckExecutor::Init() {
26+
if (!child_executor_) {
27+
return;
28+
}
29+
prev_ = 0;
30+
// Initialize the child executor
31+
child_executor_->Init();
32+
}
33+
34+
auto TopNCheckExecutor::Next(Tuple *tuple, RID *rid) -> bool {
35+
if (!child_executor_) {
36+
return EXECUTOR_EXHAUSTED;
37+
}
38+
39+
BUSTUB_ASSERT(topn_executor_->GetNumInHeap() <= plan_->GetN(), "Cannot store more than N elements");
40+
if (prev_ > 0 && prev_ < plan_->GetN()) {
41+
BUSTUB_ASSERT(topn_executor_->GetNumInHeap() - prev_ == 1, "Did you implement GetNumInHeap() properly?");
42+
}
43+
prev_ = topn_executor_->GetNumInHeap();
44+
// Emit the next tuple
45+
return child_executor_->Next(tuple, rid);
46+
}
47+
48+
} // namespace bustub

src/execution/topn_executor.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ void TopNExecutor::Init() { throw NotImplementedException("TopNExecutor is not i
1010

1111
auto TopNExecutor::Next(Tuple *tuple, RID *rid) -> bool { return false; }
1212

13+
auto TopNExecutor::GetNumInHeap() -> size_t { throw NotImplementedException("TopNExecutor is not implemented"); };
14+
1315
} // namespace bustub
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// BusTub
4+
//
5+
// topn_check_executor.h
6+
//
7+
// Identification: src/include/execution/executors/topn_check_executor.h
8+
//
9+
// Copyright (c) 2015-2021, Carnegie Mellon University Database Group
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#pragma once
14+
15+
#include <memory>
16+
#include <utility>
17+
18+
#include "execution/executors/abstract_executor.h"
19+
#include "execution/executors/topn_executor.h"
20+
#include "execution/plans/topn_plan.h"
21+
22+
namespace bustub {
23+
24+
/**
25+
* TopNCheckExecutor checks the number of items in topn executor container
26+
*/
27+
class TopNCheckExecutor : public AbstractExecutor {
28+
public:
29+
/**
30+
* Construct a new TopNCheckExecutor instance.
31+
* @param exec_ctx The executor context
32+
* @param plan The TopN plan to be executed
33+
* @param child_executor The topn child executor
34+
*/
35+
TopNCheckExecutor(ExecutorContext *exec_ctx, const TopNPlanNode *plan,
36+
std::unique_ptr<AbstractExecutor> &&child_executor, TopNExecutor *topn_executor);
37+
38+
/** Initialize the TopNCheck */
39+
void Init() override;
40+
41+
/**
42+
* Yield the next tuple from the child executor.
43+
* @param[out] tuple The next tuple produced by the child executor
44+
* @param[out] rid The next tuple RID produced by the child executor
45+
* @return `true` if a tuple was produced, `false` if there are no more tuples
46+
*/
47+
auto Next(Tuple *tuple, RID *rid) -> bool override;
48+
49+
/** @return The output schema for the child executor */
50+
auto GetOutputSchema() const -> const Schema & override { return plan_->OutputSchema(); };
51+
52+
private:
53+
/** TopNCheckExecutor returns `false` when child executor is exhausted */
54+
constexpr static const bool EXECUTOR_EXHAUSTED{false};
55+
56+
/** The TopNPlanNode to be executed */
57+
const TopNPlanNode *plan_;
58+
59+
std::size_t prev_{0};
60+
61+
/** The child executor from which tuples are obtained */
62+
std::unique_ptr<AbstractExecutor> child_executor_;
63+
64+
TopNExecutor *topn_executor_;
65+
};
66+
67+
} // namespace bustub

src/include/execution/executors/topn_executor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#pragma once
1414

1515
#include <memory>
16+
#include <utility>
1617
#include <vector>
1718

1819
#include "execution/executor_context.h"
@@ -49,8 +50,18 @@ class TopNExecutor : public AbstractExecutor {
4950
/** @return The output schema for the topn */
5051
auto GetOutputSchema() const -> const Schema & override { return plan_->OutputSchema(); }
5152

53+
/** Sets new child executor (for testing only) */
54+
void SetChildExecutor(std::unique_ptr<AbstractExecutor> &&child_executor) {
55+
child_executor_ = std::move(child_executor);
56+
}
57+
58+
/** @return The size of top_entries_ container, which will be called on each child_executor->Next(). */
59+
auto GetNumInHeap() -> size_t;
60+
5261
private:
5362
/** The topn plan node to be executed */
5463
const TopNPlanNode *plan_;
64+
/** The child executor from which tuples are obtained */
65+
std::unique_ptr<AbstractExecutor> child_executor_;
5566
};
5667
} // namespace bustub

0 commit comments

Comments
 (0)