使用 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;

服务器需要知道当 MONEYINTDOUBLEDECIMAL 相遇时应使用哪种通用类型。这些规则属于 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/)