Skip to content

Commit

Permalink
Execution Engine (#37)
Browse files Browse the repository at this point in the history
Cleans up existing code and adds an execution engine to the system. Students are expected to implement the executors.
  • Loading branch information
lmwnshn committed Oct 21, 2019
1 parent 71636aa commit 96ccf62
Show file tree
Hide file tree
Showing 42 changed files with 2,645 additions and 378 deletions.
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
file(GLOB_RECURSE bustub_sources ${PROJECT_SOURCE_DIR}/src/*/*.cpp)
# This is hacky :(
file(GLOB_RECURSE bustub_sources ${PROJECT_SOURCE_DIR}/src/*/*.cpp ${PROJECT_SOURCE_DIR}/src/*/*/*.cpp)
add_library(bustub_shared SHARED ${bustub_sources})

######################################################################################################################
Expand Down
126 changes: 126 additions & 0 deletions src/catalog/table_generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "catalog/table_generator.h"

#include <algorithm>
#include <random>
#include <vector>

namespace bustub {

template <typename CppType>
std::vector<Value> TableGenerator::GenNumericValues(ColumnInsertMeta *col_meta, uint32_t count) {
std::vector<Value> values;
if (col_meta->dist_ == Dist::Serial) {
for (uint32_t i = 0; i < count; i++) {
values.emplace_back(Value(col_meta->type_, static_cast<CppType>(col_meta->serial_counter_)));
col_meta->serial_counter_ += 1;
}
return values;
}
std::default_random_engine generator;
// TODO(Amadou): Break up in two branches if this is too weird.
std::conditional_t<std::is_integral_v<CppType>, std::uniform_int_distribution<CppType>,
std::uniform_real_distribution<CppType>>
distribution(static_cast<CppType>(col_meta->min_), static_cast<CppType>(col_meta->max_));
for (uint32_t i = 0; i < count; i++) {
values.emplace_back(Value(col_meta->type_, distribution(generator)));
}
return values;
}

std::vector<Value> TableGenerator::MakeValues(ColumnInsertMeta *col_meta, uint32_t count) {
std::vector<Value> values;
switch (col_meta->type_) {
case TypeId::TINYINT:
return GenNumericValues<int8_t>(col_meta, count);
case TypeId::SMALLINT:
return GenNumericValues<int16_t>(col_meta, count);
case TypeId::INTEGER:
return GenNumericValues<int32_t>(col_meta, count);
case TypeId::BIGINT:
return GenNumericValues<int64_t>(col_meta, count);
case TypeId::DECIMAL:
return GenNumericValues<double>(col_meta, count);
default:
UNREACHABLE("Not yet implemented");
}
}

void TableGenerator::FillTable(TableMetadata *info, TableInsertMeta *table_meta) {
uint32_t num_inserted = 0;
uint32_t batch_size = 128;
while (num_inserted < table_meta->num_rows_) {
std::vector<std::vector<Value>> values;
uint32_t num_values = std::min(batch_size, table_meta->num_rows_ - num_inserted);
for (auto &col_meta : table_meta->col_meta_) {
values.emplace_back(MakeValues(&col_meta, num_values));
}
for (uint32_t i = 0; i < num_values; i++) {
std::vector<Value> entry;
entry.reserve(values.size());
for (const auto &col : values) {
entry.emplace_back(col[i]);
}
RID rid;
bool inserted = info->table_->InsertTuple(Tuple(entry, &info->schema_), &rid, exec_ctx_->GetTransaction());
BUSTUB_ASSERT(inserted, "Sequential insertion cannot fail");
num_inserted++;
}
// exec_ctx_->GetBufferPoolManager()->FlushAllPages();
}
LOG_INFO("Wrote %d tuples to table %s.", num_inserted, table_meta->name_);
}

void TableGenerator::GenerateTestTables() {
/**
* This array configures each of the test tables. Each able is configured
* with a name, size, and schema. We also configure the columns of the table. If
* you add a new table, set it up here.
*/
std::vector<TableInsertMeta> insert_meta{
// The empty table
{"empty_table", 0, {{"colA", TypeId::INTEGER, false, Dist::Serial, 0, 0}}},

// Table 1
{"test_1",
TEST1_SIZE,
{{"colA", TypeId::INTEGER, false, Dist::Serial, 0, 0},
{"colB", TypeId::INTEGER, false, Dist::Uniform, 0, 9},
{"colC", TypeId::INTEGER, false, Dist::Uniform, 0, 9999},
{"colD", TypeId::INTEGER, false, Dist::Uniform, 0, 99999}}},

// Table 2
{"test_2",
TEST2_SIZE,
{{"col1", TypeId::SMALLINT, false, Dist::Serial, 0, 0},
{"col2", TypeId::INTEGER, true, Dist::Uniform, 0, 9},
{"col3", TypeId::BIGINT, false, Dist::Uniform, 0, 1024},
{"col4", TypeId::INTEGER, true, Dist::Uniform, 0, 2048}}},

// Empty table with two columns
{"empty_table2",
0,
{{"colA", TypeId::INTEGER, false, Dist::Serial, 0, 0}, {"colB", TypeId::INTEGER, false, Dist::Uniform, 0, 9}}},

// Empty table with two columns
{"empty_table3",
0,
{{"outA", TypeId::INTEGER, false, Dist::Serial, 0, 0}, {"outB", TypeId::INTEGER, false, Dist::Uniform, 0, 9}}},
};

for (auto &table_meta : insert_meta) {
// Create Schema
std::vector<Column> cols{};
cols.reserve(table_meta.col_meta_.size());
for (const auto &col_meta : table_meta.col_meta_) {
if (col_meta.type_ != TypeId::VARCHAR) {
cols.emplace_back(col_meta.name_, col_meta.type_);
} else {
cols.emplace_back(col_meta.name_, col_meta.type_, TEST_VARLEN_SIZE);
}
}
Schema schema(cols);
auto info = exec_ctx_->GetCatalog()->CreateTable(exec_ctx_->GetTransaction(), table_meta.name_, schema);
FillTable(info, &table_meta);
}
}
} // namespace bustub
62 changes: 62 additions & 0 deletions src/execution/executor_factory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===----------------------------------------------------------------------===//
//
// BusTub
//
// executor_factory.cpp
//
// Identification: src/execution/executor_factory.cpp
//
// Copyright (c) 2015-2019, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "execution/executor_factory.h"

#include <memory>
#include <utility>

#include "execution/executors/abstract_executor.h"
#include "execution/executors/aggregation_executor.h"
#include "execution/executors/hash_join_executor.h"
#include "execution/executors/insert_executor.h"
#include "execution/executors/seq_scan_executor.h"

namespace bustub {
std::unique_ptr<AbstractExecutor> ExecutorFactory::CreateExecutor(ExecutorContext *exec_ctx,
const AbstractPlanNode *plan) {
switch (plan->GetType()) {
// Create a new sequential scan executor.
case PlanType::SeqScan: {
return std::make_unique<SeqScanExecutor>(exec_ctx, dynamic_cast<const SeqScanPlanNode *>(plan));
}

// Create a new insert executor.
case PlanType::Insert: {
auto insert_plan = dynamic_cast<const InsertPlanNode *>(plan);
auto child_executor =
insert_plan->IsRawInsert() ? nullptr : ExecutorFactory::CreateExecutor(exec_ctx, insert_plan->GetChildPlan());
return std::make_unique<InsertExecutor>(exec_ctx, insert_plan, std::move(child_executor));
}

// Create a new hash join executor.
case PlanType::HashJoin: {
auto join_plan = dynamic_cast<const HashJoinPlanNode *>(plan);
auto left_executor = ExecutorFactory::CreateExecutor(exec_ctx, join_plan->GetLeftPlan());
auto right_executor = ExecutorFactory::CreateExecutor(exec_ctx, join_plan->GetRightPlan());
return std::make_unique<HashJoinExecutor>(exec_ctx, join_plan, std::move(left_executor),
std::move(right_executor));
}

// Create a new aggregation executor.
case PlanType::Aggregation: {
auto agg_plan = dynamic_cast<const AggregationPlanNode *>(plan);
auto child_executor = ExecutorFactory::CreateExecutor(exec_ctx, agg_plan->GetChildPlan());
return std::make_unique<AggregationExecutor>(exec_ctx, agg_plan, std::move(child_executor));
}

default: {
BUSTUB_ASSERT(false, "Unsupported plan type.");
}
}
}
} // namespace bustub
17 changes: 13 additions & 4 deletions src/include/catalog/column.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "type/type.h"

namespace bustub {
class AbstractExpression;

class Column {
friend class Schema;
Expand All @@ -30,9 +31,10 @@ class Column {
* Non-variable-length constructor for creating a Column.
* @param column_name name of the column
* @param type type of the column
* @param expr expression used to create this column
*/
Column(std::string column_name, TypeId type)
: column_name_(std::move(column_name)), column_type_(type), fixed_length_(TypeSize(type)) {
Column(std::string column_name, TypeId type, const AbstractExpression *expr = nullptr)
: column_name_(std::move(column_name)), column_type_(type), fixed_length_(TypeSize(type)), expr_{expr} {
BUSTUB_ASSERT(type != TypeId::VARCHAR, "Wrong constructor for VARCHAR type.");
}

Expand All @@ -41,9 +43,10 @@ class Column {
* @param column_name name of the column
* @param type type of column
* @param length length of the varlen
* @param expr expression used to create this column
*/
Column(std::string column_name, TypeId type, uint32_t length)
: column_name_(std::move(column_name)), column_type_(type), fixed_length_(TypeSize(type)) {
Column(std::string column_name, TypeId type, uint32_t length, const AbstractExpression *expr = nullptr)
: column_name_(std::move(column_name)), column_type_(type), fixed_length_(TypeSize(type)), expr_{expr} {
BUSTUB_ASSERT(type == TypeId::VARCHAR, "Wrong constructor for non-VARCHAR type.");
}

Expand Down Expand Up @@ -76,6 +79,9 @@ class Column {
/** @return a string representation of this column */
std::string ToString() const;

/** @return the expression used to create this column */
const AbstractExpression *GetExpr() const { return expr_; }

private:
/**
* Return the size in bytes of the type.
Expand Down Expand Up @@ -119,6 +125,9 @@ class Column {

/** Column offset in the tuple. */
uint32_t column_offset_{0};

/** Expression used to create this column **/
const AbstractExpression *expr_;
};

} // namespace bustub
4 changes: 2 additions & 2 deletions src/include/catalog/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ class Schema {
}

/** @return all the columns in the schema */
const std::vector<Column> &GetColumns() { return columns_; }
const std::vector<Column> &GetColumns() const { return columns_; }

/**
* Returns a specific column from the schema.
* @param col_idx index of requested column
* @return requested column
*/
const Column &GetColumn(const uint32_t col_idx) { return columns_[col_idx]; }
const Column &GetColumn(const uint32_t col_idx) const { return columns_[col_idx]; }

/**
* @param col_name name of the wanted column
Expand Down
78 changes: 78 additions & 0 deletions src/include/catalog/simple_catalog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#pragma once

#include <memory>
#include <string>
#include <unordered_map>
#include <utility>

#include "buffer/buffer_pool_manager.h"
#include "catalog/schema.h"
#include "storage/index/index.h"
#include "storage/table/table_heap.h"

namespace bustub {

/**
* Typedefs
*/
using table_oid_t = uint32_t;
using column_oid_t = uint32_t;

/**
* Metadata about a table.
*/
struct TableMetadata {
TableMetadata(Schema schema, std::string name, std::unique_ptr<TableHeap> &&table, table_oid_t oid)
: schema_(std::move(schema)), name_(std::move(name)), table_(std::move(table)), oid_(oid) {}
Schema schema_;
std::string name_;
std::unique_ptr<TableHeap> table_;
table_oid_t oid_;
};

/**
* SimpleCatalog is a non-persistent catalog that is designed for the executor to use.
* It handles table creation and table lookup.
*/
class SimpleCatalog {
public:
/**
* Creates a new catalog object.
* @param bpm the buffer pool manager backing tables created by this catalog
* @param lock_manager the lock manager in use by the system
* @param log_manager the log manager in use by the system
*/
SimpleCatalog(BufferPoolManager *bpm, LockManager *lock_manager, LogManager *log_manager)
: bpm_{bpm}, lock_manager_{lock_manager}, log_manager_{log_manager} {}

/**
* Create a new table and return its metadata.
* @param txn the transaction in which the table is being created
* @param table_name the name of the new table
* @param schema the schema of the new table
* @return a pointer to the metadata of the new table
*/
TableMetadata *CreateTable(Transaction *txn, const std::string &table_name, const Schema &schema) {
BUSTUB_ASSERT(names_.count(table_name) == 0, "Table names should be unique!");
return nullptr;
}

/** @return table metadata by name */
TableMetadata *GetTable(const std::string &table_name) { return nullptr; }

/** @return table metadata by oid */
TableMetadata *GetTable(table_oid_t table_oid) { return nullptr; }

private:
[[maybe_unused]] BufferPoolManager *bpm_;
[[maybe_unused]] LockManager *lock_manager_;
[[maybe_unused]] LogManager *log_manager_;

/** tables_ : table identifiers -> table metadata. Note that tables_ owns all table metadata. */
std::unordered_map<table_oid_t, std::unique_ptr<TableMetadata>> tables_;
/** names_ : table names -> table identifiers */
std::unordered_map<std::string, table_oid_t> names_;
/** The next table identifier to be used. */
std::atomic<table_oid_t> next_table_oid_{0};
};
} // namespace bustub
Loading

0 comments on commit 96ccf62

Please sign in to comment.