Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
oceanbase
miniob
提交
f4e52131
M
miniob
项目概览
oceanbase
/
miniob
大约 1 年 前同步成功
通知
74
Star
1521
Fork
537
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
分析
仓库
DevOps
项目成员
Pages
M
miniob
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Pages
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
提交
未验证
提交
f4e52131
编写于
6月 26, 2023
作者:
羽飞
提交者:
GitHub
6月 26, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
增加一些文档 (#200)
### What problem were solved in this pull request? Issue Number: ref #165 ref #174 Problem: 一些文档需要优化
上级
380fea38
变更
46
隐藏空白更改
内联
并排
Showing
46 changed file
with
839 addition
and
66 deletion
+839
-66
README.md
README.md
+10
-8
benchmark/bplus_tree_concurrency_test.cpp
benchmark/bplus_tree_concurrency_test.cpp
+1
-1
benchmark/record_manager_concurrency_test.cpp
benchmark/record_manager_concurrency_test.cpp
+1
-1
docs/src/SUMMARY.md
docs/src/SUMMARY.md
+5
-1
docs/src/dev-env/introduction.md
docs/src/dev-env/introduction.md
+2
-1
docs/src/dev-env/miniob-how-to-debug.md
docs/src/dev-env/miniob-how-to-debug.md
+227
-0
docs/src/game/introduction.md
docs/src/game/introduction.md
+5
-0
docs/src/game/miniob-date-implementation.md
docs/src/game/miniob-date-implementation.md
+162
-0
docs/src/game/miniob-drop-table-implementation.md
docs/src/game/miniob-drop-table-implementation.md
+103
-0
docs/src/game/miniob-output-convention.md
docs/src/game/miniob-output-convention.md
+3
-1
docs/src/game/miniob-test-comment-date.md
docs/src/game/miniob-test-comment-date.md
+83
-0
docs/src/how_to_run.md
docs/src/how_to_run.md
+17
-1
docs/src/lectures/copyright.md
docs/src/lectures/copyright.md
+2
-0
docs/src/lectures/index.md
docs/src/lectures/index.md
+1
-2
src/observer/common/init.cpp
src/observer/common/init.cpp
+1
-1
src/observer/net/mysql_communicator.cpp
src/observer/net/mysql_communicator.cpp
+6
-16
src/observer/sql/stmt/create_index_stmt.h
src/observer/sql/stmt/create_index_stmt.h
+4
-0
src/observer/sql/stmt/create_table_stmt.h
src/observer/sql/stmt/create_table_stmt.h
+1
-0
src/observer/sql/stmt/delete_stmt.h
src/observer/sql/stmt/delete_stmt.h
+4
-0
src/observer/sql/stmt/desc_table_stmt.h
src/observer/sql/stmt/desc_table_stmt.h
+1
-0
src/observer/sql/stmt/exit_stmt.h
src/observer/sql/stmt/exit_stmt.h
+1
-0
src/observer/sql/stmt/explain_stmt.h
src/observer/sql/stmt/explain_stmt.h
+4
-0
src/observer/sql/stmt/filter_stmt.h
src/observer/sql/stmt/filter_stmt.h
+4
-0
src/observer/sql/stmt/help_stmt.h
src/observer/sql/stmt/help_stmt.h
+1
-0
src/observer/sql/stmt/insert_stmt.h
src/observer/sql/stmt/insert_stmt.h
+4
-0
src/observer/sql/stmt/select_stmt.h
src/observer/sql/stmt/select_stmt.h
+4
-0
src/observer/sql/stmt/show_tables_stmt.h
src/observer/sql/stmt/show_tables_stmt.h
+1
-0
src/observer/sql/stmt/stmt.h
src/observer/sql/stmt/stmt.h
+11
-0
src/observer/sql/stmt/trx_begin_stmt.h
src/observer/sql/stmt/trx_begin_stmt.h
+1
-0
src/observer/sql/stmt/trx_end_stmt.h
src/observer/sql/stmt/trx_end_stmt.h
+1
-0
src/observer/sql/stmt/update_stmt.h
src/observer/sql/stmt/update_stmt.h
+4
-0
src/observer/storage/buffer/disk_buffer_pool.cpp
src/observer/storage/buffer/disk_buffer_pool.cpp
+1
-1
src/observer/storage/buffer/disk_buffer_pool.h
src/observer/storage/buffer/disk_buffer_pool.h
+23
-1
src/observer/storage/buffer/frame.h
src/observer/storage/buffer/frame.h
+8
-0
src/observer/storage/buffer/page.h
src/observer/storage/buffer/page.h
+4
-0
src/observer/storage/index/bplus_tree.cpp
src/observer/storage/index/bplus_tree.cpp
+1
-1
src/observer/storage/index/bplus_tree.h
src/observer/storage/index/bplus_tree.h
+54
-8
src/observer/storage/index/bplus_tree_index.h
src/observer/storage/index/bplus_tree_index.h
+12
-2
src/observer/storage/index/index.h
src/observer/storage/index/index.h
+47
-13
src/observer/storage/index/index_meta.h
src/observer/storage/index/index_meta.h
+6
-0
src/observer/storage/record/record_manager.h
src/observer/storage/record/record_manager.h
+3
-2
src/observer/storage/table/table.cpp
src/observer/storage/table/table.cpp
+1
-1
src/observer/storage/trx/latch_memo.cpp
src/observer/storage/trx/latch_memo.cpp
+1
-1
unittest/bp_manager_test.cpp
unittest/bp_manager_test.cpp
+1
-1
unittest/bplus_tree_test.cpp
unittest/bplus_tree_test.cpp
+1
-1
unittest/record_manager_test.cpp
unittest/record_manager_test.cpp
+1
-1
未找到文件。
README.md
浏览文件 @
f4e52131
...
...
@@ -4,7 +4,11 @@ MiniOB 是 [OceanBase](https://github.com/oceanbase/oceanbase) 与华中科技
MiniOB 设计的目标是面向在校学生、数据库从业者、爱好者,或者对基础技术有兴趣的爱好者, 整体代码量少,易于上手并学习, 是一个系统性的数据库学习项目。miniob 设置了一系列由浅入深的题目,以帮助同学们"零"基础入门, 让同学们快速了解数据库并深入学习数据库内核,期望通过相关训练之后,能够熟练掌握数据库内核模块的功能与协同关系, 并能够在使用数据库时,设计出高效的 SQL 。miniob 为了更好的学习数据库实现原理, 对诸多模块都做了简化,比如不考虑并发操作, 安全特性, 复杂的事物管理等功能。
## 快速上手
# GitHub Pages
代码配套文档和相关代码注释已经生成文档并通过 GitHub Pages 发布, 可以直接访问:
[
MiniOB GitHub Pages
](
https://oceanbase.github.io/miniob/
)
.
# 快速上手
为了帮助开发者更好的上手并学习 miniob, 建议阅读:
...
...
@@ -17,8 +21,6 @@ MiniOB 设计的目标是面向在校学生、数据库从业者、爱好者,
6.
[
MiniOB 各模块文档
](
docs/src/design/introduction.md
)
7.
[
doxygen 代码文档
](
docs/doxy/html/index.html
)
或者直接看
[
MiniOB GitHub Pages
](
https://oceanbase.github.io/miniob/
)
.
更多的文档, 可以参考 docs 目录下的文档, 为了帮助大家更好的学习数据库基础知识, OceanBase 社区提供了一系列教程, 建议学习:
1.
[
《从0到1数据库内核实战教程》 视频教程
](
https://open.oceanbase.com/activities/4921877?id=4921946
)
...
...
@@ -53,7 +55,7 @@ MiniOB 整体架构如下图所示:
-
客户端:作为测试工具,接收用户请求,向服务端发起请求。
#
#
[OceanBase 大赛](https://open.oceanbase.com/competition)
# [OceanBase 大赛](https://open.oceanbase.com/competition)
2022 OceanBase 数据库大赛是由中国计算机学会(CCF)数据库专业委员会指导,OceanBase 与蚂蚁技术研究院学术合作团队联合举办的数据库内核实战赛事。本次大赛主要面向全国爱好数据库的高校学生,以“竞技、交流、成长”为宗旨,搭建基于赛事的技术交流平台,促进高校创新人才培养机制,不仅帮助学生从0开始系统化学习数据库理论知识,提升学生数据库实践能力,更能帮助学生走向企业积累经验,促进国内数据库人才的发展,碰撞出创新的火花。
...
...
@@ -81,7 +83,7 @@ OceanBase 初赛基于一套适合初学者实践的数据库实训平台 miniob
[
大赛 FAQ
](
https://ask.oceanbase.com/t/topic/35601465
)
#
#
在线开发平台
# 在线开发平台
本仓库基于 Gitpod 建立了快速在线开发平台, 点击下面按钮一键体验(建议使用 Chrome 浏览器)
...
...
@@ -89,15 +91,15 @@ OceanBase 初赛基于一套适合初学者实践的数据库实训平台 miniob
首次进入 Gitpod 时需要安装一些依赖,依赖安装完成后,终端界面会显示 "Dependency installed successfully"。运行
`bash build.sh --make -j4`
命令即可编译miniob。
#
#
Contributing
# Contributing
OceanBase 社区热情欢迎每一位对数据库技术热爱的开发者,期待携手开启思维碰撞之旅。无论是文档格式调整或文字修正、问题修复还是增加新功能,都是对 OceanBase 社区参与和贡献方式之一,立刻开启您的 First Contribution 吧!更多详情, 请参考
[
社区贡献
](
CONTRIBUTING.md
)
.
#
#
License
# License
MiniOB 采用
[
木兰宽松许可证,第2版
](
https://license.coscl.org.cn/MulanPSL2
)
, 可以自由拷贝和使用源码, 当做修改或分发时, 请遵守
[
木兰宽松许可证,第2版
](
https://license.coscl.org.cn/MulanPSL2
)
.
#
#
社区组织
# 社区组织
-
[
OceanBase 社区交流群 33254054
](
https://h5.dingtalk.com/circle/healthCheckin.html?corpId=dingd88359ef5e4c49ef87cda005313eea7a&1fe0ca69-72d=16c86a07-83c&cbdbhh=qwertyuiop&origin=1
)
-
[
OceanBase 大赛官方交流群 35326455
](
https://qr.dingtalk.com/action/joingroup?code=v1,k1,g61jI0RwHQA8UMocuTbys2cyM7vck2c6jNE87vdxz9o=&_dt_no_comment=1&origin=11
)
...
...
benchmark/bplus_tree_concurrency_test.cpp
浏览文件 @
f4e52131
...
...
@@ -16,7 +16,7 @@ See the Mulan PSL v2 for more details. */
#include <benchmark/benchmark.h>
#include "storage/index/bplus_tree.h"
#include "storage/
default
/disk_buffer_pool.h"
#include "storage/
buffer
/disk_buffer_pool.h"
#include "common/log/log.h"
#include "integer_generator.h"
...
...
benchmark/record_manager_concurrency_test.cpp
浏览文件 @
f4e52131
...
...
@@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */
#include <benchmark/benchmark.h>
#include "storage/record/record_manager.h"
#include "storage/
default
/disk_buffer_pool.h"
#include "storage/
buffer
/disk_buffer_pool.h"
#include "storage/common/condition_filter.h"
#include "storage/trx/vacuous_trx.h"
#include "common/log/log.h"
...
...
docs/src/SUMMARY.md
浏览文件 @
f4e52131
...
...
@@ -9,6 +9,7 @@
-
[
开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)
](
./dev-env/how_to_dev_in_docker_container_by_vscode.md
)
-
[
Windows 使用Docker开发MiniOB
](
./dev-env/how_to_dev_miniob_by_docker_on_windows.md
)
-
[
使用Docker开发MiniOB
](
./dev-env/how-to-dev-using-docker.md
)
-
[
MiniOB 调试
](
./dev-env/miniob-how-to-debug.md
)
-
[
功能模块设计说明文档
](
./design/introduction.md
)
-
[
事务
](
./design/miniob-transaction.md
)
...
...
@@ -20,8 +21,12 @@
-
[
提交测试需要满足的输出要求
](
./game/miniob-output-convention.md
)
-
[
2021届大赛题目介绍
](
./game/miniob_topics.md
)
-
[
大赛手把手入门教程
](
./game/gitee-instructions.md
)
-
[
date 测试说明
](
./game/miniob-test-comment-date.md
)
-
[
date 实现解析
](
./game/miniob-date-implementation.md
)
-
[
drop table 实现解析
](
./game/miniob-drop-table-implementation.md
)
-
[
数据库基础理论课程
](
./lectures/index.md
)
-
[
版权声明
](
./lectures/copyright.md
)
-
[
第1章 数据库管理系统概述
](
./lectures/lecture-1.md
)
-
[
第2章 数据库的存储结构
](
./lectures/lecture-2.md
)
-
[
第3章 索引结构
](
./lectures/lecture-3.md
)
...
...
@@ -29,4 +34,3 @@
-
[
第5章 查询优化
](
./lectures/lecture-5.md
)
-
[
第6章 事务处理
](
./lectures/lecture-6.md
)
-
[
参考资料
](
./lectures/references.md
)
-
[
版权声明
](
./lectures/copyright.md
)
\ No newline at end of file
docs/src/dev-env/introduction.md
浏览文件 @
f4e52131
...
...
@@ -6,4 +6,5 @@ MiniOB 当前可以在Linux/MacOS上编译,所以开发环境最好是Linux或
-
[
开发环境搭建(本地调试, 适用 Linux 和 Mac)
](
how_to_dev_miniob_by_vscode.md
)
-
[
开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)
](
how_to_dev_in_docker_container_by_vscode.md
)
-
[
Windows 使用Docker开发MiniOB
](
how_to_dev_miniob_by_docker_on_windows.md
)
-
[
使用Docker开发MiniOB
](
how-to-dev-using-docker.md
)
\ No newline at end of file
-
[
使用Docker开发MiniOB
](
how-to-dev-using-docker.md
)
-
[
MiniOB 调试
](
./dev-env/miniob-how-to-debug.md
)
\ No newline at end of file
docs/src/dev-env/miniob-how-to-debug.md
0 → 100644
浏览文件 @
f4e52131
# miniob调试篇
-- by caizj
调试c/c++程序,常用的有两种方式,一是打印日志调试,二是gdb调试,调试不仅可以定位问题,也可以用来熟悉代码。
## miniob关键代码
首先,拿到一份陌生的代码,要先确定代码的大致结构,一些关键数据结构和方法,这里的技巧和经验不展开了
### miniob的关键数据结构
部分关键数据结构:
```
c++
parse_def
.
h
:
struct
Selects
;
//查询相关
struct
CreateTable
;
//建表相关
struct
DropTable
;
//删表相关
enum
SqlCommandFlag
;
//sql语句对应的command枚举
union
Queries
;
//各类dml和ddl操作的联合
table
.
h
class
Table
;
db
.
h
class
Db
;
```
### miniob的关键接口
部分关键接口
```
c++
RC
parse
(
const
char
*
st
,
Query
*
sqln
);
//sql parse入口
ExecuteStage
::
handle_request
ExecuteStage
::
do_select
DefaultStorageStage
::
handle_event
DefaultHandler
::
create_index
DefaultHandler
::
insert_record
DefaultHandler
::
delete_record
DefaultHandler
::
update_record
Db
::
create_table
Db
::
find_table
Table
::
create
Table
::
scan_record
Table
::
insert_record
Table
::
update_record
Table
::
delete_record
Table
::
scan_record
Table
::
create_index
```
### 打印日志调试
miniob提供的日志接口
```
c++
deps
/
common
/
log
/
log
.
h
:
#define LOG_PANIC(fmt, ...)
#define LOG_ERROR(fmt, ...)
#define LOG_WARN(fmt, ...)
#define LOG_INFO(fmt, ...)
#define LOG_DEBUG(fmt, ...)
#define LOG_TRACE(fmt, ...)
```
日志相关配置项
`observer.ini`
```
LOG_FILE_NAME = observer.log
# LOG_LEVEL_PANIC = 0,
# LOG_LEVEL_ERR = 1,
# LOG_LEVEL_WARN = 2,
# LOG_LEVEL_INFO = 3,
# LOG_LEVEL_DEBUG = 4,
# LOG_LEVEL_TRACE = 5,
# LOG_LEVEL_LAST
LOG_FILE_LEVEL=5
LOG_CONSOLE_LEVEL=1
```
### gdb调试
调试工具有很多种,但是它们的关键点都是类似的,比如关联到进程、运行时查看变量值、单步运行、跟踪变量等。GDB是在Linux环境中常用的调试工具。其它环境上也有类似的工具,比如LLDB,或者Windows可能使用Visual Studio直接启动调试。Java的调试工具是jdb。
另外,很多同学喜欢使用Visual Studio Code(vscode)开发项目,vscode提供了很多插件,包括调试的插件,这些调试插件支持gdb、lldb等,可以按照自己的平台环境,设置不同的调试工具。
这里介绍了gdb的基本使用,其它工具的使用方法类似。
1.
Attach进程
```
[caizj@localhost run]$ gdb -p `pidof observer`
GNU gdb (GDB) Red Hat Enterprise Linux 8.2-15.el8 Copyright (C) 2018 Free Software Foundation, Inc.
(gdb)
```
2.
设置断点
```
(gdb) break do_select
Breakpoint 1 at 0x44b636: file /home/caizj/source/stunning-engine/src/observer/sql/executor/execute_stage.cpp, line 526.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000044b636 in ExecuteStage::do_select(char const*, Query*, SessionEvent*)
at /home/caizj/source/stunning-engine/src/observer/sql/executor/execute_stage.cpp:526
```
```
(gdb) break Table::scan_record
Breakpoint 2 at 0x50b82b: Table::scan_record. (2 locations)
(gdb) inf b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000044b636 in ExecuteStage::do_select(char const*, Query*, SessionEvent*)
at /home/caizj/source/stunning-engine/src/observer/sql/executor/execute_stage.cpp:526
2 breakpoint keep y <MULTIPLE>
2.1 y 0x000000000050b82b in Table::scan_record(Trx*, ConditionFilter*, int, void*, void (*)(char const*, void*))
at /home/caizj/source/stunning-engine/src/observer/storage/common/table.cpp:421
2.2 y 0x000000000050ba00 in Table::scan_record(Trx*, ConditionFilter*, int, void*, RC (*)(Record*, void*))
at /home/caizj/source/stunning-engine/src/observer/storage/common/table.cpp:426
(gdb)
```
3.
继续执行
```
(gdb) c
Continuing.
```
4.
触发断点
执行:miniob > select * from t1;
```
[Switching to Thread 0x7f51345f9700 (LWP 54706)]
Thread 8 "observer" hit Breakpoint 1, ExecuteStage::do_select (this=0x611000000540,
db=0x6040000005e0 "sys", sql=0x620000023080, session_event=0x608000003d20)
at /home/caizj/source/stunning-engine/src/observer/sql/executor/execute_stage.cpp:526
526 RC rc = RC::SUCCESS;
(gdb)
```
5.
单步调式
```
575 std::vector<TupleSet> tuple_sets;
(gdb) next
576 for (SelectExeNode *&node: select_nodes) {
(gdb) n
577 TupleSet tuple_set;
(gdb)
578 rc = node->execute(tuple_set);
(gdb)
```
6.
跳入
跟踪到函数内部
```
(gdb) s
SelectExeNode::execute (this=0x60700002ce80, tuple_set=...)
at /home/caizj/source/stunning-engine/src/observer/sql/executor/execution_node.cpp:43
43 CompositeConditionFilter condition_filter;
(gdb)
```
7.
打印变量
```
(gdb) p tuple_set
$3 = (TupleSet &) @0x7f51345f1760: {tuples_ = std::vector of length 0, capacity 0, schema_ = {
fields_ = std::vector of length 0, capacity 0}}
(gdb)
```
8.
watch变量
```
(gdb) n
443 RC rc = RC::SUCCESS;
(gdb) n
444 RecordFileScanner scanner;
(gdb) n
445 rc = scanner.open_scan(*data_buffer_pool_, file_id_, filter);
(gdb) watch -l rc
Hardware watchpoint 3: -location rc
(gdb) c
Continuing.
Thread 8 "observer" hit Hardware watchpoint 3: -location rc
Old value = SUCCESS
New value = RECORD_EOF
0x000000000050c2de in Table::scan_record (this=0x60f000007840, trx=0x606000009920,
filter=0x7f51345f12a0, limit=2147483647, context=0x7f51345f11c0,
record_reader=0x50b74a <scan_record_reader_adapter(Record*, void*)>)
at /home/caizj/source/stunning-engine/src/observer/storage/common/table.cpp:454
454 for ( ; RC::SUCCESS == rc && record_count < limit; rc = scanner.get_next_record(&record)) {
(gdb)
```
9.
结束函数调用
```
(gdb) finish
Run till exit from #0 0x000000000050c2de in Table::scan_record (this=0x60f000007840,
trx=0x606000009920, filter=0x7f51345f12a0, limit=2147483647, context=0x7f51345f11c0,
record_reader=0x50b74a <scan_record_reader_adapter(Record*, void*)>)
at /home/caizj/source/stunning-engine/src/observer/storage/common/table.cpp:454
```
10.
结束调试
```
(gdb) quit
A debugging session is active.
Inferior 1 [process 54699] will be detached.
Quit anyway? (y or n) y
Detaching from program: /home/caizj/local/bin/observer, process 54699
[Inferior 1 (process 54699) detached]
```
\ No newline at end of file
docs/src/game/introduction.md
浏览文件 @
f4e52131
...
...
@@ -10,6 +10,11 @@
作为参考,这里有第一届数据库大赛的题目介绍:
[
第一届数据库大赛题目介绍
](
./miniob_topics.md
)
还有往届选手给出了一些题解:
-
[
date 测试说明
](
./miniob-test-comment-date.md
)
-
[
date 实现解析
](
./miniob-date-implementation.md
)
-
[
drop table 实现解析
](
./miniob-drop-table-implementation.md
)
在参赛前,除了学习基础的理论知识,还可以使用OceanBase提供的训练营,来快速上手:
[
训练营
](
https://open.oceanbase.com/train?questionId=200001
)
...
...
docs/src/game/miniob-date-implementation.md
0 → 100644
浏览文件 @
f4e52131
# Date实现解析
> 此实现解析有往届选手提供。具体代码实现已经有所变更,因此仅供参考。
-
by caizj
## DATE的存储
一种实现方式:date以int类型的YYYYMMDD格式保存,比如2021-10-21,保存为整数就是2021
\*
1000 + 10
\*
100 + 21,在select展示时转成字符串YYYY-MM-DD格式,注意月份和天数要使用0填充。
在parse.cpp中,参考
```
c++
int
value_init_date
(
Value
*
value
,
const
char
*
v
)
{
value
->
type
=
DATES
;
int
y
,
m
,
d
;
sscanf
(
v
,
"%d-%d-%d"
,
&
y
,
&
m
,
&
d
);
//not check return value eq 3, lex guarantee
bool
b
=
check_date
(
y
,
m
,
d
);
if
(
!
b
)
return
-
1
;
int
dv
=
y
*
10000
+
m
*
100
+
d
;
value
->
data
=
malloc
(
sizeof
(
dv
));
//TODO:check malloc failure
memcpy
(
value
->
data
,
&
dv
,
sizeof
(
dv
));
return
0
;
}
```
## 修改点
### 语法上修改支持
需要可匹配date的token词和DATE_STR值(一定要先于SSS,因为date的输入DATE_STR是SSS的子集)
语法(yacc文件)上增加type,value里增加DATE_STR值
```
c++
[
Dd
][
Aa
][
Tt
][
Ee
]
RETURN_TOKEN
(
DATE_T
);
// 增加DATE的token,需要在yacc文件中增加DATE_T的token
{
QUOTE
}[
0
-
9
]{
4
}
\
-
(
0
?
[
1
-
9
]
|
1
[
012
])
\
-
(
0
?
[
1
-
9
]
|
[
12
][
0
-
9
]
|
3
[
01
]){
QUOTE
}
yylval
->
string
=
strdup
(
yytext
);
RETURN_TOKEN
(
DATE_STR
);
// 使用正则表达式过滤DATE。需要在yacc文件中增加 %token <string> DATE_STR
```
同时,需要增加一个DATE类型,与INTS,FLOATS等含义相同:
```
c++
// in parse_defs.h
typedef
enum
{
UNDEFINED
,
CHARS
,
INTS
,
FLOATS
,
DATES
,
TEXTS
,
NULLS
}
AttrType
;
```
### Date的合法性判断
输入日期的格式可以在词法分析时正则表达式里过滤掉。润年,大小月日期的合法性在普通代码中再做进一步判断。
在parse阶段,对date做校验,并格式化成int值保存(参考最前面的代码),同时对日期的合法性做校验,参考:
```
c++
bool
check_date
(
int
y
,
int
m
,
int
d
)
{
static
int
mon
[]
=
{
0
,
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
bool
leap
=
(
y
%
400
==
0
||
(
y
%
100
&&
y
%
4
==
0
));
return
y
>
0
&&
(
m
>
0
)
&&
(
m
<=
12
)
&&
(
d
>
0
)
&&
(
d
<=
((
m
==
2
&&
leap
)
?
1
:
0
)
+
mon
[
m
]);
}
```
### 增加新的类型date枚举
代码里有多处和类型耦合地方(增加一个类型,要动很多处离散的代码,基础代码在这方面的可维护性不好)
包括不限于,以下几处:
-
DefaultConditionFilter
需要增加DATES类型的数据对比。因为这里将date作为整数存储,那么可以直接当做INTS来对比,比如:
```
c++
case
INTS
:
case
DATES
:
{
// 没有考虑大小端问题
// 对int和float,要考虑字节对齐问题,有些平台下直接转换可能会跪
int
left
=
*
(
int
*
)
left_value
;
int
right
=
*
(
int
*
)
right_value
;
cmp_result
=
left
-
right
;
}
break
;
```
-
BplusTreeScanner
与
`DefaultConditionFilter`
类似,也需要支持DATE类型的对比,可以直接当做整数比较。参考其中一块代码:
```
c++
case
INTS
:
case
DATES
:
{
i1
=
*
(
int
*
)
pdata
;
i2
=
*
(
int
*
)
pkey
;
if
(
i1
>
i2
)
return
1
;
if
(
i1
<
i2
)
return
-
1
;
if
(
i1
==
i2
)
return
0
;
}
break
;
```
-
ATTR_TYPE_NAME(storage/common/field_meta.cpp)
保存元数据时,需要这里的信息,比较简单,参考:
```
c++
const
char
*
ATTR_TYPE_NAME
[]
=
{
"undefined"
,
"chars"
,
"ints"
,
"floats"
,
"dates"
};
```
-
insert_record_from_file(storage/default/default_storage_stage.cpp)
这个接口主要是为了支持从文件导入数据的,同样,实现可以与int类型保持一致。
```
c++
switch
(
field
->
type
())
{
case
INTS
:
case
DATES
:{
deserialize_stream
.
clear
();
// 清理stream的状态,防止多次解析出现异常
deserialize_stream
.
str
(
file_value
);
int
int_value
;
deserialize_stream
>>
int_value
;
if
(
!
deserialize_stream
||
!
deserialize_stream
.
eof
())
{
errmsg
<<
"need an integer but got '"
<<
file_values
[
i
]
<<
"' (field index:"
<<
i
<<
")"
;
rc
=
RC
::
SCHEMA_FIELD_TYPE_MISMATCH
;
}
else
{
value_init_integer
(
&
record_values
[
i
],
int_value
);
}
}
```
### Date select展示
TupleRecordConverter::add_record时做格式转换,需要按照输出要求,将日期类型数据,转换成合适的字符串。参考:
```
c++
case
DATES
:
{
int
value
=
*
(
int
*
)(
record
+
field_meta
->
offset
());
char
buf
[
16
]
=
{
0
};
snprintf
(
buf
,
sizeof
(
buf
),
"%04d-%02d-%02d"
,
value
/
10000
,
(
value
%
10000
)
/
100
,
value
%
100
);
// 注意这里月份和天数,不足两位时需要填充0
tuple
.
add
(
buf
,
strlen
(
buf
));
}
break
;
```
### 异常失败处理
只要输入的日期不合法,输出都是FAILURE
\n
。包括查询的where条件、插入的日期值、更新的值等。这里在解析时(parse.cpp)中就可以直接返回错误。
## 自测覆盖点
1.
日期输入,包括合法和非法日期格式。非法日期可以写单元测试做。
2.
日期值比较=、 >、
<
、
>
=、 <=
3.
日期字段当索引。很多同学漏掉了这个点。
4.
日期展示格式,注意月份和天数补充0
\ No newline at end of file
docs/src/game/miniob-drop-table-implementation.md
0 → 100644
浏览文件 @
f4e52131
# miniob - drop table 实现解析
> 此实现解析有往届选手提供。具体代码实现已经有所变更,因此仅供参考。
**代码部分主要添加在:**
drop table 与create table相反,要清理掉所有创建表和表相关联的资源,比如描述表的文件、数据文件以及索引等相关数据和文件。
sql流转到default_storge阶段的时候,在处理sql的函数中,新增一个drop_table的case。
drop table就是删除表,在
`create table t`
时,会新建一个t.table文件,同时为了存储数据也会新建一个t.data文件存储下来。同时创建索引的时候,也会创建记录索引数据的文件,在删除表时也要一起删除掉。
那么删除表,就需要
**删除t.table文件、t.data文件和关联的索引文件**
。
同时由于buffer pool的存在,在新建表和插入数据的时候,会写入buffer pool缓存。所以drop table,不仅需要删除文件,也需要
**清空buffer pool**
,防止在数据没落盘的时候,再建立同名表,仍然可以查询到数据。
如果建立了索引,比如t_id on t(id),那么也会新建一个t_id.index文件,也需要删除这个文件。
这些东西全部清空,那么就完成了drop table。
具体的代码实现如下:
在default_storage_stage.cpp 中的处理SQL语句的case中增加一个
```
c++
case
SCF_DROP_TABLE
:
{
const
DropTable
&
drop_table
=
sql
->
sstr
[
sql
->
q_size
-
1
].
drop_table
;
// 拿到要drop 的表
rc
=
handler_
->
drop_table
(
current_db
,
drop_table
.
relation_name
);
// 调用drop table接口,drop table要在handler中实现
snprintf
(
response
,
sizeof
(
response
),
"%s
\n
"
,
rc
==
RC
::
SUCCESS
?
"SUCCESS"
:
"FAILURE"
);
// 返回结果,带不带换行符都可以
}
break
;
```
在default_handler.cpp文件中,实现handler的drop_table接口:
```
c++
RC
DefaultHandler
::
drop_table
(
const
char
*
dbname
,
const
char
*
relation_name
)
{
Db
*
db
=
find_db
(
dbname
);
// 这是原有的代码,用来查找对应的数据库,不过目前只有一个库
if
(
db
==
nullptr
)
{
return
RC
::
SCHEMA_DB_NOT_OPENED
;
}
return
db
->
drop_table
(
relation_name
);
// 直接调用db的删掉接口
}
```
在db.cpp中,实现drop_table接口
```
c++
RC
Db
::
drop_table
(
const
char
*
table_name
)
{
auto
it
=
opened_tables_
.
find
(
table_name
);
if
(
it
==
opened_tables_
.
end
())
{
return
SCHEMA_TABLE_NOT_EXIST
;
// 找不到表,要返回错误,测试程序中也会校验这种场景
}
Table
*
table
=
it
->
second
;
RC
rc
=
table
->
destroy
(
path_
.
c_str
());
// 让表自己销毁资源
if
(
rc
!=
RC
::
SUCCESS
)
return
rc
;
opened_tables_
.
erase
(
it
);
// 删除成功的话,从表list中将它删除
delete
table
;
return
RC
::
SUCCESS
;
}
```
table.cpp中清理文件和相关数据
```
c++
RC
Table
::
destroy
(
const
char
*
dir
)
{
RC
rc
=
sync
();
//刷新所有脏页
if
(
rc
!=
RC
::
SUCCESS
)
return
rc
;
std
::
string
path
=
table_meta_file
(
dir
,
name
());
if
(
unlink
(
path
.
c_str
())
!=
0
)
{
LOG_ERROR
(
"Failed to remove meta file=%s, errno=%d"
,
path
.
c_str
(),
errno
);
return
RC
::
GENERIC_ERROR
;
}
std
::
string
data_file
=
std
::
string
(
dir
)
+
"/"
+
name
()
+
TABLE_DATA_SUFFIX
;
if
(
unlink
(
data_file
.
c_str
())
!=
0
)
{
// 删除描述表元数据的文件
LOG_ERROR
(
"Failed to remove data file=%s, errno=%d"
,
data_file
.
c_str
(),
errno
);
return
RC
::
GENERIC_ERROR
;
}
std
::
string
text_data_file
=
std
::
string
(
dir
)
+
"/"
+
name
()
+
TABLE_TEXT_DATA_SUFFIX
;
if
(
unlink
(
text_data_file
.
c_str
())
!=
0
)
{
// 删除表实现text字段的数据文件(后续实现了text case时需要考虑,最开始可以不考虑这个逻辑)
LOG_ERROR
(
"Failed to remove text data file=%s, errno=%d"
,
text_data_file
.
c_str
(),
errno
);
return
RC
::
GENERIC_ERROR
;
}
const
int
index_num
=
table_meta_
.
index_num
();
for
(
int
i
=
0
;
i
<
index_num
;
i
++
)
{
// 清理所有的索引相关文件数据与索引元数据
((
BplusTreeIndex
*
)
indexes_
[
i
])
->
close
();
const
IndexMeta
*
index_meta
=
table_meta_
.
index
(
i
);
std
::
string
index_file
=
index_data_file
(
dir
,
name
(),
index_meta
->
name
());
if
(
unlink
(
index_file
.
c_str
())
!=
0
)
{
LOG_ERROR
(
"Failed to remove index file=%s, errno=%d"
,
index_file
.
c_str
(),
errno
);
return
RC
::
GENERIC_ERROR
;
}
}
return
RC
::
SUCCESS
;
}
```
\ No newline at end of file
docs/src/game/miniob-output-convention.md
浏览文件 @
f4e52131
...
...
@@ -6,6 +6,8 @@
输出是指服务端返回给客户端的数据。为了可以做测试,需要对输出的格式做约定。
NOTE:后台测试程序,是将预先编辑好的Case执行后,将执行结果与预期输出结果(预先编写完成)做对比,与mysql test工作原理类似,因此需要严格按照输出约束来输出。
> 这里虽然列出了很多约束条件,但是同学们并不需要担心,当前的实现已经满足了这些约束条件,或者给出了满足约束的帮助函数,只要按照要求使用即可。
1.
语法解析错误,返回 FAILURE(只返回这个字符串,不带任何多余字符)。