#sqlite #ffi #sql-cipher #bindings #version #wrapper #api

sys libsqlite3-sys-ic

libsqlite3库的本地绑定

1 个不稳定版本

0.25.0 2023年1月17日

#6 in #sql-cipher


2 个crate中使用(通过 rusqlite-ic

MIT 协议

18MB
345K SLoC

C 323K SLoC // 0.3% comments Rust 22K SLoC // 0.0% comments Shell 47 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.28.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.6.8或更高版本。如果您需要支持较旧版本,请提交问题。一些Cargo功能需要较新的SQLite版本;请参见以下详细信息。

可选功能

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

  • load_extension 允许加载基于动态库的SQLite扩展。
  • backup 允许使用SQLite的在线备份API。注意:此功能需要SQLite 3.6.11或更高版本。
  • functions 允许您将Rust闭包加载到SQLite连接中,以便在查询中使用。注意:此功能需要SQLite 3.7.3或更高版本。
  • window 用于 窗口函数 支持(fun(...) OVER ...)。(隐含 functions。)
  • trace 允许钩子进入SQLite的跟踪和剖析API。注意:此功能需要SQLite 3.6.23或更高版本。
  • blob 为SQL BLOB提供 std::io::{Read, Write, Seek} 访问。注意:此功能需要SQLite 3.7.4或更高版本。
  • limits 允许您设置和检索 SQLite 的每个连接限制。
  • chronoFromSqlToSql 实现了来自 chrono crate 的各种类型。
  • serde_jsonserde_json crate 中的 Value 类型实现了 FromSqlToSql
  • time 为来自 time cratetime::OffsetDateTime 类型实现了 FromSqlToSql
  • url 为来自 url crateUrl 类型实现了 FromSqlToSql
  • bundled 使用 SQLite 的捆绑版本。这对于链接到 SQLite 复杂的情况,如 Windows,是一个好选择。
  • sqlcipher 寻找 SQLCipher 库进行链接,而不是 SQLite。此功能覆盖了 bundled
  • bundled-sqlcipher 使用 SQLCipher 的捆绑版本。它搜索并链接到一个系统安装的加密库以提供加密实现。
  • bundled-sqlcipher-vendored-openssl 允许使用带有 OpenSSL(通过 openssl-sys crate)的捆绑版本作为加密提供者的 bundled-sqlcipher
    • 正如其名所示,这依赖于 bundled-sqlcipher 功能,并自动将其打开。
    • 如果打开,这会使用 openssl-sys crate,并启用 vendored 功能来构建和捆绑 OpenSSL 加密库。
  • 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,会话模块扩展。需要 buildtime_bindgen 功能。(隐含 hooks。)
  • extra_check 在执行传递的查询为只读或有列数 > 0 时失败。
  • column_decltype 为 Statements 和 Rows 提供 columns() 方法;如果链接到使用 -DSQLITE_OMIT_DECLTYPE 编译的 SQLite/SQLCipher 版本,则省略。
  • collation 提供了 sqlite3_create_collation_v2
  • winsqlite3 允许链接到 Windows 新版本中存在的 SQLite。

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

libsqlite3-sys 是一个与 rusqlite 分离的 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.39.0(截至 rusqlite 0.28.0 / libsqlite3-sys 0.25.0)。这可能是解决任何构建问题的最简单方法。您可以在 Cargo.toml 文件中添加以下内容以启用此功能

    [dependencies.rusqlite]
    version = "0.28.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_6_8 - SQLite 3.6.8绑定(这是默认值)
  • min_sqlite_version_3_6_23 - SQLite 3.6.23绑定
  • min_sqlite_version_3_7_7 - SQLite 3.7.7绑定

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

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

贡献

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

为了帮助这里:您通常应该确保您运行了 tests/lint 对 --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)

社区

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

许可

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

捆绑软件的许可证

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

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

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

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

依赖项

约5-14MB
约158K SLoC