Skip to content

Commit 7a50098

Browse files
committed
Project 3 DONE, Leaderboard tasks soon ✨
1 parent c39f10b commit 7a50098

22 files changed

+700
-46
lines changed

src/execution/aggregation_executor.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,54 @@ namespace bustub {
1818

1919
AggregationExecutor::AggregationExecutor(ExecutorContext *exec_ctx, const AggregationPlanNode *plan,
2020
std::unique_ptr<AbstractExecutor> &&child)
21-
: AbstractExecutor(exec_ctx) {}
21+
: AbstractExecutor(exec_ctx),
22+
plan_(plan),
23+
child_(std::move(child)),
24+
aht_(plan_->GetAggregates(), plan_->GetAggregateTypes()),
25+
aht_iterator_(aht_.Begin()) {}
2226

23-
void AggregationExecutor::Init() {}
27+
void AggregationExecutor::Init() {
28+
// BUILD PHASE
29+
child_->Init();
30+
Tuple tuple_;
31+
RID rid_;
2432

25-
auto AggregationExecutor::Next(Tuple *tuple, RID *rid) -> bool { return false; }
33+
while (child_->Next(&tuple_, &rid_)) {
34+
// make the group bys from the group by expressions (the key)
35+
AggregateKey key = MakeAggregateKey(&tuple_);
36+
// get the aggregate values from the aggregate expressions (the value) out of the tuple
37+
AggregateValue value = MakeAggregateValue(&tuple_);
38+
aht_.InsertCombine(key, value);
39+
}
40+
aht_iterator_ = aht_.Begin();
41+
}
42+
43+
auto AggregationExecutor::Next(Tuple *tuple, RID *rid) -> bool {
44+
// ITERATE PHASE
45+
Schema schema(*plan_->output_schema_);
46+
if (aht_iterator_ != aht_.End()) {
47+
// get the group bys from the key
48+
std::vector<Value> values(aht_iterator_.Key().group_bys_);
49+
// for each aggregate, push the aggregate value into the values vector to make the tuple
50+
for (auto &agg : aht_iterator_.Val().aggregates_) {
51+
values.push_back(agg);
52+
}
53+
*tuple = Tuple(values, &schema);
54+
++aht_iterator_;
55+
is_successful = true;
56+
return true;
57+
}
58+
// EMPTY TABLE
59+
if (!is_successful) {
60+
is_successful = true;
61+
if (plan_->GetGroupBys().empty()) {
62+
std::vector<Value> values(aht_.GenerateInitialAggregateValue().aggregates_);
63+
*tuple = Tuple(values, &schema);
64+
return true;
65+
}
66+
}
67+
return false;
68+
}
2669

2770
auto AggregationExecutor::GetChildExecutor() const -> const AbstractExecutor * { return child_.get(); }
2871

src/execution/delete_executor.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,59 @@ namespace bustub {
1818

1919
DeleteExecutor::DeleteExecutor(ExecutorContext *exec_ctx, const DeletePlanNode *plan,
2020
std::unique_ptr<AbstractExecutor> &&child_executor)
21-
: AbstractExecutor(exec_ctx) {}
21+
: AbstractExecutor(exec_ctx), plan_(plan), child_executor_(std::move(child_executor)) {}
2222

23-
void DeleteExecutor::Init() { throw NotImplementedException("DeleteExecutor is not implemented"); }
23+
void DeleteExecutor::Init() {
24+
// Get the table to delete from
25+
table_info_ = exec_ctx_->GetCatalog()->GetTable(plan_->table_oid_);
26+
table_ = table_info_->table_.get();
27+
table_name_ = table_info_->name_;
2428

25-
auto DeleteExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) -> bool { return false; }
29+
// Initialize the child executor
30+
child_executor_->Init();
31+
}
32+
33+
auto DeleteExecutor::Next(Tuple *tuple, RID *rid) -> bool {
34+
// We return only once
35+
if (is_successful_) {
36+
return false;
37+
}
38+
RID rid_;
39+
Tuple tup;
40+
41+
int num_deleted = 0;
42+
43+
while (child_executor_->Next(&tup, &rid_)) {
44+
if (!table_->MarkDelete(rid_, this->GetExecutorContext()->GetTransaction())) {
45+
return false;
46+
}
47+
auto indexes = this->GetExecutorContext()->GetCatalog()->GetTableIndexes(table_name_);
48+
for (auto i : indexes) {
49+
auto key = tup.KeyFromTuple(table_info_->schema_, i->key_schema_, i->index_->GetKeyAttrs());
50+
i->index_->DeleteEntry(key, rid_, this->GetExecutorContext()->GetTransaction());
51+
}
52+
num_deleted++;
53+
}
54+
55+
// prepare schema of one column of type integer
56+
// Schema: "":(INTEGER)
57+
std::vector<Column> cols;
58+
Column col("", INTEGER);
59+
cols.push_back(col);
60+
Schema schema(cols);
61+
62+
// value of only one tuple (num of tuples deleted)
63+
Value val(INTEGER, num_deleted);
64+
std::vector<Value> values;
65+
values.push_back(val);
66+
*tuple = Tuple(values, &schema);
67+
68+
/* RESULT TUPLE: Schema: "":INTEGER
69+
* TUPLE/ROW 0 num_deleted
70+
*/
71+
72+
is_successful_ = true;
73+
return true;
74+
}
2675

2776
} // namespace bustub

