未验证 提交 291eb33a 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

Docs (#201)

### What problem were solved in this pull request?

Issue Number: close #191 

Problem:
doxy文档的首页没有描述

### What is changed and how it works?
增加首页描述信息,写在了main.cpp中

### Other information
上级 f4e52131
......@@ -189,3 +189,11 @@ int main(int argc, char **argv)
delete g_server;
}
/**
* @mainpage MiniOB
*
* MiniOB 是 OceanBase 与华中科技大学联合开发的、面向"零"基础同学的数据库入门学习项目。
*
* MiniOB 设计的目标是面向在校学生、数据库从业者、爱好者,或者对基础技术有兴趣的爱好者, 整体代码量少,易于上手并学习, 是一个系统性的数据库学习项目。miniob 设置了一系列由浅入深的题目,以帮助同学们"零"基础入门, 让同学们快速了解数据库并深入学习数据库内核,期望通过相关训练之后,能够熟练掌握数据库内核模块的功能与协同关系, 并能够在使用数据库时,设计出高效的 SQL 。miniob 为了更好的学习数据库实现原理, 对诸多模块都做了简化,比如不考虑并发操作, 安全特性, 复杂的事物管理等功能。
*/
\ No newline at end of file
......@@ -18,7 +18,15 @@ See the Mulan PSL v2 for more details. */
class SQLStageEvent;
/**
* @defgroup Executor
* @brief 一些SQL语句不会生成对应的执行计划,直接使用Executor来执行,比如DDL语句
*/
/**
* @brief 执行器
* @ingroup Executor
*/
class CommandExecutor
{
public:
......
......@@ -18,6 +18,11 @@ See the Mulan PSL v2 for more details. */
class SQLStageEvent;
/**
* @brief 创建索引的执行器
* @ingroup Executor
* @note 创建索引时不能做其它操作。MiniOB当前不完善,没有对一些并发做控制,包括schema的并发。
*/
class CreateIndexExecutor
{
public:
......
......@@ -18,6 +18,10 @@ See the Mulan PSL v2 for more details. */
class SQLStageEvent;
/**
* @brief 创建表的执行器
* @ingroup Executor
*/
class CreateTableExecutor
{
public:
......
......@@ -18,6 +18,10 @@ See the Mulan PSL v2 for more details. */
class SQLStageEvent;
/**
* @brief 描述表的执行器
* @ingroup Executor
*/
class DescTableExecutor
{
public:
......
......@@ -21,6 +21,10 @@ See the Mulan PSL v2 for more details. */
#include "sql/executor/sql_result.h"
#include "session/session.h"
/**
* @brief Help语句执行器
* @ingroup Executor
*/
class HelpExecutor
{
public:
......
......@@ -22,6 +22,11 @@ See the Mulan PSL v2 for more details. */
#include "session/session.h"
#include "storage/db/db.h"
/**
* @brief 显示所有表的执行器
* @ingroup Executor
* @note 与CreateIndex类似,不处理并发
*/
class ShowTablesExecutor
{
public:
......
......@@ -22,6 +22,12 @@ See the Mulan PSL v2 for more details. */
class Session;
/**
* @brief SQL执行结果
* @details 如果当前SQL生成了执行计划,那么在返回客户端时,调用执行计划返回结果。
* 否则返回的结果就是当前SQL的执行结果,比如DDL语句,通过return_code和state_string来描述。
* 如果出现了一些错误,也可以通过return_code和state_string来获取信息。
*/
class SqlResult
{
public:
......@@ -63,9 +69,9 @@ public:
RC next_tuple(Tuple *&tuple);
private:
Session *session_ = nullptr;
std::unique_ptr<PhysicalOperator> operator_;
TupleSchema tuple_schema_;
Session *session_ = nullptr; ///< 当前所属会话
std::unique_ptr<PhysicalOperator> operator_; ///< 执行计划
TupleSchema tuple_schema_; ///< 返回的表头信息。可能有也可能没有
RC return_code_ = RC::SUCCESS;
std::string state_string_;
};
......@@ -22,6 +22,10 @@ See the Mulan PSL v2 for more details. */
#include "session/session.h"
#include "storage/trx/trx.h"
/**
* @brief 事务开始语句的执行器
* @ingroup Executor
*/
class TrxBeginExecutor
{
public:
......
......@@ -22,6 +22,10 @@ See the Mulan PSL v2 for more details. */
#include "storage/trx/trx.h"
#include "sql/stmt/stmt.h"
/**
* @brief 事务结束的执行器,可以是提交或回滚
* @ingroup Executor
*/
class TrxEndExecutor
{
public:
......
......@@ -22,19 +22,29 @@ See the Mulan PSL v2 for more details. */
class Tuple;
/**
* @defgroup Expression
* @brief 表达式
*/
/**
* @brief 表达式类型
* @ingroup Expression
*/
enum class ExprType
{
NONE,
FIELD,
VALUE,
CAST,
COMPARISON,
CONJUNCTION,
FIELD, ///< 字段。在实际执行时,根据行数据内容提取对应字段的值
VALUE, ///< 常量值
CAST, ///< 需要做类型转换的表达式
COMPARISON, ///< 需要做比较的表达式
CONJUNCTION, ///< 多个表达式使用同一种关系(AND或OR)来联结
};
/**
* 表达式的抽象描述
* 在SQL的元素中,任何需要得出值的元素都可以使用表达式来描述
* @brief 表达式的抽象描述
* @ingroup Expression
* @details 在SQL的元素中,任何需要得出值的元素都可以使用表达式来描述
* 比如获取某个字段的值、比较运算、类型转换
* 当然还有一些当前没有实现的表达式,比如算术运算。
*
......@@ -49,22 +59,27 @@ public:
virtual ~Expression() = default;
/**
* 根据具体的tuple,来计算当前表达式的值
* @brief 根据具体的tuple,来计算当前表达式的值。tuple有可能是一个具体某个表的行数据
*/
virtual RC get_value(const Tuple &tuple, TupleCell &cell) const = 0;
/**
* 表达式的类型
* @brief 表达式的类型
* 可以根据表达式类型来转换为具体的子类
*/
virtual ExprType type() const = 0;
/**
* 表达式值的类型
* @brief 表达式值的类型
* @details 一个表达式运算出结果后,只有一个值
*/
virtual AttrType value_type() const = 0;
};
/**
* @brief 字段表达式
* @ingroup Expression
*/
class FieldExpr : public Expression
{
public:
......@@ -111,6 +126,10 @@ private:
Field field_;
};
/**
* @brief 常量值表达式
* @ingroup Expression
*/
class ValueExpr : public Expression
{
public:
......@@ -166,6 +185,10 @@ private:
TupleCell tuple_cell_;
};
/**
* @brief 类型转换表达式
* @ingroup Expression
*/
class CastExpr : public Expression
{
public:
......@@ -192,6 +215,10 @@ private:
AttrType cast_type_;
};
/**
* @brief 比较表达式
* @ingroup Expression
*/
class ComparisonExpr : public Expression
{
public:
......@@ -240,6 +267,8 @@ private:
};
/**
* @brief 联结表达式
* @ingroup Expression
* 多个表达式使用同一种关系(AND或OR)来联结
* 当前miniob仅有AND操作
*/
......
......@@ -18,7 +18,8 @@ See the Mulan PSL v2 for more details. */
#include "storage/table/table.h"
#include "storage/field/field_meta.h"
class TupleCellSpec {
class TupleCellSpec
{
public:
TupleCellSpec(const char *table_name, const char *field_name, const char *alias = nullptr);
TupleCellSpec(const char *alias);
......
......@@ -52,10 +52,10 @@ enum CompOp
enum AttrType
{
UNDEFINED,
CHARS, /// 字符串类型
INTS, /// 整数类型(4字节)
FLOATS, /// 浮点数类型(4字节)
BOOLEANS, /// boolean类型,当前不是由parser解析出来的,是程序内部使用的
CHARS, ///< 字符串类型
INTS, ///< 整数类型(4字节)
FLOATS, ///< 浮点数类型(4字节)
BOOLEANS, ///< boolean类型,当前不是由parser解析出来的,是程序内部使用的
};
/**
......@@ -64,14 +64,14 @@ enum AttrType
*/
struct Value
{
AttrType type; /// 属性的类型
int int_value; /// 如果是整数,这个值就有意义
float float_value; /// 如果是浮点数,这个值就有意义
bool bool_value; /// 如果是boolean值,这个值就有意义
std::string string_value; /// 如果是字符串,这个值就有意义
AttrType type; ///< 属性的类型
int int_value; ///< 如果是整数,这个值就有意义
float float_value; ///< 如果是浮点数,这个值就有意义
bool bool_value; ///< 如果是boolean值,这个值就有意义
std::string string_value; ///< 如果是字符串,这个值就有意义
const char *data() const; /// 获取值的内存地址
int length(); /// 获取占用的内存长度
const char *data() const; ///< 获取值的内存地址
int length(); ///< 获取占用的内存长度
};
/**
......@@ -105,9 +105,9 @@ struct Condition
*/
struct Selects
{
std::vector<RelAttr> attributes; /// attributes in select clause
std::vector<std::string> relations; /// 查询的表
std::vector<Condition> conditions; /// 查询条件,使用AND串联起来多个条件
std::vector<RelAttr> attributes; ///< attributes in select clause
std::vector<std::string> relations; ///< 查询的表
std::vector<Condition> conditions; ///< 查询条件,使用AND串联起来多个条件
};
/**
......@@ -116,8 +116,8 @@ struct Selects
*/
struct Inserts
{
std::string relation_name; /// Relation to insert into
std::vector<Value> values; /// 要插入的值
std::string relation_name; ///< Relation to insert into
std::vector<Value> values; ///< 要插入的值
};
/**
......@@ -135,9 +135,9 @@ struct Deletes
*/
struct Updates
{
std::string relation_name; // Relation to update
std::string attribute_name; /// 更新的字段,仅支持一个字段
Value value; /// 更新的值,仅支持一个字段
std::string relation_name; ///< Relation to update
std::string attribute_name; ///< 更新的字段,仅支持一个字段
Value value; ///< 更新的值,仅支持一个字段
std::vector<Condition> conditions;
};
......@@ -149,9 +149,9 @@ struct Updates
*/
struct AttrInfo
{
AttrType type; /// Type of attribute
std::string name; /// Attribute name
size_t length; /// Length of attribute
AttrType type; ///< Type of attribute
std::string name; ///< Attribute name
size_t length; ///< Length of attribute
};
/**
......@@ -191,8 +191,8 @@ struct CreateIndex
*/
struct DropIndex
{
std::string index_name; // Index name
std::string relation_name; // Relation name
std::string index_name; ///< Index name
std::string relation_name; ///< Relation name
};
/**
......
......@@ -47,10 +47,13 @@ class DiskBufferPool;
/**
* @brief BufferPool的文件第一个页面,存放一些元数据信息,包括了后面每页的分配信息。
* @ingroup BufferPool
* @details
* @code
* TODO 1. 当前的做法,只能分配比较少的页面,你可以扩展一下,支持更多的页面或无限多的页面吗?
* 可以参考Linux ext(n)和Windows NTFS等文件系统
* 2. 当前使用bitmap存放页面分配情况,但是这种方法在页面非常多的时候,查找空闲页面的
* 效率非常低,你有办法优化吗?
* @endcode
*/
struct BPFileHeader
{
......@@ -69,6 +72,10 @@ struct BPFileHeader
/**
* @brief 管理页面Frame
* @ingroup BufferPool
* @details 管理内存中的页帧。内存是有限的,内存中能够存放的页帧个数也是有限的。
* 当内存中的页帧不够用时,需要从内存中淘汰一些页帧,以便为新的页帧腾出空间。
* 这个管理器负责为所有的BufferPool提供页帧管理服务,也就是所有的BufferPool磁盘文件
* 在访问时都使用这个管理器映射到内存。
*/
class BPFrameManager
{
......@@ -78,10 +85,30 @@ public:
RC init(int pool_num);
RC cleanup();
/**
* @brief 获取指定的页面
*
* @param file_desc 文件描述符,也可以当做buffer pool文件的标识
* @param page_num 页面号
* @return Frame* 页帧指针
*/
Frame *get(int file_desc, PageNum page_num);
/**
* @brief 列出所有指定文件的页面
*
* @param file_desc 文件描述符
* @return std::list<Frame *> 页帧列表
*/
std::list<Frame *> find_list(int file_desc);
/**
* @brief 分配一个新的页面
*
* @param file_desc 文件描述符
* @param page_num 页面编号
* @return Frame* 页帧指针
*/
Frame *alloc(int file_desc, PageNum page_num);
/**
......
......@@ -49,6 +49,14 @@ private:
/**
* @brief 页帧
* @ingroup BufferPool
* @details 页帧是磁盘文件在内存中的表示。磁盘文件按照页面来操作,操作之前先映射到内存中,
* 将磁盘数据读取到内存中,也就是页帧。
*
* 当某个页面被淘汰时,如果有些内容曾经变更过,那么就需要将这些内容刷新到磁盘上。这里有
* 一个dirty标识,用来标识页面是否被修改过。
*
* 为了防止在使用过程中页面被淘汰,这里使用了pin count,当页面被使用时,pin count会增加,
* 当页面不再使用时,pin count会减少。当pin count为0时,页面可以被淘汰。
*/
class Frame
{
......@@ -59,8 +67,8 @@ public:
}
/**
* reinit 和 reset 在 MemPoolSimple 中使用
* 在 MemPoolSimple 分配和释放一个Frame对象时,不会调用构造函数和析构函数,
* @brief reinit 和 reset 在 MemPoolSimple 中使用
* @details 在 MemPoolSimple 分配和释放一个Frame对象时,不会调用构造函数和析构函数,
* 而是调用reinit和reset。
*/
void reinit()
......@@ -86,7 +94,7 @@ public:
void access();
/**
* 标记指定页面为“脏”页。如果修改了页面的内容,则应调用此函数,
* @brief 标记指定页面为“脏”页。如果修改了页面的内容,则应调用此函数,
* 以便该页面被淘汰出缓冲区时系统将新的页面数据写入磁盘文件
*/
void mark_dirty() { dirty_ = true; }
......@@ -98,13 +106,13 @@ public:
bool can_purge() { return pin_count_.load() == 0; }
/**
* 给当前页帧增加引用计数
* @brief 给当前页帧增加引用计数
* pin通常都会加着frame manager锁来访问
*/
void pin();
/**
* 释放一个当前页帧的引用计数
* @brief 释放一个当前页帧的引用计数
* 与pin对应,但是通常不会加着frame manager的锁来访问
*/
int unpin();
......
......@@ -20,13 +20,9 @@ See the Mulan PSL v2 for more details. */
using TrxID = int32_t;
static constexpr int BP_INVALID_PAGE_NUM = -1;
static constexpr int INVALID_TRX_ID = -1;
static constexpr int INVALID_LSN = -1;
static constexpr PageNum BP_HEADER_PAGE = 0;
static constexpr int LOG_BUFFER_SIZE = 1<<10; // TODO move to log record
static constexpr const int BP_PAGE_SIZE = (1 << 13);
static constexpr const int BP_PAGE_DATA_SIZE = (BP_PAGE_SIZE - sizeof(PageNum) - sizeof(LSN));
......
......@@ -31,7 +31,7 @@ See the Mulan PSL v2 for more details. */
/**
* @brief B+树的实现
* @defgroup B+Tree
* @defgroup BPlusTree
*/
#define EMPTY_RID_PAGE_NUM -1 // TODO remove me
......@@ -39,7 +39,7 @@ See the Mulan PSL v2 for more details. */
/**
* @brief B+树的操作类型
* @ingroup B+Tree
* @ingroup BPlusTree
*/
enum class BplusTreeOperationType
{
......@@ -50,7 +50,7 @@ enum class BplusTreeOperationType
/**
* @brief 属性比较
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class AttrComparator
{
......@@ -92,7 +92,7 @@ private:
/**
* @brief 键值比较
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class KeyComparator
{
......@@ -125,7 +125,7 @@ private:
/**
* @brief 属性打印,调试使用
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class AttrPrinter
{
......@@ -174,7 +174,7 @@ private:
/**
* @brief 键值打印,调试使用
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class KeyPrinter
{
......@@ -205,7 +205,7 @@ private:
/**
* @brief the meta information of bplus tree
* @ingroup B+Tree
* @ingroup BPlusTree
* @details this is the first page of bplus tree.
* only one field can be supported, can you extend it to multi-fields?
*/
......@@ -216,12 +216,12 @@ struct IndexFileHeader
memset(this, 0, sizeof(IndexFileHeader));
root_page = BP_INVALID_PAGE_NUM;
}
PageNum root_page;
int32_t internal_max_size;
int32_t leaf_max_size;
int32_t attr_length;
int32_t key_length; // attr length + sizeof(RID)
AttrType attr_type;
PageNum root_page; ///< 根节点在磁盘中的页号
int32_t internal_max_size; ///< 内部节点最大的键值对数
int32_t leaf_max_size; ///< 叶子节点最大的键值对数
int32_t attr_length; ///< 键值的长度
int32_t key_length; ///< attr length + sizeof(RID)
AttrType attr_type; ///< 键值的类型
const std::string to_string()
{
......@@ -240,9 +240,11 @@ struct IndexFileHeader
/**
* @brief the common part of page describtion of bplus tree
* @ingroup B+Tree
* @ingroup BPlusTree
* @code
* storage format:
* | page type | item number | parent page id |
* @endcode
*/
struct IndexNode
{
......@@ -255,11 +257,12 @@ struct IndexNode
/**
* @brief leaf page of bplus tree
* @ingroup B+Tree
* @ingroup BPlusTree
* @code
* storage format:
* | common header | prev page id | next page id |
* | key0, rid0 | key1, rid1 | ... | keyn, ridn |
*
* @endcode
* the key is in format: the key value of record and rid.
* so the key in leaf page must be unique.
* the value is rid.
......@@ -278,11 +281,12 @@ struct LeafIndexNode : public IndexNode
/**
* @brief internal page of bplus tree
* @ingroup B+Tree
* @ingroup BPlusTree
* @code
* storage format:
* | common header |
* | key(0),page_id(0) | key(1), page_id(1) | ... | key(n), page_id(n) |
*
* @endcode
* the first key is ignored(key0).
* so it will waste space, can you fix this?
*/
......@@ -298,7 +302,7 @@ struct InternalIndexNode : public IndexNode
/**
* @brief IndexNode 仅作为数据在内存或磁盘中的表示
* @ingroup B+Tree
* @ingroup BPlusTree
* IndexNodeHandler 负责对IndexNode做各种操作。
* 作为一个类来说,虚函数会影响“结构体”真实的内存布局,所以将数据存储与操作分开
*/
......@@ -337,7 +341,7 @@ protected:
/**
* @brief 叶子节点的操作
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class LeafIndexNodeHandler : public IndexNodeHandler
{
......@@ -388,7 +392,7 @@ private:
/**
* @brief 内部节点的操作
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class InternalIndexNodeHandler : public IndexNodeHandler
{
......@@ -453,7 +457,7 @@ private:
/**
* @brief B+树的实现
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class BplusTreeHandler
{
......@@ -587,7 +591,7 @@ private:
/**
* @brief B+树的扫描器
* @ingroup B+Tree
* @ingroup BPlusTree
*/
class BplusTreeScanner
{
......
......@@ -29,8 +29,6 @@ class Table;
* @brief 这里负责管理在一个文件上表记录(行)的组织/管理
* @defgroup RecordManager
*
* @file record_manager.h
*
* @details 表记录管理的内容包括如何在文件上存放、读取、检索。也就是记录的增删改查。
* 这里的文件都会被拆分成页面,每个页面都有一样的大小。更详细的信息可以参考BufferPool。
* 按照BufferPool的设计,第一个页面用来存放BufferPool本身的元数据,比如当前文件有多少页面、已经分配了多少页面、
......@@ -104,9 +102,11 @@ private:
* @brief 负责处理一个页面中各种操作,比如插入记录、删除记录或者查找记录
* @ingroup RecordManager
* @details 当前定长记录模式下每个页面的组织大概是这样的:
* @code
* | PageHeader | record allocate bitmap |
* |------------|------------------------|
* | record1 | record2 | ..... | recordN |
* @endcode
*/
class RecordPageHandler
{
......