Skip to main content
自定义类型使用 VEF 协议 3,该协议自 v0.0.4 版本起已稳定。协议 4 正在 开发中,并且仅通过选择加入的开发 ABI 头文件提供 (-DVSQL_USE_DEV_ABI=ON)。使用旧协议 2 构建的扩展程序将被服务器拒绝,并且必须重新构建。
自定义类型允许您定义新的列类型——例如 COMPLEXUUIDVECTOR——这些类型可以与 ORDER BY、索引和聚合函数一起使用。本 页是 在 C++ 中创建扩展 教程的第 4 步。在继续操作之前,请完成第 1-3 步。

定义类型操作

每个自定义类型都需要编码、解码和比较操作,以及可选的哈希操作。针对以下签名实现它们,并将构建器对象传递给 vsql::make_type<>()
对于返回自定义类型的 VDF (from_string),服务器在调用 VDF 之前,会将 输出缓冲区的大小设置为至少为类型的 persisted_length 值,因此在进入时,可以保证 buf.size() >= persisted_length。 这适用于固定宽度类型和参数化类型(其中 persisted_length 在调用时从类型上下文中解析)。 不需要单独的缓冲区大小请求。
原始二进制访问通过 vsql::Span<T> 进行,这是一个对连续的 T 序列的非所有权视图——in.value() 返回 vsql::Span<const unsigned char>out.buffer() 返回 vsql::Span<unsigned char>。使用 C++20 或更高版本,vsql::Span<T>std::span<T> 的别名;在 C++17 下,C++ SDK 提供了一个最小的源代码兼容回退,具有相同的 data()size()empty()、索引和迭代器接口。它通过 #include <villagesql/vsql.h> 提供。

注册类型

vsql::make_type<kName>() 模板将编码、解码、比较和哈希操作直接嵌入到类型对象中。VDF 名称在编译时自动生成为 TYPE::from_stringTYPE::to_stringTYPE::compareTYPE::hash。 不需要单独的 .func(make_type_encode<>(...)) 调用。
如果缺少 from_stringto_stringcomparebuild() 将无法编译。 每个模板方法使用 static_assert 验证函数指针签名。 类型名称作为非类型模板参数 (NTTP) 传递。将其声明为 static constexpr const char[] 数组——使用指针身份来确定独立的 VDF 名称缓冲区,因此即使两个类型共享一个函数指针,它们仍然会获得单独的自动生成名称。

类型操作参考

基于模板的 API 自动生成以下可由 SQL 调用的 VDF: 有关完整的 C++ 签名,请参阅 类型操作

ALTER TABLE 和自定义类型

当涉及自定义类型时,ALTER TABLE ... MODIFY COLUMNCHANGE COLUMN 强制执行以下规则:

类型转换函数

使用基于模板的 API,编码和解码 VDF 嵌入在类型对象中,并自动注册——不需要单独的 .func() 调用。 自动生成的 VDF 可以通过 SQL 调用:
何时需要显式转换。 VillageSQL 隐式地将字符串字面量转换为自定义类型,直接赋值到列中,因此 INSERT INTO t (val) VALUES ('(1.0,2.0)') 可以在没有显式调用的情况下工作。但是,解析为 STRING 类型的表达式——CASE 表达式、CONCAT 等——不会隐式强制转换。使用 TYPE::from_string 包装它们:

示例:COMPLEX 类型

这是一个完整的示例,实现了 COMPLEX 数字类型:
定义这些操作后,用户可以创建包含自定义类型的表:

生成列中的 VDF

VDF 可用于生成列表达式。VDF 必须在扩展构建器中声明为 .deterministic()——服务器会阻止在此上下文中使用的非确定性函数。
complex_abs 必须使用 .deterministic() 注册。传统的 MySQL UDF 不允许在生成列中使用。
有关完整的实现,请参阅 vsql_complex 示例

函数索引中的 VDF

VDF 可用于函数索引表达式。与生成列相同的 .deterministic() 要求也适用于此处,因为 MySQL 将函数索引实现为隐藏的生成列。
当相同的 VDF 表达式出现在 WHEREORDER BYGROUP BY 中时,优化器会使用该索引。将比较值转换为 VDF 的返回类型,以便优化器匹配该表达式:

后续步骤

定义完类型后,请继续教程的第 5 步,以构建和安装您的扩展。

继续:构建您的扩展

返回教程,以构建和安装您的扩展。

参数化类型

接受参数的类型,例如 VECTOR(1536)——感知维度的编码、解码和存储大小调整。

扩展 API 参考

VDF API 契约、空值处理、缓冲区大小调整和高级模式。

复制

ROW 格式要求、扩展安装顺序和复制设置的版本匹配。