目录
- 实验准备
- 实验测试
- Task 1: CREATING A CATALOG TABLE
SQL 执行是由数据库解析器转化为一个由多个 executor 组成的 Query Plan 来完成的,本实验选择了火山模型来完成 query execution,这一次的 project 就是实现各种 exeutor,从而可以通过组装这些 executor 来完成数据库的查询、插入等操作。
火山模型如下图所示:
SQL 被转换为一系列 executor 的执行,首先会对每个 executor 调用 Init()
方法来进行初始化,之后上层的 executor 通过调用下层的 executor 的 Next()
方法来获取一个 tuple,每一个 executor 都是如此,就类似一个火山一样,数据从底部逐渐向上喷发。
实验准备
- 官方说明:https://15445.courses.cs.cmu.edu/fall2019/project3/
实验测试
Task 1:
cd build
make catalog_test
./test/catalog_test
Task 2~3:
cd build
make executor_test
./test/executor_test
Task 1: CREATING A CATALOG TABLE
这是一个热身任务,较为简单。
DB 内部通过维护 catalog 来维护数据库的元数据(比如 table 的创建与获取等),这个 task 需要实现 SimpleCatalog
的 CreateTable()
和 GetTable()
方法。
数据库的 table 主要包含 name 和 oid 两个属性,catalog 通过 table_
属性维护 table 的 name 与 oid 的映射关系,其 GetTable()
方法需要同时支持对这两个的查询:
GetTable(const std::string &table_name)
:通过 name 来获取 tableGetTable(table_oid_t table_oid)
:通过 oid 来获取 table
一个 table 的元数据如下:
using table_oid_t = uint32_t;
using column_oid_t = uint32_t;
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_;
};
Catalog 的关键属性字段有如下:
tables_
:记录 table oid -> table metadata 的映射names_
:记录 table name -> table oid 的映射next_table_oid
:记录创建下一个 table 时可以分配的 oid
catalog 创建 table 的实现:
/**
* 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
*/
auto CreateTable(Transaction *txn, const std::string &table_name, const Schema &schema) -> TableMetadata * {
BUSTUB_ASSERT(names_.count(table_name) == 0, "Table names should be unique!");
table_oid_t table_oid = next_table_oid_++; // 这行代码很妙,在自增了 atomic 变量的同时将旧值返回给了 oid
auto *tableHeap = new TableHeap(bpm_, lock_manager_, log_manager_, txn);
auto *tableMetadata = new TableMetadata(schema, table_name, std::unique_ptr<TableHeap>(tableHeap), table_oid);
tables_.insert({table_oid, std::unique_ptr<TableMetadata>(tableMetadata)});
names_.insert({table_name, table_oid});
return tableMetadata;
}
catalog 查询 table 的实现:
/** @return table metadata by name */
auto GetTable(const std::string &table_name) -> TableMetadata * {
const table_oid_t table_oid = names_.at(table_name);
const auto& table = tables_.at(table_oid);
return table.get();
}
/** @return table metadata by oid */
auto GetTable(table_oid_t table_oid) -> TableMetadata * {
const auto &table = tables_.at(table_oid);
return table.get();
}