#sqlite #native-bindings #sql-cipher

sys libsqlite3-sys

对libsqlite3库的本机绑定

54个版本 (28个重大更改)

0.30.1 2024年7月26日
0.29.0 2024年6月22日
0.28.0 2024年1月27日
0.27.0 2023年11月12日
0.0.12 2015年3月29日

#7 in 数据库接口

Download history 462745/week @ 2024-05-03 477580/week @ 2024-05-10 506303/week @ 2024-05-17 478324/week @ 2024-05-24 537977/week @ 2024-05-31 517739/week @ 2024-06-07 497399/week @ 2024-06-14 504344/week @ 2024-06-21 475848/week @ 2024-06-28 469338/week @ 2024-07-05 486360/week @ 2024-07-12 501569/week @ 2024-07-19 517721/week @ 2024-07-26 501240/week @ 2024-08-02 533419/week @ 2024-08-09 550736/week @ 2024-08-16

2,203,955 每月下载量
用于 2,054 个crates (75直接)

MIT 许可证

19MB
374K SLoC

C 350K SLoC // 0.3% comments Rust 24K SLoC // 0.0% comments Shell 55 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 类型。
  • time 为来自 time crate 的各种类型实现了 FromSqlToSql
  • url 为来自 url crateUrl 类型实现了 FromSqlToSql
  • bundled 使用了捆绑版的 SQLite。这对于像 Windows 这样链接到 SQLite 复杂的情况来说是一个好选择。
  • sqlcipher 寻找 SQLCipher 库来链接,而不是 SQLite。此功能覆盖了 bundled
  • bundled-sqlcipher 使用了 SQLCipher 的捆绑版本。它搜索并链接到一个系统安装的加密库来提供加密实现。
  • bundled-sqlcipher-vendored-openssl 允许使用带有供应商版本的开源 OpenSSL(通过 openssl-sys crate)作为加密提供者的捆绑 sqlcipher。
    • 如名称所示,这依赖于 bundled-sqlcipher 功能,并自动将其打开。
    • 如果打开,则使用具有启用 vendored 功能的 openssl-sys crate,以构建和捆绑 OpenSSL 加密库。
  • hooks 用于 提交、回滚数据更改 通知回调。
  • preupdate_hook 用于 预更新 通知回调。(隐含 hooks。)
  • unlock_notify 用于 解锁 通知。
  • vtab 用于 虚拟表 支持(允许您在 Rust 中编写虚拟表实现)。目前,仅支持只读虚拟表。
  • series 公开了 generate_series(...) 表值函数。(隐含 vtab。)
  • csvtab,用Rust编写的CSV虚拟表。(意味着 vtab。)
  • array,表值函数 rarray()。(意味着 vtab。)
  • i128_blob 允许在SQLite数据库中存储 i128 类型的值。内部,数据以16字节的big-endian blob形式存储,最高有效位被反转,这使得存储i128的不同blob之间的排序和比较能够按预期工作。
  • uuid 允许使用blob从 uuid crate 存储和检索 Uuid 值。
  • session,会话模块扩展。需要 buildtime_bindgen 功能。(意味着 hooks。)
  • extra_check 当传递给执行查询为只读或列数 > 0 时会失败。
  • column_decltype 为语句和行提供 columns() 方法;如果链接到使用 -DSQLITE_OMIT_DECLTYPE 编译的SQLite/SQLCipher版本,则省略。
  • collation公开了 sqlite3_create_collation_v2
  • serialize公开了 sqlite3_serialize(3.23.0)。

关于构建rusqlite和libsqlite3-sys的注意事项

libsqlite3-sys 是一个独立的crate,它提供了SQLite C API的Rust声明。默认情况下,libsqlite3-sys 会尝试使用pkg-config找到您系统上已经存在的SQLite库,或者为MSVC ABI构建使用 Vcpkg 安装。

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

  • 如果您使用 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 的捆绑版本的预生成绑定。如果您需要其他特定的预生成绑定版本,请提交一个 issue。如果您想在构建时运行 bindgen 以生成自己的绑定,请使用 buildtime_bindgen Cargo 特性。

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

贡献

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

以下是一些建议:通常,您应该确保运行测试/lint for --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服务器[https://discord.gg/nFYfGPB8g4](https://discord.gg/nFYfGPB8g4)来讨论或获取有关rusqlitelibsqlite3-sys的帮助。

许可证

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

捆绑软件的许可证

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

  • 如果启用了--features=bundled-sqlcipher,则会编译和静态链接SQLcipher的供应商源代码。SQLcipher以BSD风格的许可证分发,如此处所述。

  • 如果启用了--features=bundled,则会编译和链接SQLite的供应商源代码。SQLite处于公共领域,如此处所述。

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

依赖项