From d37e0a81869c700bb150daeca949e97dad869738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Mon, 20 Oct 2025 13:54:35 +0800 Subject: [PATCH] Update the display of some documents on github.io --- .../design/miniob-how-to-add-new-datatype.md | 293 ++++++++++++++++-- .../design/miniob-sql-execution-process.md | 23 +- docs/docs/how_to_build.md | 69 ++++- docs/mkdocs.yml | 3 + 4 files changed, 340 insertions(+), 48 deletions(-) diff --git a/docs/docs/design/miniob-how-to-add-new-datatype.md b/docs/docs/design/miniob-how-to-add-new-datatype.md index 4ad9bb0ff..79370b4b1 100644 --- a/docs/docs/design/miniob-how-to-add-new-datatype.md +++ b/docs/docs/design/miniob-how-to-add-new-datatype.md @@ -2,31 +2,270 @@ title: 如何新增一种数据类型 --- -> 本文介绍如何新增一种数据类型。 -MiniOB 的数据类型系统采用分层设计,实现集中在[path](../../../src/observer/common)文件夹下,核心组件包括: -1. Value 类:统一数据操作接口 -路径:src/observer/common/value.h -作用:封装实际数据值,提供类型无关的操作方法 -2. Type 工具类:特定类型的操作实现 -路径:src/observer/common/type/ -作用:每种数据类型对应一个工具类,实现具体运算逻辑 - -以下示例展示 MiniOB 如何处理整数类型数据: -```cpp -// 假设解析器识别到整数 "1" -int val = 1; -Value value(val); // 封装为 Value 对象 -// 执行加法运算 +# 概述 + +本文详细介绍如何在 MiniOB 中新增一种数据类型。MiniOB 采用分层架构设计,数据类型系统实现集中在 `src/observer/common` 目录下,通过统一的接口提供类型无关的数据操作。 + +# 核心架构 + +## 1. 数据类型系统架构 + +MiniOB 的数据类型系统采用分层设计,主要包含以下核心组件: + +### Value 类 - 统一数据操作接口 +- **路径**: `src/observer/common/value.h` +- **作用**: 封装实际数据值,提供类型无关的操作方法 +- **特点**: 支持多种数据类型的统一操作接口 + +### DataType 基类 - 类型操作抽象 +- **路径**: `src/observer/common/type/data_type.h` +- **作用**: 定义数据类型操作的抽象接口 +- **功能**: 提供比较、算术运算、类型转换等操作的虚函数 + +### 具体类型实现类 - 特定类型操作 +- **路径**: `src/observer/common/type/` +- **作用**: 每种数据类型对应一个实现类,实现具体的运算逻辑 +- **示例**: `IntegerType`、`FloatType`、`CharType` 等 + +## 2. 现有数据类型 + +当前 MiniOB 支持以下数据类型: + +```cpp +enum class AttrType +{ + UNDEFINED, + CHARS, ///< 字符串类型 + INTS, ///< 整数类型(4字节) + FLOATS, ///< 浮点数类型(4字节) + VECTORS, ///< 向量类型 + BOOLEANS, ///< boolean类型 + MAXTYPE, ///< 请在 UNDEFINED 与 MAXTYPE 之间增加新类型 +}; +``` + +# 数据类型操作流程 + +## 示例:整数类型操作 + +以下代码展示了 MiniOB 如何处理整数类型数据: + +```cpp +// 1. 创建整数 Value 对象 +int val = 42; +Value value(val); // 自动识别为 AttrType::INTS + +// 2. 执行算术运算 +Value left(10); +Value right(32); Value result; -Value::add(value, value, result); // 调用加法接口 -// Value::add 方法内部会根据类型调用对应工具类 -// 对于 INT 类型,实际调用代码位于: -// src/observer/common/type/integer_type.cpp -``` - -# 若要新增一种数据类型(如 DATE),建议按以下步骤开发: -1. 在 src/observer/common/type/attr_type.h 中添加新的类型枚举以及对应类型名 -2. 在 src/observer/common/type/data_type.cpp 中添加新的类型实例 -3. 在 src/observer/common/type/ 文件夹下,参照现有工具类,实现 DateType 工具类 -4. 在 Value 类中增加类型处理逻辑,支持date类型的分发,储存date类型值 -5. 必要情况下还需要增加新的词法规则(lex_sql.l)以及语法规则(yacc_sql.y),支持新类型关键字 \ No newline at end of file +result.set_type(AttrType::INTS); // 设置结果类型 + +// 3. 调用统一接口进行加法运算 +RC rc = Value::add(left, right, result); +// 内部会调用 IntegerType::add() 方法 +``` + +## 类型分发机制 + +`Value::add()` 方法通过以下机制实现类型分发: + +```cpp +static RC add(const Value &left, const Value &right, Value &result) +{ + return DataType::type_instance(result.attr_type())->add(left, right, result); +} +``` + +# 新增数据类型步骤 + +## 以新增 DATE 类型为例 + +### 步骤 1: 添加类型枚举 + +在 `src/observer/common/type/attr_type.h` 中添加新类型: + +```cpp +enum class AttrType +{ + UNDEFINED, + CHARS, + INTS, + FLOATS, + VECTORS, + BOOLEANS, + DATES, ///< 新增:日期类型 + MAXTYPE, ///< 请在 UNDEFINED 与 MAXTYPE 之间增加新类型 +}; +``` + +### 步骤 2: 注册类型实例 + +在 `src/observer/common/type/data_type.cpp` 中注册新类型: + +```cpp +array, static_cast(AttrType::MAXTYPE)> DataType::type_instances_ = { + make_unique(AttrType::UNDEFINED), + make_unique(), + make_unique(), + make_unique(), + make_unique(), + make_unique(AttrType::BOOLEANS), + make_unique(), // 新增:注册 DateType 实例 +}; +``` + +### 步骤 3: 实现具体类型类 + +创建 `src/observer/common/type/date_type.h`: + +```cpp +#pragma once +#include "common/type/data_type.h" + +class DateType : public DataType +{ +public: + DateType() : DataType(AttrType::DATES) {} + virtual ~DateType() {} + + int compare(const Value &left, const Value &right) const override; + RC add(const Value &left, const Value &right, Value &result) const override; + RC subtract(const Value &left, const Value &right, Value &result) const override; + RC cast_to(const Value &val, AttrType type, Value &result) const override; + RC to_string(const Value &val, string &result) const override; + RC set_value_from_str(Value &val, const string &data) const override; + + int cast_cost(const AttrType type) override; +}; +``` + +### 步骤 4: 实现类型操作逻辑 + +创建 `src/observer/common/type/date_type.cpp`: + +```cpp +#include "common/type/date_type.h" +#include "common/value.h" + +int DateType::compare(const Value &left, const Value &right) const +{ + // 实现日期比较逻辑 + // 返回 -1 (left < right), 0 (left == right), 1 (left > right) +} + +RC DateType::add(const Value &left, const Value &right, Value &result) const +{ + // 实现日期加法运算(如加天数) + // 设置 result 的值和类型 + return RC::SUCCESS; +} + +RC DateType::to_string(const Value &val, string &result) const +{ + // 将日期值转换为字符串格式 + return RC::SUCCESS; +} + +RC DateType::set_value_from_str(Value &val, const string &data) const +{ + // 从字符串解析日期值 + return RC::SUCCESS; +} +``` + +### 步骤 5: 扩展 Value 类支持 + +在 `src/observer/common/value.h` 中添加日期类型的构造函数: + +```cpp +class Value final +{ +public: + // 现有构造函数... + explicit Value(const Date &date); // 新增:日期构造函数 + + // 现有方法... + Date get_date() const; // 新增:获取日期值 + void set_date(const Date &date); // 新增:设置日期值 +}; +``` + +### 步骤 6: 更新词法和语法规则(可选) + +如果需要支持 SQL 中的 DATE 关键字,需要修改: + +- **词法规则**: `src/observer/sql/parser/lex_sql.l` +- **语法规则**: `src/observer/sql/parser/yacc_sql.y` + +# 实现要点 + +## 1. 类型兼容性 + +实现 `cast_cost()` 方法定义类型转换成本: + +```cpp +int DateType::cast_cost(const AttrType type) override +{ + if (type == AttrType::DATES) { + return 0; // 相同类型,无转换成本 + } else if (type == AttrType::CHARS) { + return 1; // 可转换为字符串,成本为1 + } + return INT32_MAX; // 不支持转换 +} +``` + +## 2. 错误处理 + +所有操作都应返回适当的 `RC` 状态码: + +```cpp +RC DateType::add(const Value &left, const Value &right, Value &result) const +{ + if (left.attr_type() != AttrType::DATES || right.attr_type() != AttrType::INTS) { + return RC::SCHEMA_FIELD_TYPE_MISMATCH; + } + // 执行加法操作... + return RC::SUCCESS; +} +``` + +## 3. 内存管理 + +对于复杂数据类型,注意内存管理: + +```cpp +void Value::set_date(const Date &date) +{ + reset(); // 清理之前的数据 + attr_type_ = AttrType::DATES; + // 设置日期值... +} +``` + +# 测试验证 + +新增数据类型后,建议编写单元测试验证功能: + +```cpp +TEST(DateTypeTest, BasicOperations) +{ + Value date1("2023-01-01"); + Value date2("2023-01-02"); + Value result; + result.set_type(AttrType::DATES); + + // 测试比较操作 + EXPECT_EQ(DateType().compare(date1, date2), -1); + + // 测试字符串转换 + string str; + EXPECT_EQ(DateType().to_string(date1, str), RC::SUCCESS); + EXPECT_EQ(str, "2023-01-01"); +} +``` + +# 总结 + +新增数据类型需要按照上述步骤系统性地修改多个文件,确保类型系统的一致性和完整性。建议在实现过程中参考现有的 `IntegerType` 和 `FloatType` 实现,保持代码风格的一致性。 \ No newline at end of file diff --git a/docs/docs/design/miniob-sql-execution-process.md b/docs/docs/design/miniob-sql-execution-process.md index b80a83b4d..d8c0ce715 100644 --- a/docs/docs/design/miniob-sql-execution-process.md +++ b/docs/docs/design/miniob-sql-execution-process.md @@ -1,8 +1,23 @@ -如图[image](images/miniob-sql-execution-process.png) +--- +title: SQL 执行流程 +--- -PlantUML时序图使用 https://www.plantuml.com/plantuml 生成 -代码如下: -```cpp +### SQL 执行流程时序图 + +![SQL 执行流程图](images/miniob-sql-execution-process.png) + +*图:MiniOB SQL 执行流程时序图(可通过 PlantUML 源码重新生成)* + + +> 💡 提示:本图由 [PlantUML](https://www.plantuml.com/plantuml) 在线工具生成,可用于调试或更新图表。 + +--- + +#### PlantUML 源码 + +建议保存此代码以便后续修改图像内容: + +```plantuml @startuml title SQL 执行流程时序图\n diff --git a/docs/docs/how_to_build.md b/docs/docs/how_to_build.md index c6823f522..8561a1221 100644 --- a/docs/docs/how_to_build.md +++ b/docs/docs/how_to_build.md @@ -161,31 +161,66 @@ git config --global core.autocrlf false 关于该问题的进一步分析,请参考[Linux系统下执行sudo命令环境变量失效现象](https://zhuanlan.zhihu.com/p/669332689)。 也可以将cmake所在路径添加到sudo的PATH变量中来解决上述问题,请参考[sudo命令下环境变量实效的解决方法](https://www.cnblogs.com/xiao-xiaoyang/p/17444600.html)。 +### 3. 构建错误:找不到 Libevent 或 jsoncpp -### 3. Could not find a package configuration file provided by "Libevent" -在执行build.sh脚本时,遇到下面的错误 -![cmake error](images/miniob-build-libevent.png) +在执行 `build.sh init` 时可能出现以下错误: -通常是因为cmake版本原因(版本太高?)导致libevent在init阶段没有编译成功。 +![CMake Error - Libevent Not Found](images/miniob-build-libevent.png) +![CMake Error - jsoncpp Not Found](images/miniob-build-jsoncpp.png) -***解决方法:*** +### 🔍 原因 + +项目使用的第三方库 `libevent` 和 `jsoncpp` 依赖较老的 CMake 语法,与高版本 CMake(3.10+)不兼容,导致构建失败。 + +--- -在[text](../../deps/3rd/libevent/CMakeLists.txt) 中将cmake的最低版本设置 -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -改为 -cmake_minimum_required(VERSION 3.1...3.8 FATAL_ERROR) -之后重新执行 +### ✅ 解决方案(二选一) + +#### 方案一:快速修复(本地临时使用) + +修改子模块中的 CMake 配置,放宽版本限制。 + +1. 修改 `libevent`: +```bash +sed -i 's|cmake_minimum_required(VERSION 3.1 FATAL_ERROR)|cmake_minimum_required(VERSION 3.1...3.8 FATAL_ERROR)|' deps/3rd/libevent/CMakeLists.txt +``` +2. 修改 jsoncpp: +```bash +sed -i 's|cmake_policy(VERSION 3.0)|cmake_policy(VERSION 3.0...3.8)|' deps/3rd/jsoncpp/jsoncppConfig.cmake.in +``` +重新初始化: ```bash sudo bash build.sh init ``` +⚠️ 注意:此修改仅为本地临时适配,请勿提交到 Git。 + +#### 方案二:根本解决(推荐,长期使用) + +升级 libevent 和 jsoncpp 到支持现代 CMake 的新版。 +```bash +# 更新 libevent +cd deps/3rd/libevent +git checkout main && git pull origin main +cd ../../.. + +# 更新 jsoncpp +```bash +cd deps/3rd/jsoncpp +git checkout master && git pull origin master +cd ../../.. +``` +推荐切换到稳定版本: -如果你成功解决libevent的问题,你大概率会遇到另一个错误: -![cmake error](images/miniob-build-jsoncpp.png) -需要在[text](../../deps/3rd/jsoncpp/jsoncppConfig.cmake.in)中将cmake策略 -cmake_policy(VERSION 3.0) -改为 -cmake_policy(VERSION 3.0...3.8) -之后重新执行 +libevent: release-2.1.12-stable +jsoncpp: 1.9.5 或更高 +提交更新: +```bash +git add deps/3rd/libevent deps/3rd/jsoncpp +git commit -m "chore: upgrade libevent and jsoncpp for CMake compatibility" +git push origin main +``` +然后重新构建: ```bash +rm -rf build/ # 清理缓存 sudo bash build.sh init ``` \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index da6da2a87..fd5a28a14 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -34,6 +34,7 @@ nav: - design/miniob-durability.md - design/miniob-sql-parser.md - design/miniob-how-to-add-new-sql.md + - design/miniob-how-to-add-new-datatype.md - design/miniob-sql-expression.md - design/miniob-bplus-tree.md - design/miniob-bplus-tree-concurrency.md @@ -42,6 +43,8 @@ nav: - design/miniob-pax-storage.md - design/miniob-aggregation-and-group-by.md - design/miniob-lsm-tree.md + - design/miniob-realtime-analytic.md + - design/miniob-sql-execution-process.md - Doxy 代码文档: design/doxy/html/index.html - OceanBase 数据库大赛: - game/introduction.md