Skip to main content
Rust SDK 处于 alpha 阶段——各版本之间可能出现破坏性的 API 变更。支持纯函数扩展、聚合函数、变长参数函数以及自定义类型(encode、decode、compare、hash),同时也支持 sys_varstatus_varthread_workerkeyring 预览功能。列存储 ABI 目前仅在 C++ SDK 中提供——如果您需要它,请使用 C++ SDK
本页是 villagesql crate API 的参考。有关入门教程,请参阅 使用 Rust 构建扩展。有关自定义类型,请参阅 Rust 中的自定义类型

InValue

InValue 是服务器为每个函数参数传递的枚举。您的函数接收 args: &[InValue],并且必须在使用其值之前检查每个参数。
始终显式匹配 Null。调用 .unwrap() 或仅模式匹配值变体是一种错误——SQL NULL 是一种正常的输入,而不是错误。

VdfReturn

VdfReturn 是您的函数返回给服务器的内容。使用以下关联函数之一构造它: 警告与错误: 对于用户输入验证失败的情况,如果继续处理其余结果集是有意义的,请使用 warning。在严格模式下,MySQL 会在 INSERTUPDATE 上将警告升级为错误。对于继续操作不安全的情况(损坏存储的数据、违反内部不变量),请使用 error。致命错误会中止整个语句。

extension! 宏

extension! 生成服务器在加载 VEB 文件时调用的 VEF 入口点。它必须在 crate 中恰好出现一次。
types:requires: 各自都是可选的,但 funcs: 必须始终存在——对于仅类型扩展,请写 funcs: []。纯函数扩展省略 types:。一个带有 funcs: [] 且没有类型的 extension! 块是有效的,但会生成一个不执行任何操作的扩展。 requires: 声明扩展所使用的 Rust 中的预览功能,以对 static 功能对象的引用的形式给出。它必须放在最后,位于 funcs: 部分之后——如果扩展不注册任何函数,请包含 funcs: []

func! 宏

func! 声明一个可从 SQL 调用的函数。有六种形式——四种不带每个语句状态的形式(不带可选参数、仅 buffer_size、仅 deterministic、两者都有),以及两种通过 prerun 函数附加每个语句状态的形式:
buffer_size 参数需要 villagesql crate 0.0.2 或更高版本。当前的 crates.io 发布版本(0.0.1)尚未公开该参数——在 0.0.2 发布之前,请使用不带 buffer_size 的形式。
func! 中使用的 类型常量

每个语句的状态

有些函数需要跨单个语句的每一行都存在的状态——调用计数器、累加器。使用 state: 声明状态类型,使用 prerun: 声明一个设置函数。prerun 函数在第一行之前运行一次;随后行函数对每一行运行一次,并对该状态拥有 &mut 访问权限。 prerun 函数的签名是 fn(PrerunArgs, PrerunResult<T>),它所供给状态的行函数将状态作为第一个参数:fn(state: &mut T, args: &[InValue]) -> VdfReturnT 是由 state: 指定的类型,编译器会检查 prerun 与行函数在该类型上是否一致。 PrerunArgs::len() 是每一行将接收的参数数量,当函数调用时不带任何参数时,PrerunArgs::is_empty() 为真。 您不能自行释放该状态:func! 会生成在语句结束时丢弃它的 postrun。这与 C++ SDK 相反,在 C++ SDK 中,您的 postrun 必须调用 delete_state<T>()——请参阅每个语句的状态
stateprerun 参数尚未包含在已发布的版本中。当前的 crates.io 发布版本(0.0.1) 尚未公开它们。
一个完整的扩展示例,其函数返回它在语句内自身的调用序号:
按照使用 Rust 构建扩展中的说明构建并安装它,然后:
该表有三行,因此 call_index() 运行三次,依次返回 123——每行一个值。SUM 将这三个值相加,得到 6 第二个 SELECT 返回与第一个相同的总和,而不是更大的值:该计数器为一个语句分配,并在该语句结束时被丢弃。

agg_func! 宏

