#sqlite #ffi

rusqlite

SQLite 的便捷包装器

64 个版本 (32 个重大更改)

0.32.1 2024 年 7 月 26 日
0.31.0 2024 年 2 月 17 日
0.30.0 2023 年 11 月 12 日
0.29.0 2023 年 3 月 26 日
0.0.1 2014 年 11 月 21 日

#1 in 数据库接口

Download history 231025/week @ 2024-05-03 222238/week @ 2024-05-10 254953/week @ 2024-05-17 238135/week @ 2024-05-24 266363/week @ 2024-05-31 247074/week @ 2024-06-07 246190/week @ 2024-06-14 243172/week @ 2024-06-21 225746/week @ 2024-06-28 205661/week @ 2024-07-05 222218/week @ 2024-07-12 223878/week @ 2024-07-19 228336/week @ 2024-07-26 213521/week @ 2024-08-02 230140/week @ 2024-08-09 179246/week @ 2024-08-16

894,121 每月下载量
用于 1,147 个 Crates (772 个直接使用)

MIT 许可证

20MB
387K SLoC

C 349K SLoC // 0.3% comments Rust 38K SLoC // 0.0% comments Shell 54 SLoC // 0.2% comments

Rusqlite

Latest Version Documentation Build Status (GitHub) Build Status (AppVeyor) Code Coverage Dependency Status Discord Chat

Rusqlite 是 Rust 从 SQLite 中使用的便捷包装器。

历史上,API 基于 rust-postgres 的 API。然而,两者在许多方面都发生了分歧,并且没有计划让它们兼容。

用法

在你的 Cargo.toml 中

[dependencies]
# `bundled` causes us to automatically compile and link in an up to date
# version of SQLite for you. This avoids many common build issues, and
# avoids depending on the version of SQLite on the users system (or your
# system), which may be old or missing. It's the right choice for most
# programs that control their own SQLite databases.
#
# That said, it's not ideal for all scenarios and in particular, generic
# libraries built around `rusqlite` should probably not enable it, which
# is why it is not a default feature -- it could become hard to disable.
rusqlite = { version = "0.32.0", features = ["bundled"] }

简单示例用法

use rusqlite::{Connection, Result};

#[derive(Debug)]
struct Person {
    id: i32,
    name: String,
    data: Option<Vec<u8>>,
}

fn main() -> Result<()> {
    let conn = Connection::open_in_memory()?;

    conn.execute(
        "CREATE TABLE person (
            id    INTEGER PRIMARY KEY,
            name  TEXT NOT NULL,
            data  BLOB
        )",
        (), // empty list of parameters.
    )?;
    let me = Person {
        id: 0,
        name: "Steven".to_string(),
        data: None,
    };
    conn.execute(
        "INSERT INTO person (name, data) VALUES (?1, ?2)",
        (&me.name, &me.data),
    )?;

    let mut stmt = conn.prepare("SELECT id, name, data FROM person")?;
    let person_iter = stmt.query_map([], |row| {
        Ok(Person {
            id: row.get(0)?,
            name: row.get(1)?,
            data: row.get(2)?,
        })
    })?;

    for person in person_iter {
        println!("Found person {:?}", person.unwrap());
    }
    Ok(())
}

支持的 SQLite 版本

基础 rusqlite 包支持 SQLite 版本 3.14.0 或更高版本。如果您需要支持旧版本,请提交一个问题。一些 cargo 功能需要更高版本的 SQLite;请参阅下面的详细信息。

可选功能

