COMPLEX、UUID 或
VECTOR——这些类型可以与 ORDER BY、索引和聚合函数一起使用。本
页是 创建扩展
教程的第 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 下,SDK 提供了一个最小的源代码兼容回退,具有相同的 data()、size()、empty()、索引和迭代器接口。它通过 #include <villagesql/vsql.h> 提供。
注册类型
vsql::make_type<kName>() 模板将编码、解码、比较和哈希操作直接嵌入到类型对象中。VDF 名称在编译时自动生成为
TYPE::from_string、TYPE::to_string、TYPE::compare 和 TYPE::hash。
不需要单独的 .func(make_type_encode<>(...)) 调用。
from_string、to_string 或 compare,build() 将无法编译。
每个模板方法使用 static_assert 验证函数指针签名。
类型名称作为非类型模板参数 (NTTP) 传递。将其声明为
static constexpr const char[] 数组——使用指针身份来确定独立的 VDF 名称缓冲区,因此即使两个类型共享一个函数指针,它们仍然会获得单独的自动生成名称。
类型操作参考
基于模板的 API 自动生成以下可由 SQL 调用的 VDF:
有关完整的 C++ 签名,请参阅 类型操作构建器。
ALTER TABLE 和自定义类型
当涉及自定义类型时,ALTER TABLE ... MODIFY COLUMN 和 CHANGE COLUMN 强制执行以下规则:
类型转换函数
使用基于模板的 API,编码和解码 VDF 嵌入在类型对象中,并自动注册——不需要单独的.func() 调用。
自动生成的 VDF 可以通过 SQL 调用:
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 不允许在生成列中使用。功能索引中的 VDF
VDF 可用于功能索引表达式。与生成列相同的.deterministic() 要求也适用于此处,因为 MySQL 将功能索引实现为隐藏的生成列。
WHERE、ORDER BY 或 GROUP BY 中时,优化器会使用该索引。将比较值转换为 VDF 的返回类型,以便优化器匹配该表达式:
后续步骤
定义完类型后,请继续教程的第 5 步,以构建和安装您的扩展。继续:构建您的扩展
返回教程,以构建和安装您的扩展。
参数化类型
接受参数的类型,例如
VECTOR(1536)——感知维度的编码、解码和存储大小调整。扩展 API 参考
VDF API 契约、空值处理、缓冲区大小调整和高级模式。
复制
ROW 格式要求、扩展安装顺序和复制设置的版本匹配。

