• Stars
    star
    474
  • Rank 92,640 (Top 2 %)
  • Language
    Rust
  • License
    MIT License
  • Created over 3 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Ergonomic bindings to duckdb for Rust

duckdb-rs

Downloads Build Status dependency status codecov Latest Version Docs

duckdb-rs is an ergonomic wrapper for using duckdb from Rust. It attempts to expose an interface similar to rusqlite. Actually 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};

// 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 {
        println!("Found person {:?}", person.unwrap());
    }

    // query table by arrow
    let rbs: Vec<RecordBatch> = stmt.query_arrow([])?.collect();
    print_batches(&rbs).unwrap();
    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 bundled feature, libduckdb-sys will use the cc crate to compile DuckDB from source and link against that. This source is embedded in the libduckdb-sys crate 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 your Cargo.toml file:
    [dependencies.duckdb]
    version = "0.1"
    features = ["bundled"]
  • When linking against a DuckDB library already on the system (so not using any of the bundled features), you can set the DUCKDB_LIB_DIR environment variable to point to a directory containing the library. You can also set the DUCKDB_INCLUDE_DIR variable to point to the directory containing duckdb.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=1 environment 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 therefore duckdb) increased dramatically.
  • Running bindgen requires a relatively-recent version of Clang, which many systems do not have installed by default.
  • Running bindgen also 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 +nightly fmt to ensure your Rust code is correctly formatted.
  • Run cargo clippy --fix --allow-dirty --all-targets --workspace --all-features -- -D warnings to fix all clippy issues.
  • Ensure cargo test --all-targets --workspace --features "modern-full extensions-full" reports no failures.

TODOs

  • Refactor the ErrorCode part, it's borrowed from rusqlite, we should have our own
  • Support more type
  • Update duckdb.h
  • Adjust the code examples and documentation
  • Delete unused code / functions
  • Add CI
  • Publish to crate

License

DuckDB and libduckdb-sys are available under the MIT license. See the LICENSE file for more info.

More Repositories

1

duckdb

DuckDB is an analytical in-process SQL database management system
C++
23,715
star
2

pg_duckdb

DuckDB-powered Postgres for high performance apps & analytics.
C++
1,410
star
3

duckdb-wasm

WebAssembly version of DuckDB
C++
1,185
star
4

dbt-duckdb

dbt (http://getdbt.com) adapter for DuckDB (http://duckdb.org)
Python
896
star
5

duckdb_spatial

C
448
star
6

postgres_scanner

C++
209
star
7

sqlite_scanner

DuckDB extension to read and write to SQLite databases
C
196
star
8

duckdb-web

DuckDB website and documentation
JavaScript
167
star
9

duckdb_iceberg

C++
121
star
10

duckdb-r

The duckdb R package
R
112
star
11

extension-template

Template for DuckDB extensions to help you develop, test and deploy a custom extension
Python
112
star
12

duckdb_delta

DuckDB extension for Delta Lake
C++
101
star
13

community-extensions

Shell
97
star
14

duckdb-swift

C++
68
star
15

duckdb_vss

C++
68
star
16

duckdb_mysql

C++
45
star
17

duckdb_azure

Azure extension for DuckDB
C++
43
star
18

duckdb-node

C++
42
star
19

uc_catalog

Proof-of-concept extension combining the delta extension with Unity Catalog
C++
39
star
20

duckdb_aws

C++
37
star
21

arrow

Extension for DuckDB for functions that require the Apache Arrow dependency
C++
33
star
22

duckdb-java

DuckDB JDBC Driver
C++
28
star
23

substrait

C++
23
star
24

duckdb-node-neo

Second iteration on a DuckDB Node.js client
TypeScript
18
star
25

duckdb_httpfs_wasm_experiment

HTTPFS extension for DuckDB. Adds support for an HTTPFileSytem and S3FileSystem.
C++
13
star
26

duckdb-pyodide

HTML
11
star
27

extension-ci-tools

Repository containing reusable workflows / actions for building DuckDB extensions
Makefile
9
star
28

duckdb-odbc

ODBC Driver for DuckDB
C++
5
star
29

duckdb-data

5
star
30

duckdb-wasm-wip

duckdb-wasm test deployment
CSS
4
star
31

duckdb-wasm-ci-env

GitHub Action for DuckDB WASM CI
Dockerfile
3
star
32

duckdb_excel

Excel extension for DuckDB
C++
3
star
33

duckdb_httpfs

C++
2
star
34

duckdb_sqlsmith

DuckDB SQLsmith extension repository
C++
2
star
35

duckdb-fuzzer

Repository that contains automatic reports of issues found through fuzzing DuckDB
1
star
36

duckdb.r-universe.dev

R-universe for the duckdb GitHub organization
1
star
37

duckdb-workflow-trigger

Adding a level of indirection to rule all workflows
1
star
38

duckdb-wasm-extensions-ci

C
1
star
39

extension-template-sql

C++
1
star