用 Rust 扩展 SQLite
作为进程内数据库,SQLite 具有其他扩展机制,例如 用户定义函数(简称 UDF)。但是UDF有一些缺点:
UDF 在 SQLite 连接中是当前生效的,而不是为所有连接共享;
UDF 必须在程序中定义。这意味着您需要在与您的应用程序相同的作用域内使用该功能。
这就是 UDF 的用武之地。UDF 可以用任何可以编译为共享库或者 DLL 的编程语言编写。然后,您可以共享已编译的对象并从任何应用程序或编程语言中加载它们。在这篇文章中,我们将看到如何使用Rust编写 SQLite 可加载扩展。
借鉴
我们可以从 phiresky/sqlite-zstd 学到的 SQLite UDF 简化版本技术。这是一个在 SQLite 上启用 zstd 压缩的 SQLite 扩展,如果您想查看比这篇文章更高级的示例,我强烈建议您查看它。
Cargo.toml
需要依赖:https://github.com/Genomicsplc/rusqlite/tree/loadable-extensions 原因是 #910
合并版本为:https://github.com/litements/rusqlite/tree/loadable-extensions-release-2
crate-type 标记为:["cdylib"]。这将告诉 rust 编译器我们正在构建一个共享库。
[package]
name = "sqlite-regex"
version = "0.1.0"
edition = "2021"
[features]
default = []
build_extension = ["rusqlite/bundled", "rusqlite/functions"]
[lib]
crate-type = ["cdylib"]
[dependencies]
regex = "1.5.4"
log = "0.4.14"
env_logger = "0.9.0"
anyhow = "1.0.54"
[dependencies.rusqlite]
package = "rusqlite"
git = "https://github.com/litements/rusqlite/"
branch = "loadable-extensions-release-2"
default-features = false
features = ["loadable_extension", "vtab", "functions", "bundled"]
编写扩展和入口函数
函数 ah 作用是会将一个 anyhow 错误转换为 rusqlite 错误;函数 init_logging 则将设置 env_logger。
#![allow(clippy::missing_safety_doc)]
use crate::ffi::loadable_extension_init;
use an