#sqlite #ffi

libsql-rusqlite

SQLite(libsql 分支)的便捷包装

4 个版本 (破坏性更新)

0.32.0 2024年8月7日
0.31.0 2024年6月11日
0.30.0 2024年3月8日
0.29.0 2024年1月4日

#65数据库接口

Download history 738/week @ 2024-05-01 552/week @ 2024-05-08 642/week @ 2024-05-15 581/week @ 2024-05-22 795/week @ 2024-05-29 968/week @ 2024-06-05 709/week @ 2024-06-12 1129/week @ 2024-06-19 1018/week @ 2024-06-26 990/week @ 2024-07-03 615/week @ 2024-07-10 592/week @ 2024-07-17 1976/week @ 2024-07-24 1442/week @ 2024-07-31 1766/week @ 2024-08-07 1879/week @ 2024-08-14

7,153 每月下载量
用于 5 个 Crates(直接使用 2 个)

MIT 许可证

620KB
13K SLoC

Rusqlite

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

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

历史上,API 基于来自 rust-postgres 的一个。然而,两者在很多方面已经分化,没有打算两者之间兼容。

使用方法

在你的 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.29.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 扩展。
  • 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 的各种类型。
  • serde_jsonFromSqlToSql 实现了来自 serde_jsonValue 类型。
  • time 为来自 timetime::OffsetDateTime 类型实现了 FromSqlToSql
  • url 为来自 urlUrl 类型实现了 FromSqlToSql
  • bundled 使用了SQLite的捆绑版本。这在Windows等链接SQLite比较复杂的情况下是一个好选择。
  • sqlcipher 寻找SQLCipher库进行链接,而不是SQLite。这个特性覆盖了 bundled
  • bundled-sqlcipher 使用SQLCipher的捆绑版本。这会搜索并链接到系统安装的加密库,以提供加密实现。
  • bundled-sqlcipher-vendored-openssl 允许使用捆绑的SQLCipher与捆绑版本的OpenSSL(通过 openssl-sys 包)一起作为加密提供者。
    • 正如其名所示,这依赖于 bundled-sqlcipher 特性,并自动打开它。
    • 如果打开,这将使用具有 vendored 特性启用的 openssl-sys 包来构建和捆绑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 包存储和检索 Uuid 值。
  • session,会话模块扩展。需要buildtime_bindgen特性。(隐含hooks。)
  • extra_check在执行查询时,如果查询为只读或有列数>0时将失败。
  • column_decltype为语句和行提供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.41.2(截至rusqlite 0.29.0 / libsqlite3-sys 0.26.0)。这可能是解决任何构建问题的最简单方法。您可以通过在Cargo.toml文件中添加以下内容来启用此功能

    [dependencies.rusqlite]
    version = "0.29.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-config和vcpkg的构建助手有一些额外的配置选项。使用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 是多个人共同努力的成果。名单可在此处查看:[Rusqlite GitHub 贡献者](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 代码本身的许可证,如果您不使用这些功能,则可以完全忽略。

依赖项

~42MB
~716K SLoC