#rusqlite #sqlite #detail #bindings #wrapper

rusqlite-macros

rusqlite crate的私有实现细节

3 个版本 (重大更新)

0.3.0 2024年7月21日
0.2.0 2024年2月17日
0.1.0 2023年11月12日

数据库接口 中排名 2147

Download history 35/week @ 2024-05-20 26/week @ 2024-05-27 37/week @ 2024-06-03 18/week @ 2024-06-10 13/week @ 2024-06-17 23/week @ 2024-06-24 4/week @ 2024-07-01 41/week @ 2024-07-08 105/week @ 2024-07-15 80/week @ 2024-07-22 110/week @ 2024-07-29 27/week @ 2024-08-05 27/week @ 2024-08-12

每月下载量 322
rusqlite 中使用

MIT 许可证 MIT

6KB
95

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 的每个连接限制。
  • chrono 实现了从 FromSqlToSqlchrono 中的各种类型。
  • serde_json 实现了从 FromSqlToSqlserde_json 中的 Value 类型。
  • time 实现了从 FromSqlToSqltime 中的各种类型。
  • url 实现了从 FromSqlToSqlurl 中的 Url 类型。
  • bundled 使用了捆绑版本的 SQLite。这对于链接到 SQLite 复杂的情况(如 Windows)是一个好选择。
  • sqlcipher 会寻找 SQLCipher 库来链接,而不是 SQLite。这个特性会覆盖 bundled
  • bundled-sqlcipher 使用了捆绑版本的 SQLCipher。它搜索并链接到一个系统安装的加密库,以提供加密实现。
  • bundled-sqlcipher-vendored-openssl 允许使用捆绑的 SQLCipher 与 OpenSSL 的捆绑版本(通过 openssl-sys 包)作为加密提供者。
    • 如名称所示,这依赖于 bundled-sqlcipher 特性,并自动开启它。
    • 如果开启,这将使用 openssl-sys 包,并启用 vendored 特性以构建和捆绑 OpenSSL 加密库。
  • hooks提交、回滚数据变更 通知回调。
  • preupdate_hookpreupdate 通知回调。(隐含 hooks。)
  • unlock_notify解锁 通知。
  • vtab虚拟表 支持(允许你在 Rust 中编写虚拟表实现)。目前,仅支持只读虚拟表。
  • series 公开了 generate_series(...) 表值函数。(隐含 vtab。)
  • csvtab,使用 Rust 编写的 CSV 虚拟表。(隐含 vtab。)
  • arrayrarray() 表值函数。(隐含 vtab。)
  • i128_blob 允许在 SQLite 数据库中存储 i128 类型的值。内部,数据以 16 字节的大端 blob 存储的,最高有效位被翻转,这使得不同 blob 之间存储 i128 的排序和比较可以按预期工作。
  • uuid 允许使用 blob 从 uuid crate 存储和检索 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 分离的 crate,它提供了 SQLite 的 Rust 声明。默认情况下,libsqlite3-sys 尝试使用 pkg-config 在您的系统上查找已存在的 SQLite 库,或者使用 Vcpkg 安装 MSVC ABI 构建。

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

  • 如果您使用 bundledbundled-sqlcipherbundled-sqlcipher-vendored-openssl 功能,libsqlite3-sys 将使用 cc crate 从源代码编译 SQLite 或 SQLCipher,并将其链接到该库。此源代码嵌入到 libsqlite3-sys crate 中,目前为 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)库(因此不使用任何 bundled 功能)时,您可以设置 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绑定(这是默认选项)

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

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

贡献

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

为此提供帮助:您通常应该确保您为--features bundled--features "bundled-full session buildtime_bindgen"运行测试/lint。

如果运行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)

社区

欢迎加入 [Rusqlite Discord 服务器](https://discord.gg/nFYfGPB8g4) 讨论或寻求关于 rusqlitelibsqlite3-sys 的帮助。

许可证

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

捆绑软件的许可证

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

  • 如果启用了 --features=bundled-sqlcipher,则会编译并静态链接 SQLcipher 的供应商源代码。SQLcipher 在 BSD 样式许可证下分发,如[此处](https://github.com/rusqlite/rusqlite/blob/09bd40b3f126cdc333db537e3387e1a34dcc1a58/libsqlite3-sys/sqlcipher/LICENSE)所述。

  • 如果启用了 --features=bundled,则会编译并链接 SQLite 的供应商源代码。SQLite 属于公有领域,如[此处](https://www.sqlite.org/copyright.html)所述。

这两者都相当宽松,不影响 rusqlitelibsqlite3-sys 本身的许可证,如果您不使用相关功能,可以完全忽略。


lib.rs:

rusqlite 的私有实现细节。

依赖项

~1.8–2.4MB
~47K SLoC