Rusqlite 提供了几个位于 Cargo 功能 之后的特性。它们是

  • load_extension 允许加载基于动态库的 SQLite 扩展。
  • loadable_extension 允许在 Rust 中编程 可加载扩展
  • backup 允许使用 SQLite 的在线备份 API。
  • functions 允许您将 Rust 闭包加载到 SQLite 连接中以便在查询中使用。
  • window 支持 窗口函数 (fun(...) OVER ...)。 (隐含 functions)。
  • trace 允许挂钩 SQLite 的跟踪和剖析 API。
  • blob 提供对 SQL BLOB 的 std::io::{Read, Write, Seek} 访问。
  • limits 允许您设置和检索 SQLite 的每个连接限制。
  • chronoFromSqlToSql 实现了来自 chrono crate 的各种类型。
  • serde_jsonFromSqlToSql 实现了来自 serde_json crateValue 类型。
  • timeFromSqlToSql 实现了来自 time crate 的各种类型。
  • urlFromSqlToSql 实现了来自 url crateUrl 类型。
  • bundled 使用了内置的 SQLite 版本。这在链接 SQLite 复杂的情况下是一个好选择,例如在 Windows 上。
  • sqlcipher 寻找 SQLCipher 库进行链接,而不是 SQLite。这个特性覆盖了 bundled
  • bundled-sqlcipher 使用了内置的 SQLCipher 版本。这会在系统中搜索并链接加密库以提供加密实现。
  • bundled-sqlcipher-vendored-openssl 允许使用内置的 SQLCipher 与通过 openssl-sys crate 供应商版本的 OpenSSL(作为加密提供者)一起使用。
    • 如名称所示,这依赖于 bundled-sqlcipher 特性,并自动启用它。
    • 如果启用,这会使用带有启用的 vendored 特性的 openssl-sys crate,以构建和捆绑 OpenSSL 加密库。
  • hooks 用于 提交、回滚数据更改 通知回调。
  • preupdate_hook 用于 预更新 通知回调。(隐含 hooks。)
  • unlock_notify 用于 解锁 通知。
  • vtab 用于 虚拟表 支持(允许您用 Rust 编写虚拟表实现)。目前,仅支持只读虚拟表。
  • series 暴露了 generate_series(...) 表值函数。(隐含 vtab。)
  • csvtab,用 Rust 编写的 CSV 虚拟表。(隐含 vtab。)
  • arrayrarray() 表值函数。(隐含 vtab。)
  • i128_blob 允许在 SQLite 数据库中存储 i128 类型的值。内部,数据以 16 字节的大端格式存储,最高有效位翻转,这使得存储不同 i128 的 blob 之间的排序和比较能够按预期工作。
  • uuid 允许使用 blob 从 uuid 包中存储和检索 Uuid 值。
  • session,Session 模块扩展。需要 buildtime_bindgen 功能。(隐含 hooks。)
  • extra_check 在执行查询时失败,如果查询是只读的或列数大于 0。
  • column_decltype 为 Statements 和 Rows 提供了 columns() 方法;如果链接到使用 -DSQLITE_OMIT_DECLTYPE 编译的 SQLite/SQLCipher 版本,则省略。
  • collation 暴露了 sqlite3_create_collation_v2
  • serialize 暴露了 sqlite3_serialize(3.23.0)。

关于构建 rusqlite 和 libsqlite3-sys 的说明

libsqlite3-sys 是一个独立的包,与 rusqlite 一起提供 SQLite 的 Rust 声明。默认情况下,libsqlite3-sys 尝试使用 pkg-config 在您的系统上找到现有的 SQLite 库,或者为 MSVC ABI 构建使用 Vcpkg 安装。

您可以通过多种方式调整此行为

  • 如果您使用 bundledbundled-sqlcipherbundled-sqlcipher-vendored-openssl 功能,libsqlite3-sys 将使用 cc 包从源代码编译 SQLite 或 SQLCipher,并将其链接到该代码。此源代码嵌入到 libsqlite3-sys 包中,目前为 SQLite 3.46.0(截至 rusqlite 0.32.0 / libsqlite3-sys 0.30.0)。这可能是解决构建问题的最简单方法。您可以在 Cargo.toml 文件中添加以下内容以启用此功能

    [dependencies.rusqlite]
    version = "0.32.0"
    features = ["bundled"]
    
  • 使用任何 bundled 功能时,构建脚本将尊重 SQLITE_MAX_VARIABLE_NUMBERSQLITE_MAX_EXPR_DEPTH 变量。它还将尊重一个 LIBSQLITE3_FLAGS 变量,其格式类似于 "-USQLITE_ALPHA -DSQLITE_BETA SQLITE_GAMMA ..."。这将禁用 SQLITE_ALPHA 标志,并设置 SQLITE_BETASQLITE_GAMMA 标志。(最后一个 -D 可以省略。)

  • 使用 bundled-sqlcipher(且不使用 bundled-sqlcipher-vendored-openssl),libsqlite3-sys 需要链接到系统上的加密库。如果构建脚本可以找到 OpenSSL 或 LibreSSL 的 libcrypto(它将咨询 OPENSSL_LIB_DIR/OPENSSL_INCLUDE_DIROPENSSL_DIR 环境变量),则将使用该库。如果在 Mac 上构建,并且没有设置这些变量,则将使用系统上的 SecurityFramework。

  • 当链接到系统上已存在的SQLite(或SQLCipher)库(因此不使用任何捆绑功能),可以将环境变量SQLITE3_LIB_DIR(或SQLCIPHER_LIB_DIR)设置为一个包含库的目录。您还可以设置环境变量SQLITE3_INCLUDE_DIR(或SQLCIPHER_INCLUDE_DIR),使其指向包含sqlite3.h的目录。

  • 安装sqlite3开发包通常就足够了,但pkg-configvcpkg的构建辅助程序有一些额外的配置选项。使用vcpkg的默认设置为动态链接,必须在构建前设置环境变量VCPKGRS_DYNAMIC=1。使用vcpkg install sqlite3:x64-windows将安装所需的库。

  • 当链接到系统上已存在的SQLite(或SQLCipher)库时,可以将环境变量SQLITE3_STATIC(或SQLCIPHER_STATIC)设置为1,以请求将库以静态方式而不是动态方式链接。

