路径 | 重要类 | 说明 |
---|---|---|
common | Init | 初始化服务器配置 |
event | SessionEvent、SqlEvent | 处理SQL请求、SQL调试信息 |
net | Server | 网络模块,负责客户端与服务端通信 |
session | SessionStage | 创建Session窗口(每次输入SQL语句时创建) |
sql/parser | ParseStage、ResolveStage | SQL解析处理阶段,将SQL解析为语法树和Stmt语义 |
sql/stmt | Stmt | 定义各种SQL语句的Stmt语义 |
sql/operator | - | 实现各种查询计划 |
sql/expr | Expression、Tuple | 定义表达式类型、表示一行数据 |
sql/optimizer | OptimizeStage | 查询优化阶段 |
sql/executor | ExecuteStage | SQL执行阶段,实现了各种SQL语句的Executor |
sql/plan_cache | PlanCacheStage | 计划缓存阶段,本项目未实现 |
sql/query_cache | QueryCacheStage | 查询缓存阶段,本项目未实现 |
storage/db | Db | 数据库实现类 |
storage/table | Table | 数据表实现类 |
storage/record | Record | 数据表中的记录类 |
storage/field | Field、FieldMeta | 数据表中的字段类 |
storage/index | Index、B+Tree | 索引类、B+树实现 |
storage/trx | - | 事务类 |
storage/clog | - | 定义事务操作的类型和日志文件的格式 |
storage/buffer | Page、Frame、DiskBufferPool | 定义页、页帧、缓冲池 |
storage/persist | PersistHandler | 数据持久化类,定义打开、删除等文件操作 |
storage/common | MetaUtil | 工具类,指定数据库文件的扩展名 |
类 | 路径 | 说明 |
---|---|---|
RC | common/rc.h | 函数返回码 |
CompOp | sql/parser/parse_defs.h | 描述比较运算符 |
SqlCommandFlag | sql/parser/parse_defs.h | SQL语句类型 |
ExprType | sql/expr/expression.h | 表达式类型 |
AttrType | sql/parser/value.h | 字段类型 |
StmtType | sql/stmt/stmt.h | Stmt语义类型 |
CLogType | storage/clog/clog.h | 事务日志类型 |
-
以监听TCP端口的方式启动
-
运行服务端
./bin/observer -f ../etc/observer.ini -p 6789
-
运行客户端
./bin/obclient -p 6789
-
-
以监听unix socket的方式启动
-
运行服务端
./bin/observer -f ../etc/observer.ini -s miniob.sock
-
运行客户端
./bin/obclient -s miniob.sock
-
-
以直接执行命令的方式启动
-
单线程模式,可以直接在服务端输入命令,不需要客户端
./bin/observer -f ../etc/observer.ini -P cli
-
类 | 函数 | 服务端 |
---|---|---|
- | main@src/observer/main.cpp | 启动服务端(解析命令行参数、加载配置文件、初始化) |
Server | recv@src/observer/net/server.cpp | 客户端输入SQL并回车后,Server接收客户端消息并创建SessionEvent |
SessionStage | handle_request@src/observer/session/session_stage.cpp | 处理SessionEvent并创建SQLStageEvent |
SessionStage | handle_sql@src/observer/session/session_stage.cpp | 执行各阶段的SQL处理 |
QueryCacheStage | handle_request@src/observer/sql/query_cache/query_cache_stage.cpp | 查询缓存 |
ParseStage | handle_request@src/observer/sql/parser/parse_stage.cpp | 解析SQL语句为ParsedSqlNode |
ResolveStage | handle_request@src/observer/sql/parser/resolve_stage.cpp | 解析ParsedSqlNode为Stmt |
分支操作 | - | 根据SQL语句是否进行查询计划分支操作 |
SessionStage | handle_request@src/observer/session/session_stage.cpp | 向客户端返回结果(打印SessionEvent中SqlResult属性的内容) |
类 | 函数 | 功能类 |
---|---|---|
ExecuteStage | handle_request@src/observer/sql/executor/execute_stage.cpp | 调用CommandExecutor执行 |
CommandExecutor | execute@src/observer/sql/executor/command_executor.cpp | 根据StmtType分发执行 |
Executor | - | 调用db->调用table执行相关操作 |
类 | 函数 | 功能类 |
---|---|---|
OptimizeStage | handle_request@src/observer/sql/optimizer/optimize_stage.cpp | 创建查询计划,并进行优化(在select、insert、update、delete时使用) |
ExecuteStage | handle_request@src/observer/sql/executor/execute_stage.cpp | 根据StmtType执行查询计划,将结果写入SessionEvent的SqlResult属性 |
-
逻辑算子描述当前执行计划要做什么,比如从表中获取数据,过滤,投影,连接等
-
属性列表
属性 类型 说明 type() LogicalOperatorType 指定算子类型,如从表中获取数据、过滤、投影、连接、插入、删除、查看执行计划、更新 children List 子算子列表 expressions_ List 子算子列表对应的表达式列表
-
物理算子描述如何执行当前计划,这是与逻辑算子不同之处
-
算子是最小执行单位,是事务性的
-
Mniob采用流水线模型(火山模型)执行查询计划,即从根节点开始递归调用孩子结点的next()函数,逐行获取元组并由下至上进行相应的运算,直到处理完表中的所有元组,同时生成要返回的结果集字符串
-
属性列表
属性 类型 说明 type() 返回PhysicalOperatorType 指定算子类型,如扫描表、扫描索引、嵌套连接、查看执行计划、过滤、投影、计算、删除等 children List 子算子列表 open() 参数为Trx 开始执行一个算子时需要开启事务 next() - 逐行调用子算子的next(),获取其current_tuple(), close() - 关闭算子 current_tuple() 返回Tuple 当前Tuple
名称 | 分值 | 说明 |
---|---|---|
basic | 10 | 基本功能 |
drop-table | 10 | 删除表 |
update | 10 | 更新字段 |
date | 10 | 日期字段 |
select-tables | 10 | 多表查询 |
select-meta | 10 | 表结构 |
aggregation-func | 10 | 聚合函数 |
假设表名为demo
-
分析
-
需要删除demo.table文件、demo.data文件和关联的索引文件
-
由于具体执行阶段在CommandExecutor进行分发,因此需要实现DropTableExecutor
-
相应地,需要实现DropTableStmt
-
-
实现
- 实现DropTableExecutor
- db中实现delete_table接口
- table中实现destroy接口
- 删除Meta
- 删除Data
- 删除索引
- 清空buffer pool
- CommandExecutor增加对StmtType::DROP_TABLE的执行分支
- 实现DropTableExecutor
- 分析
- 更新语句涉及修改数据库,可能会用到where语句,因此需要实现查询计划
- 实现
- 实现UpdateLogicalOperator、UpdatePhysicalOperator
- 在LogicalPlanGenerator、PhysicalPlanGenerator中分别实现生成UpdateLogicalOperator、UpdatePhysicalOperator的逻辑
- 实现UpdateStmt::create函数,从而实现Update语句的处理逻辑
- 重写type
- 检查参数合法性(表名、字段名不为空)
- 检查表是否存在
- 检查字段是否存在
- 由于可能会用到where语句,因此需要在UpdateStmt中实现FilterStmt
要求:增加date字段。字段不会超过2038年2月,不会小于1970年1月1号
-
分析
- 在parser中添加对date关键字、date取值、date字段的词法语法定义
- 对于insert/update语句,需要检查插入或更新的date字段值是否合法
- 对于select语句,需要检查where条件中出现的date值是否合法
-
实现
- 在lex中添加date的正则表达式,并在此处将字符串转换为date类型,如果字符串不合法,则该date值为0,便于后续判断
- 在value.cpp中添加DATES的属性类型、date类型的构造函数、set_date、get_date、实现to_string、实现compare、在联合体中添加date字段date_value_
- 在filter_stmt中添加对date为0的特判:select/update中检查date是否合法
- 在insert_stmt中添加对date为0的特判:insert中检查date是否合法
- 在B+树中添加对compare类型的比较(实际上由于Miniob底层代码逻辑缺陷,此处调用value.cpp中的compare方法实现为好,扩展性更强)
- 分析
- 可以分解为三个操作:两张表分别针对要select的字段进行TableSelect算子、进行Join连接算子、根据where子句进行过滤算子
- 实现
- 与Update类似,需要在LogicalPlanGenerator、PhysicalPlanGenerator中分别实现生成select逻辑计划、select物理计划的逻辑,此处无需单独实现SelectLogicalOperator、SelectPhyicalOperator,利用已有算子即可实现
要求:实现max/min/count/avg函数;包含聚合字段时,只会出现聚合字段;聚合函数中的参数不会是表达式,比如age+1
-
分析
-
首先在lex和yacc中添加各聚合函数的token
-
select的语法解析树中,select_attrs需要改为select_exprs,即引入聚合函数后,select的内容由字段列表变为表达式列表
-
在yacc中定义select_expr、select_expr_list、select_exprs、aggr_func
- select_expr可以是rel_attr、也可以是aggr_func
- select_expr_list参照attr_list
- select_exprs可以是select_expr_list,也可以是*表示所有字段
- aggr_func由aggr_fun_name和select_attr组成
-
将yacc中定义的语义变量转换为相应数据结构
- select_expr >> SelectExprNode(指定表达式类型SelectExprType、字段名/聚合函数)
- aggr_func >> AggrFuncNode(指定聚合函数类型AggrFuncType、字段列表)
- 修改SelectSqlNode的属性(去除attributes,添加select_exprs)
-
修改SelectStmt的create逻辑
- SelectStmt中删除原属性query_fields,添加表达式Expression列表query_exprs
- 遍历SelectSqlNode中的select_exprs
- 如果是聚合函数,那么根据SelectExprType的arrgfunc属性创建AggrStmt并转换为Expression
- 如果是字段
- 表名为空,列属性为*,添加所有表的所有列
- 表名为空,列属性不为*,默认为第一个表,如果存在多个表报错
- 表名不为空
- 表名为*,属性不为*,不合法
- 表名不为*,属性为*,添加该表的所有列(判断表是否存在)
- 表名不为*,属性不为*,添加该列(判断表和列是否存在)
-
在表达式Expression中添加AggrExpr表示聚合函数表达式
- 添加ExprType
- 定义各种聚合函数的操作
-
修改select逻辑计划、select物理计划的逻辑
- 实现AggrLogicalOperator、AggrPhysicalOperator
-
名称 | 分值 | 说明 |
---|---|---|
insert | 10 | 插入多条数据 |
unique | 10 | 唯一性索引 |
null | 10 | 空值 |
order-by | 10 | 排序 |
simple-sub-query | 10 | 简单子查询 |
complex-sub-query | 20 | 复杂子查询 |
group-by | 20 | 分组 |
join-tables | 20 | 连接查询 |
expression | 20 | 表达式 |
text | 20 | TEXT字段 |
multi-index | 20 | 多索引 |
要求:支持插入多条数据,且要同时失败或成功
- 分析
- 修改parser模块,使其支持插入多条数据
- 修改InsertStmt
- 修改InsertLogicalOperator、InsertPhysicalOperator