agg_func! 声明一个聚合 SQL 函数——类似 SUM/COUNT 的风格,对每个分组的各行调用,而不是每行调用一次。有两种形式:
agg_func! 尚未包含在已发布的版本中。当前的 crates.io 发布版本(0.0.1) 尚未公开它。
累加器在每个语句中分配一次,并在语句结束时被丢弃——agg_func! 会同时生成创建它的 prerun 和丢弃它的 postrun,因此这两者您都无需编写。clear_fn 是实现按分组行为的机制:使用 GROUP BY 时,同一个累加器会在各分组之间复用,因此任何不得在分组之间泄漏的字段都必须在那里重置。 一个完整的、等价于 SUM 的聚合——SDK 仓库中的 vsql_agg_sum 示例:
accumulate 只匹配 InValue::Int,这正是跳过 NULL 的方式,与内置 SUM 一致。seen 标志使得全为 NULL 的分组和空分组返回 NULL 而不是 0

varargs_func! 宏

varargs_func! 声明一个接受任意数量、任意类型参数的 VDF。参数列表写作 [..]——这是一个必需的字面量,而不是零参数 func! 所使用的 []
对于变长参数 VDF,服务器不执行任何参数数量和参数类型的验证。没有已声明的参数列表可用来检查调用,因此每次调用都会把 SQL 文本传入的任何内容原样送达您的函数,包括零个参数和您从未预期的类型。验证完全是 prerun 钩子的职责。变长参数注册还需要 VEF Protocol 3——较旧的服务器会在安装时拒绝该扩展。这与 C++ SDK 一致,在 C++ SDK 中,框架同样无法为变长参数 VDF 验证参数数量或类型
共有六种形式——三种形态,每种形态都有一个简写形式和一个完整形式,完整形式同时添加 buffer_sizedeterministic(决不单独添加):
裸形式没有任何验证,并且接受零参数调用——对于一个对每种输入都有定义的函数来说,这是一个合理的选择,但这意味着行函数必须独自处理它可能收到的每一种输入。只有 state: 形式会分配和丢弃每个语句的状态;仅 prerun 形式使用 PrerunResult<()> 且不存储任何内容,因此它没有 postrun——这样的 prerun 只将 PrerunResult 用于 errorrequest_buffer_size,决不调用 set_state

在 prerun 中检查参数类型

由于服务器不做任何验证,变长参数的 prerun 需要在第一行运行之前查看参数类型。PrerunArgs::type_at 提供了这一视图,此外还有 len()/is_empty(),以及每个语句的状态中描述的 PrerunResult 方法。 is_custom()custom_name() 搭配使用,可以只接受某一个自定义类型:单独使用 is_custom() 会接受服务器中的每一个自定义类型。
varargs_func!PrerunArgs::type_at 尚未包含在已发布的版本中。当前的 crates.io 发布版本(0.0.1) 尚未公开它们。
SDK 仓库中的 vsql_varargs 示例为每种形式各声明了一个函数。下面是一个有状态的变长参数函数,它在 prerun 中进行验证,并携带一个每个语句的调用计数器:
即使 prerun 已证明每个参数都是字符串,str_join 仍在行函数中对 InValue 进行匹配:prerun 看到的是已声明的类型,而不是值,并且 STRING 列在任何一行上都可能携带 NULL。
该示例还声明了 describe(一个仅 prerun 的函数,它拒绝零参数和非标量参数,然后格式化一个混合类型的参数列表)和 point_path(它使用 is_custom()custom_name() 进行验证)。请参阅 Rust SDK 仓库中的 examples/vsql_varargs/src/lib.rs

custom_type! 宏

custom_type! 注册一个新的列类型。type_namepersisted_lengthmax_decode_buffer_lengthencodedecodecompare 是必需的。hashdefault 是可选的,但建议使用。
default 字段不是列的默认值——它是一个启动探测。服务器在加载扩展时调用 encode(default) 以验证回调是否正常工作。如果 encode 对该默认值返回 Err,则扩展将无法加载。

custom! 宏

villagesql::custom!("type_name")func! 声明中按名称引用一个自定义类型:
在任何可以使用 villagesql::Type::* 的参数列表或返回类型位置中使用它。该字符串必须与相应的 custom_type! 中声明的 type_name 匹配。

manifest.json 字段

每个扩展都需要一个与 Cargo.toml 位于同一位置的 manifest.json 文件:
name 验证规则:必须以字母开头,以字母或数字结尾,最大长度为 64 个字符。无效的清单会导致 INSTALL EXTENSION 失败。