绑定生成

我们使用bindgen从SQLite的C头文件生成Rust声明。bindgen推荐在库的构建过程中运行此命令,我们尝试过(特别是rusqlite 0.10.0),但它有一些令人烦恼的地方。

  • libsqlite3-sys(因此rusqlite)的构建时间显著增加。
  • 运行bindgen需要相对较新的Clang版本,许多系统默认并未安装。
  • 运行bindgen还需要SQLite头文件存在。

截至rusqlite 0.10.1,我们通过提供几个SQLite版本的预生成绑定来避免在构建时运行bindgen。编译rusqlite时,我们使用您选择的Cargo功能来选择支持您所选功能的最低SQLite版本绑定。如果您直接使用libsqlite3-sys,可以使用相同的特性来选择预生成的绑定。

  • min_sqlite_version_3_14_0 - SQLite 3.14.0绑定(这是默认设置)

如果您使用任何捆绑功能,您将获得SQLite/SQLCipher捆绑版本的预生成绑定。如果您需要其他特定的预生成绑定版本,请提交一个问题。如果您希望在构建时运行bindgen以生成自己的绑定,请使用buildtime_bindgen Cargo功能。

如果您启用modern_sqlite功能,我们将使用与捆绑构建一起包含的绑定。如果您打开此选项,通常应该启用buildtime_bindgen,否则您需要保持您链接的SQLite版本与rusqlite捆绑的版本同步(通常是SQLite的最新版本)。未能这样做将导致运行时错误。

贡献

Rusqlite具有许多功能,其中许多以不兼容的方式影响构建配置。这是不幸的,使得测试更改变得困难。

在此提供帮助:您通常应确保运行测试/代码风格检查 --features bundled,以及 --features "bundled-full session buildtime_bindgen"

如果您运行 bindgen 有问题,可以使用 --features bundled-full 来启用捆绑和所有不需要绑定生成的功能,并将其作为替代方案。

清单

  • 运行 cargo fmt 确保您的 Rust 代码格式正确。
  • 确保 cargo clippy --workspace --features bundled 没有警告通过。
  • 确保 cargo clippy --workspace --features "bundled-full session buildtime_bindgen" 没有警告通过。
  • 确保 cargo test --workspace --features bundled 没有失败报告。
  • 确保 cargo test --workspace --features "bundled-full session buildtime_bindgen" 没有失败报告。

作者

Rusqlite 是由许多人共同努力的成果。名单在此处可供查阅:[https://github.com/rusqlite/rusqlite/graphs/contributors](https://github.com/rusqlite/rusqlite/graphs/contributors)

社区

欢迎加入 Rusqlite Discord 服务器,讨论或寻求 rusqlitelibsqlite3-sys 的帮助。

许可协议

Rusqlite 和 libsqlite3-sys 在 MIT 许可协议下可用。更多信息请参阅 LICENSE 文件。

捆绑软件的许可协议

根据启用的 cargo features,rusqlite 和 libsqlite3-sys 也会捆绑其他库,这些库有自己的许可条款。

  • 如果启用了 --features=bundled-sqlcipher,将编译并静态链接 SQLcipher 的供应商源代码。SQLcipher 在 BSD 风格许可下分发,详情请见 此处

  • 如果启用了 --features=bundled,将编译并链接 SQLite 的供应商源代码。SQLite 处于公有领域,详情请见 此处

这两个都是相当宽松的,不影响 rusqlitelibsqlite3-sys 代码本身的许可协议,如果您不使用相关功能,则可以完全忽略。

依赖项

~1.5–9MB
~75K SLoC