duckdb-rs
                                
                                 duckdb-rs copied to clipboard
                                
                                    duckdb-rs copied to clipboard
                            
                            
                            
                        Ergonomic bindings to duckdb for Rust
duckdb-rs
duckdb-rs is an ergonomic wrapper for using duckdb from Rust. It attempts to expose an interface similar to rusqlite. Acctually the initial code and even this README is forked from rusqlite as duckdb also tries to expose a sqlite3 compatible API.
use duckdb::{params, Connection, Result};
use arrow::record_batch::RecordBatch;
use 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 {
        println!("Found person {:?}", person.unwrap());
    }
    // query table by arrow
    let rbs: Vec<RecordBatch> = stmt.query_arrow([])?.collect();
    print_batches(&rbs);
    Ok(())
}
Notes on building duckdb and libduckdb-sys
libduckdb-sys is a separate crate from duckdb-rs that provides the Rust
declarations for DuckDB's C API. By default, libduckdb-sys attempts to find a DuckDB library that already exists on your system using pkg-config, or a
Vcpkg installation for MSVC ABI builds.
You can adjust this behavior in a number of ways:
- If you use the bundledfeature,libduckdb-syswill use the cc crate to compile DuckDB from source and link against that. This source is embedded in thelibduckdb-syscrate and as we are still in development, we will update it regularly. After we are more stable, we will use the stable released version from duckdb. This is probably the simplest solution to any build problems. You can enable this by adding the following in yourCargo.tomlfile:[dependencies.duckdb] version = "0.1" features = ["bundled"]
- When linking against a DuckDB library already on the system (so not using any of the bundledfeatures), you can set theDUCKDB_LIB_DIRenvironment variable to point to a directory containing the library. You can also set theDUCKDB_INCLUDE_DIRvariable to point to the directory containingduckdb.h.
- Installing the duckdb development packages will usually be all that is required, but
the build helpers for pkg-config
and vcpkg have some additional configuration
options. The default when using vcpkg is to dynamically link,
which must be enabled by setting VCPKGRS_DYNAMIC=1environment variable before build.
Binding generation
We use bindgen to generate the Rust
declarations from DuckDB's C header file. bindgen
recommends
running this as part of the build process of libraries that used this. We tried
this briefly (duckdb 0.10.0, specifically), but it had some annoyances:
- The build time for libduckdb-sys(and thereforeduckdb) increased dramatically.
- Running bindgenrequires a relatively-recent version of Clang, which many systems do not have installed by default.
- Running bindgenalso requires the DuckDB header file to be present.
So we try to avoid running bindgen at build-time by shipping
pregenerated bindings for DuckDB.
If you use the bundled features, you will get pregenerated bindings for the
bundled version of DuckDB. If you want to run bindgen at buildtime to
produce your own bindings, use the buildtime_bindgen Cargo feature.
Contributing
See to Contributing.md
Checklist
- Run cargo fmtto ensure your Rust code is correctly formatted.
- Ensure cargo clippy --all-targets --workspace --features bundledpasses without warnings.
- Ensure cargo test --all-targets --workspace --features bundledreports no failures.
TODOs
- [x] Refactor the ErrorCode part, it's borrowed from rusqlite, we should have our own
- [ ] Support more type
- [x] Update duckdb.h
- [x] Adjust the code examples and documentation
- [x] Delete unused code / functions
- [x] Add CI
- [x] Publish to crate
License
DuckDB and libduckdb-sys are available under the MIT license. See the LICENSE file for more info.