src/execution/index_scan_executor.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,25 @@
1313

1414
namespace bustub {
1515
IndexScanExecutor::IndexScanExecutor(ExecutorContext *exec_ctx, const IndexScanPlanNode *plan)
16-
: AbstractExecutor(exec_ctx) {}
16+
: AbstractExecutor(exec_ctx), plan_(plan) {}
1717

18-
void IndexScanExecutor::Init() { throw NotImplementedException("IndexScanExecutor is not implemented"); }
18+
void IndexScanExecutor::Init() {
19+
auto index_info_ = exec_ctx_->GetCatalog()->GetIndex(plan_->GetIndexOid());
20+
index_ = reinterpret_cast<BPlusTreeIndex<GenericKey<4>, RID, GenericComparator<4>> *>(index_info_->index_.get());
21+
iter_ = std::make_unique<IndexIterator<GenericKey<4>, RID, GenericComparator<4>>>(index_->GetBeginIterator());
22+
table_ = exec_ctx_->GetCatalog()->GetTable(index_info_->table_name_)->table_.get();
23+
}
1924

20-
auto IndexScanExecutor::Next(Tuple *tuple, RID *rid) -> bool { return false; }
25+
auto IndexScanExecutor::Next(Tuple *tuple, RID *rid) -> bool {
26+
if (*iter_ == index_->GetEndIterator()) {
27+
return false;
28+
}
29+
*rid = (*(*iter_)).second;
30+
if (!table_->GetTuple(*rid, tuple, this->GetExecutorContext()->GetTransaction())) {
31+
return false;
32+
}
33+
++(*iter_);
34+
return true;
35+
}
2136

2237
} // namespace bustub

src/execution/insert_executor.cpp

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,60 @@ namespace bustub {
1818

1919
InsertExecutor::InsertExecutor(ExecutorContext *exec_ctx, const InsertPlanNode *plan,
2020
std::unique_ptr<AbstractExecutor> &&child_executor)
21-
: AbstractExecutor(exec_ctx) {}
21+
: AbstractExecutor(exec_ctx), plan_(plan), child_executor_(std::move(child_executor)) {}
2222

23-
void InsertExecutor::Init() { throw NotImplementedException("InsertExecutor is not implemented"); }
23+
void InsertExecutor::Init() {
24+
// Get the table to insert into
25+
table_info_ = exec_ctx_->GetCatalog()->GetTable(plan_->table_oid_);
26+
table_ = table_info_->table_.get();
27+
table_name_ = table_info_->name_;
2428

25-
auto InsertExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) -> bool { return false; }
29+
// Initialize the child executor
30+
child_executor_->Init();
31+
}
32+
33+
auto InsertExecutor::Next(Tuple *tuple, RID *rid) -> bool {
34+
// We return only once
35+
if (is_successful_) {
36+
return false;
37+
}
38+
RID rid_;
39+
Tuple tup;
40+
41+
int num_inserted = 0;
42+
43+
while (child_executor_->Next(&tup, &rid_)) {
44+
if (!table_->InsertTuple(tup, &rid_, this->GetExecutorContext()->GetTransaction())) {
45+
return false;
46+
}
47+
auto indexes = this->GetExecutorContext()->GetCatalog()->GetTableIndexes(table_name_);
48+
for (auto i : indexes) {
49+
auto key = tup.KeyFromTuple(table_info_->schema_, i->key_schema_, i->index_->GetKeyAttrs());
50+
i->index_->InsertEntry(key, rid_, this->GetExecutorContext()->GetTransaction());
51+
}
52+
num_inserted++;
53+
}
54+
55+
// prepare schema of one column of type integer
56+
// Schema: "":(INTEGER)
57+
std::vector<Column> cols;
58+
Column col("", INTEGER);
59+
cols.push_back(col);
60+
Schema schema(cols);
61+
62+
// value of only one tuple (num of tuples inserted)
63+
// Value: num_inserted
64+
std::vector<Value> values;
65+
Value val(INTEGER, num_inserted);
66+
values.push_back(val);
67+
68+
Tuple t(values, &schema);
69+
*tuple = t;
70+
/* RESULT TUPLE: Schema: "":INTEGER
71+
* TUPLE/ROW 0 num_inserted */
72+
73+
is_successful_ = true;
74+
return true;
75+
}
2676

2777
} // namespace bustub

