前提条件
使用任何预览功能的扩展,只有在vsql_allow_preview_extensions 为 ON 时才能安装:
SET GLOBAL,请参阅启用预览层。
您还需要一套可用的 Rust 扩展设置——使用 Rust 构建扩展演练涵盖了工具链、cargo-vsql 以及您的第一个 extension! 块。
Rust SDK 封装了什么
其余的预览功能——
auth、mysql_services、sql_query、statement_event 以及列存储 ABI——目前仅支持 C++。如果您需要其中之一,请使用 C++ SDK。
注册模式
将每个功能声明为static,然后在 extension! 的 requires: 部分中按引用列出它——这相当于 C++ SDK 中的 .with():
static 是必需的——服务器在扩展的整个生命周期内都持有指向该功能的指针。
状态变量
status_var 功能通过 SHOW GLOBAL STATUS 公开由扩展拥有的计数器。您的扩展以 'static 原子类型拥有存储空间并写入其中;服务器每次查询状态变量时,都会通过指针读取。
将每个变量声明为一个 StatusVarSpec——Int 由 AtomicI64 支持,或 Double 由 SDK 的 AtomicF64 支持(Rust 标准库没有原子 f64,因此 SDK 提供了一个,带有 new、load 和 store):
INSTALL EXTENSION 之后,这些变量会以扩展名称作为前缀出现:
系统变量
sys_var 功能注册由您的扩展拥有的 MySQL 系统变量。支持三种类型:Bool、Int(带 min/max 边界)和 Str。每个描述符都携带一个名称、一条在 SHOW VARIABLES 元数据中显示的注释、一个默认值以及一个可选的 on_change 回调。
名称和字符串默认值是 &'static CStr 值——请将它们写为 C 字符串字面量(c"enabled"):
funcs: 部分为空,它也必须出现在 requires: 之前。
安装之后,可以使用扩展名称作为前缀来访问这些变量:
响应变更
on_change 是一个原始 C 回调,由服务器在变量被设置之后调用。服务器在持有其全局系统变量锁时调用它,因此请让它保持快速,并且不要 panic——此处的 panic 会跨越 FFI 边界。该回调接收来自原始 ABI 层的 *const vef_sys_var_change_t:
on_change: Some(on_enabled_change) 将它接入某个描述符。
从扩展代码读取和写入
SysVarCapability 还公开了 get() 和 set(),用于通过服务器进行编程访问(因此范围验证和持久化都会为您处理)。set() 接受一个 scope 参数来选择持久化方式:null 只更改运行中的值,因此它在重启后会回退;"PERSIST" 更改运行中的值并将其写入持久化配置;"PERSIST_ONLY" 写入持久化配置而不改动运行中的值,因此它在下次重启时生效。两者都是接受 NUL 结尾 C 字符串的 unsafe FFI 方法,并且两者都使用相反的 C 约定:Some(false) 表示成功,Some(true) 表示服务器报告了错误,而 None 表示该功能不可用。在 get 成功时,服务器会写入一个 malloc 分配的字符串,您必须使用 C 的 free() 释放它。vsql_sys_var 示例展示了完整的模式,包括 free extern 和安全性注释。
线程工作器
thread_worker 功能在服务器管理的后台线程上运行您提供的函数。服务器在加载时注册一个控制系统变量;当它为 ON 时,您的工作函数会在定期计时器上、在文件描述符准备就绪时,或在启用/禁用转换时被调用。
您的工作函数是普通的安全 Rust 代码:
ThreadWorkerCapability::new 接受工作函数、一个线程名称后缀、初始睡眠间隔,以及一个可选的控制变量名称覆盖值。当该覆盖值为 None 时,控制变量被命名为 {suffix}_enabled,并注册在扩展的前缀之下:
唤醒
WakeupReason 告诉您服务器为什么进行调用:Enable、Periodic、PollFd 或 Disable。您的返回值会调整下一次唤醒:
NextWakeup::unchanged()——保持当前的睡眠间隔和轮询文件描述符。NextWakeup::after(duration)——在duration之后再次唤醒。- 将
poll_fd字段设置为一个大于零的文件描述符,以便在它变为可读时也唤醒;或设置为-1以清除先前设置的文件描述符。
Duration 会退化为“无变化”——底层 C ABI 将 0 保留给该含义,因此无法表达立即唤醒。
如果工作函数发生 panic,SDK 会在 FFI 边界捕获该 panic,并将该次调用视为返回了 NextWakeup::unchanged()——工作器会继续运行。
ThreadHandle 参数是保留的,用于在 sql_query 功能移植到 Rust 之后从工作器打开 SQL 会话;它目前还没有任何方法。
密钥环访问
keyring 功能读取和写入存储在 MySQL 密钥环组件中的密钥——API 密钥、加密密钥,以及任何不应存储在表中的内容。服务器上必须安装一个密钥环组件(例如 component_keyring_file);如果没有,每次读取和写入都会以 KeyringError::NoComponent 失败。
read(data_id, auth_id, buf) 会填充您传入的缓冲区,并返回带有密钥长度的 Ok(Some(n));或者当 data_id 下不存在密钥时返回 Ok(None)——这是一种正常结果,而不是错误。write(data_id, auth_id, data) 在成功时返回 Ok(())。auth_id 是所有者用户;对于与特定用户无关的内部密钥,请传递 None。
两者在失败时都返回 Err(KeyringError):CapabilityUnavailable(该功能从未被接入)、NoComponent(服务器上没有密钥环组件)或 Other。
密钥环没有大小探测:如果某个密钥大于您传给 read 的缓冲区,返回结果为 Ok(None),与密钥缺失无法区分。请按您预期存储的最大密钥来确定缓冲区大小。
后续步骤
预览功能 (C++)
完整的功能索引、预览层,以及仅支持 C++ 的功能:auth、mysql_services、sql_query、statement_event 和列存储。
Rust API 参考
InValue、VdfReturn、extension!、func! 和 custom_type!——所有字段。

