协会地址:上海市长宁区古北路620号图书馆楼309-313室
使用 Type_handler 向 MariaDB 添加新数据类型 – 第1部分
作者: Frédéric Descamps
原文链接:https://mariadb.org/adding-a-new-data-type-to-mariadb-with-type_handler-part-1/
这是关于如何使用 Type_handler 框架向 MariaDB 添加新数据类型系列文章的第一篇。本系列的前导文章已经发布,介绍了如何设置开发环境并编译 MariaDB 服务器:使用 Type_handler 向 MariaDB 添加新数据类型 – 第 0 部分。
在编写代码之前理解 Type_handler(类型处理器)
当你向 MariaDB 添加新类型时,你不仅仅是在添加一个新的 SQL 关键字。历史上,这类工作需要跨解析器、优化器、协议、复制和类型转换机制进行侵入式修改。
可插拔类型框架的目的是用统一的抽象 Type_handler(类型处理器)替换那些分散的修改。
这个设计目标值得明确说明:MariaDB 不希望区分“原生”类型和“插件”类型。就像存储引擎都是共同框架内的插件一样,数据类型也期望遵循统一的接口。
在此基础上,你需要教会服务器一组相关的行为:
- 该类型的列如何表示,
- 值如何存储和读取,
- 值如何暴露给客户端,
- 该类型在表达式中如何与其他类型交互。
得益于这种新架构,理解这些责任变得容易得多。MariaDB 不再将类型视为一个单一、庞大、不透明的对象,而是将工作分散到几个组件中。
这就是为什么从 Type_handler 开始如此合适。
简要的心智模型
在本系列中,请记住以下模型:
- Type_handler_ 赋予类型身份,并充当工厂。
- Field_ 实现列值的运行时存储和行为。
- Type_collection_ 决定该类型如何与其他类型组合。
- 插件声明 注册类型,以便服务器可以加载它。
如果你需要记住一句话,那就是:
自定义 MariaDB 类型需要回答三个问题:如何构建字段,如何存储和读取值,以及如何在表达式中表现。
为什么这个架构很重要
该框架的深层价值不仅在于可扩展性,还在于覆盖范围。
在旧世界中,添加新数据类型需要修改许多独立的代码路径,同时希望不遗漏任何一处。在新世界中,服务器的结构是:如果 Type_handler 接口是完整的,那么主要的类型特定行为从设计阶段就会被考虑在内。
插件中的四个组件
为了添加新的 MONEY 数据类型,我们需要准备 4 个主要组件。
1. Type\_handler\_money
该类定义了类型的身份。
在我们的最小版本中,Type_handler_money 继承自 Type_handler_newdecimal,以便将重点放在插件架构上,而不是从头实现所有数值行为。
其中最重要的一个方法是:
Field *Type_handler_money::make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *root,
const LEX_CSTRING *name,
const Record_addr &rec,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const override;
这是 SQL(结构化查询语言)与运行时行为之间的桥梁。
当 MariaDB 解析类似以下的列定义时:
amount MONEY(12,2)
该方法正是服务器将定义转换为实际 Field_money 对象的地方。
2\. Field\_money
这是运行时行为所在之处。
如果 Type_handler_money 回答了“这是什么类型?”,那么 Field_money 则回答“这个类型做什么?”。
在我们的最小化版本中,Field_money 负责:
- 接受文本或数字输入,
- 四舍五入到声明的精度,
- 检查范围,
- 在内部存储值,
- 以数字或字符串形式返回值,
- 比较两个值,
- 生成排序键,
- 描述值如何发送给客户端。
3\. Type\_collection\_money
这是许多人忽略的部分。
它控制表达式中的强制类型转换和聚合规则,例如:
SELECT amount + 1;
SELECT amount + 1.5;
SELECT amount = 10;
服务器需要知道当 MONEY 与 INT、DOUBLE 或 DECIMAL 相遇时应使用哪种通用类型。这些规则属于 Type_collection_money。
4\. 插件注册(Plugin registration)
最后,插件声明将该类型暴露给服务器:
static struct st_mariadb_data_type plugin_descriptor_type_money=
{
MariaDB_DATA_TYPE_INTERFACE_VERSION,
&type_handler_money
};
maria_declare_plugin(type_money){MariaDB_DATA_TYPE_PLUGIN,&plugin_descriptor_type_money,”money”,”lefred”,”Data type MONEY”,PLUGIN_LICENSE_GPL,0,0,0×0001,NULL,NULL,”0.1″,MariaDB_PLUGIN_MATURITY_EXPERIMENTAL}maria_declare_plugin_end;
这是一个简化的 Type_handler(类型处理器)架构的示例:
<image url="https://mariadb.org/wp-content/uploads/2026/04/image-13.png"/>
](https://mariadb.org/wp-content/uploads/2026/04/image-13.png)
## 结论
既然我们已经更熟悉 `Type_handler` 架构,下一篇文章将专门构建一个可运行的小型新 **MONEY** 数据类型。
- [Adding a New Data Type to MariaDB with Type\_handler – Part 0](https://mariadb.org/adding-a-new-data-type-to-mariadb-with-type_handler-part-0/)
- [Adding a New Data Type to MariaDB with Type\_handler – Part 1](https://mariadb.org/adding-a-new-data-type-to-mariadb-with-type_handler-part-1/)







