duckdb-rs is an ergonomic Rust wrapper for DuckDB, with an API inspired by rusqlite. Use it to:
- Query DuckDB with type-safe bindings.
- Read and write Arrow, Parquet, JSON, and CSV formats natively.
- Build DuckDB extensions in Rust with custom scalar and table functions.
The DuckDB Rust client guide is the primary documentation:
- Overview — installation and the full list of Cargo feature flags.
- Connect — configuration, connection pooling, and thread safety.
- Import Data — the Appender and file readers.
- Run Queries — binding parameters and mapping rows to Rust types.
- Handle Results — Apache Arrow and Polars interchange.
- Write User Defined Functions — scalar and table functions, and loadable extensions.
- Profile and Monitor — query profiling and interrupting long-running queries.
- Troubleshoot — linking against a system library and other build issues.
The complete API reference is on docs.rs.
cargo add duckdb -F bundleduse duckdb::{Connection, Result};
fn main() -> Result<()> {
let conn = Connection::open_in_memory()?;
conn.execute_batch(
"CREATE TABLE ducks (id INTEGER, name TEXT);
INSERT INTO ducks VALUES (1, 'Donald Duck'), (2, 'Scrooge McDuck');",
)?;
let mut stmt = conn.prepare("SELECT id, name FROM ducks")?;
for row in stmt.query_map([], |r| Ok((r.get::<_, i32>(0)?, r.get::<_, String>(1)?)))? {
let (id, name) = row?;
println!("{id}) {name}");
}
Ok(())
}See the documentation for everything beyond this.
Runnable examples live in crates/duckdb/examples, covering basic usage, the Appender, Arrow virtual tables, Parquet, scalar and table functions, a REPL, and a loadable extension. Run one with the appropriate features:
cargo run --example basic --features bundled
cargo run --example arrow_vtab --features "bundled vtab-arrow"hello-ext is a library target, so build it rather than running it:
cargo build --example hello-ext --features loadable-extensionThe user-facing build options (bundled, linking against a system library, DUCKDB_DOWNLOAD_LIB, cross-compiling) are documented under Troubleshoot in the guide. The options below apply only when building from a checkout of this repository.
The bundled-cmake feature builds DuckDB from crates/libduckdb-sys/duckdb-sources using DuckDB's upstream CMake build instead of the cc backend. It is required for CMake-only extensions such as icu, and is not available from crates.io because published crates omit the full source tree.
duckdb = { git = "https://github.com/duckdb/duckdb-rs", branch = "main", features = ["bundled-cmake", "icu"] }- It implies
bundledfor conditional-compilation gates and always links DuckDB's default static extensions (core_functionsandparquet), so it also implies theparquetfeature. - It enables upstream jemalloc on supported 64-bit, non-musl Linux targets. Set
DUCKDB_DISABLE_JEMALLOC=1to force the standard allocator. - Extension autoload/autoinstall are enabled to match
bundled. SetDUCKDB_DISABLE_EXTENSION_LOAD=1to turn them off. - DuckDB builds in
Releasemode by default, even for Rust debug builds. Override withDUCKDB_CMAKE_BUILD_TYPE(which takes precedence) orCMAKE_BUILD_TYPE. - If
ninjais onPATH, the build uses it by default; setCMAKE_GENERATORto override.DUCKDB_EXTENSION_CONFIGSis unsupported and fails fast. - Use
cargo build -vv -F bundled-cmakefor CMake configure and build logs.
libduckdb-sys ships pregenerated bindings for DuckDB's C API rather than running bindgen at build time, which keeps build times down and avoids requiring Clang and the DuckDB header on every machine. To regenerate bindings at build time instead, enable the buildtime_bindgen feature.
duckdb-rs is built and tested with stable Rust and keeps a rolling MSRV that trails the current release by at least 6 months. The MSRV may only change when the encoded DuckDB major/minor version changes; patch releases keep the same MSRV.
Contributions are welcome. See CONTRIBUTING.md, and join the #rust channel on our Discord.
Copyright (c) Stichting DuckDB Foundation. Licensed under the MIT license.