25个版本 (1 个稳定版)
1.0.0 | 2024年7月11日 |
---|---|
0.10.2 | 2024年4月24日 |
0.10.1 | 2024年3月19日 |
0.9.2 | 2023年12月1日 |
0.1.2 | 2021年7月31日 |
#28 在 数据库接口
每月下载量16,465
用于 19 个crate(16 个直接使用)
7MB
11K SLoC
duckdb-rs
duckdb-rs 是一个用于从 Rust 使用 DuckDB 的舒适包装。它试图提供一个类似于 rusqlite 的接口。实际上,初始代码甚至这个 README 文件都是从 rusqlite 分支出来的,因为 DuckDB 也试图公开一个与 sqlite3 兼容的 API。
use duckdb::{params, Connection, Result};
// In your project, we need to keep the arrow version same as the version used in duckdb.
// Refer to https://github.com/wangfenjin/duckdb-rs/issues/92
// You can either:
use duckdb::arrow::record_batch::RecordBatch;
// Or in your Cargo.toml, use * as the version; features can be toggled according to your needs
// arrow = { version = "*", default-features = false, features = ["prettyprint"] }
// Then you can:
// use arrow::record_batch::RecordBatch;
use duckdb::arrow::util::pretty::print_batches;
#[derive(Debug)]
struct Person {
id: i32,
name: String,
data: Option<Vec<u8>>,
}
fn main() -> Result<()> {
let conn = Connection::open_in_memory()?;
conn.execute_batch(
r"CREATE SEQUENCE seq;
CREATE TABLE person (
id INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq'),
name TEXT NOT NULL,
data BLOB
);
")?;
let me = Person {
id: 0,
name: "Steven".to_string(),
data: None,
};
conn.execute(
"INSERT INTO person (name, data) VALUES (?, ?)",
params![me.name, me.data],
)?;
// query table by rows
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 {
let p = person.unwrap();
println!("ID: {}", p.id);
println!("Found person {:?}", p);
}
// query table by arrow
let rbs: Vec<RecordBatch> = stmt.query_arrow([])?.collect();
print_batches(&rbs).unwrap();
Ok(())
}
关于构建 DuckDB 和 libduckdb-sys 的说明
libduckdb-sys
是一个与 duckdb-rs
分离的 crate,它提供了 DuckDB C API 的 Rust 声明。默认情况下,libduckdb-sys
会尝试使用 pkg-config 在您的系统上查找已存在的 DuckDB 库,或者为 MSVC ABI 构建使用 Vcpkg 安装。
您可以通过多种方式调整此行为
-
如果您使用
bundled
功能,libduckdb-sys
将使用 cc crate 从源代码编译 DuckDB 并链接到它。此源代码嵌入在libduckdb-sys
crate 中,因为我们仍在开发中,我们将定期更新它。当我们更稳定时,我们将使用来自 duckdb 的稳定发布版本。这可能是在构建问题中最简单的解决方案。您可以通过在Cargo.toml
文件中添加以下内容来启用此功能cargo add duckdb --features bundled
Cargo.toml
将被更新。[dependencies] # Assume that version DuckDB version 0.9.2 is used. duckdb = { version = "0.9.2", features = ["bundled"] }
-
当链接到系统上现有的 DuckDB 库(因此 不 使用任何
bundled
功能)时,您可以设置DUCKDB_LIB_DIR
环境变量,使其指向包含库的目录。您还可以设置DUCKDB_INCLUDE_DIR
变量,使其指向包含duckdb.h
的目录。 -
安装 duckdb 开发包通常就足够了,但 pkg-config 和 vcpkg 的构建助手有一些额外的配置选项。使用 vcpkg 的默认设置是动态链接,必须在构建前设置
VCPKGRS_DYNAMIC=1
环境变量。
绑定生成
我们使用 bindgen 从 DuckDB 的 C 头文件生成 Rust 声明。 bindgen
由 推荐 在使用此库的库的构建过程中运行。我们尝试过这种方法(具体为 duckdb
0.10.0),但有一些不便之处。
libduckdb-sys
(以及因此duckdb
)的构建时间显著增加。- 运行
bindgen
需要一个相对较新的 Clang 版本,而许多系统默认并未安装。 - 运行
bindgen
还需要 DuckDB 头文件存在。
因此,我们尝试通过提供预生成的 DuckDB 绑定来避免在构建时运行 bindgen
。
如果您使用 bundled
功能,您将获得捆绑版 DuckDB 的预生成绑定。如果您想在构建时运行 bindgen
以生成自己的绑定,请使用 buildtime_bindgen
Cargo 功能。
贡献
清单
- 运行
cargo +nightly fmt
以确保您的 Rust 代码格式正确。 - 运行
cargo clippy --fix --allow-dirty --all-targets --workspace --all-features -- -D warnings
以修复所有 clippy 问题。 - 确保
cargo test --all-targets --workspace --features "modern-full extensions-full"
报告没有失败。
TODOs
- 重构 ErrorCode 部分,它是从 rusqlite 借用的,我们应该有自己的实现
- 支持更多类型
- 更新 duckdb.h
- 调整代码示例和文档
- 删除未使用的代码/函数
- 添加 CI
- 发布到 crate
许可证
DuckDB 和 libduckdb-sys 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。
依赖关系
~14–26MB
~392K SLoC