src/execution/limit_executor.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@ namespace bustub {
1616

1717
LimitExecutor::LimitExecutor(ExecutorContext *exec_ctx, const LimitPlanNode *plan,
1818
std::unique_ptr<AbstractExecutor> &&child_executor)
19-
: AbstractExecutor(exec_ctx) {}
19+
: AbstractExecutor(exec_ctx), plan_(plan), child_executor_(std::move(child_executor)) {}
2020

21-
void LimitExecutor::Init() { throw NotImplementedException("LimitExecutor is not implemented"); }
21+
void LimitExecutor::Init() { child_executor_->Init(); }
2222

23-
auto LimitExecutor::Next(Tuple *tuple, RID *rid) -> bool { return false; }
23+
auto LimitExecutor::Next(Tuple *tuple, RID *rid) -> bool {
24+
if (num_tuples_ >= plan_->GetLimit()) {
25+
return false;
26+
}
27+
num_tuples_++;
28+
return child_executor_->Next(tuple, rid);
29+
}
2430

2531
} // namespace bustub

src/execution/nested_index_join_executor.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,69 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "execution/executors/nested_index_join_executor.h"
14+
#include "type/value_factory.h"
1415

1516
namespace bustub {
1617

1718
NestIndexJoinExecutor::NestIndexJoinExecutor(ExecutorContext *exec_ctx, const NestedIndexJoinPlanNode *plan,
1819
std::unique_ptr<AbstractExecutor> &&child_executor)
19-
: AbstractExecutor(exec_ctx) {
20+
: AbstractExecutor(exec_ctx), plan_(plan), child_executor_(std::move(child_executor)) {
2021
if (!(plan->GetJoinType() == JoinType::LEFT || plan->GetJoinType() == JoinType::INNER)) {
2122
// Note for 2022 Fall: You ONLY need to implement left join and inner join.
2223
throw bustub::NotImplementedException(fmt::format("join type {} not supported", plan->GetJoinType()));
2324
}
2425
}
2526

26-
void NestIndexJoinExecutor::Init() { throw NotImplementedException("NestIndexJoinExecutor is not implemented"); }
27+
void NestIndexJoinExecutor::Init() {
28+
index_info_ = exec_ctx_->GetCatalog()->GetIndex(plan_->GetIndexOid());
29+
index_ = reinterpret_cast<BPlusTreeIndex<GenericKey<4>, RID, GenericComparator<4>> *>(index_info_->index_.get());
30+
table_info_ = exec_ctx_->GetCatalog()->GetTable(plan_->GetInnerTableOid());
31+
table_ = table_info_->table_.get();
32+
child_executor_->Init();
33+
}
34+
35+
auto NestIndexJoinExecutor::Next(Tuple *tuple, RID *rid) -> bool {
36+
Tuple left_tuple;
37+
RID left_rid;
38+
while (child_executor_->Next(&left_tuple, &left_rid)) {
39+
auto probe_key_schema = index_info_->index_->GetKeySchema();
40+
auto value = plan_->KeyPredicate()->Evaluate(&left_tuple, child_executor_->GetOutputSchema());
41+
std::vector<Value> values;
42+
values.push_back(value);
43+
Tuple probe_key(values, probe_key_schema);
2744

28-
auto NestIndexJoinExecutor::Next(Tuple *tuple, RID *rid) -> bool { return false; }
45+
std::vector<RID> rids;
46+
index_->ScanKey(probe_key, &rids, exec_ctx_->GetTransaction());
47+
// MATCH
48+
if (!rids.empty()) {
49+
for (auto rid : rids) {
50+
Tuple right_tuple;
51+
if (table_->GetTuple(rid, &right_tuple, exec_ctx_->GetTransaction())) {
52+
std::vector<Value> tuple_values;
53+
for (uint32_t i = 0; i < child_executor_->GetOutputSchema().GetColumnCount(); i++) {
54+
tuple_values.push_back(left_tuple.GetValue(&child_executor_->GetOutputSchema(), i));
55+
}
56+
for (uint32_t i = 0; i < table_info_->schema_.GetColumnCount(); i++) {
57+
tuple_values.push_back(right_tuple.GetValue(&table_info_->schema_, i));
58+
}
59+
*tuple = Tuple(tuple_values, &plan_->OutputSchema());
60+
return true;
61+
}
62+
}
63+
}
64+
if (plan_->GetJoinType() == JoinType::LEFT) {
65+
std::vector<Value> tuple_values;
66+
for (uint32_t i = 0; i < child_executor_->GetOutputSchema().GetColumnCount(); i++) {
67+
tuple_values.push_back(left_tuple.GetValue(&child_executor_->GetOutputSchema(), i));
68+
}
69+
for (uint32_t i = 0; i < table_info_->schema_.GetColumnCount(); i++) {
70+
tuple_values.push_back(ValueFactory::GetNullValueByType(table_info_->schema_.GetColumn(i).GetType()));
71+
}
72+
*tuple = Tuple(tuple_values, &plan_->OutputSchema());
73+
return true;
74+
}
75+
}
76+
return false;
77+
}
2978

3079
} // namespace bustub

0 commit comments

Comments
 (0)