-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change-Id: I24fe97e063d00ec99de2d95033560b581b212b6f
- Loading branch information
1 parent
37c1e15
commit 8aef6a3
Showing
3 changed files
with
245 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
ignore: | ||
- "libsduckdb-sys/duckdb" | ||
coverage: | ||
status: | ||
project: | ||
default: | ||
informational: true | ||
patch: | ||
default: | ||
informational: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,116 @@ | ||
name: Rust build | ||
|
||
on: push | ||
name: CI | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
branches: | ||
- master | ||
env: | ||
CARGO_TERM_COLOR: always | ||
|
||
RUST_BACKTRACE: 1 | ||
jobs: | ||
build: | ||
test: | ||
name: Test ${{ matrix.target }} | ||
|
||
strategy: | ||
fail-fast: true | ||
|
||
matrix: | ||
include: | ||
#- { target: x86_64-pc-windows-msvc, os: windows-latest } | ||
- { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } | ||
#- { target: x86_64-apple-darwin, os: macos-latest } | ||
#- { | ||
#target: x86_64-pc-windows-gnu, | ||
#os: windows-latest, | ||
#host: -x86_64-pc-windows-gnu, | ||
#} | ||
|
||
runs-on: ${{ matrix.os }} | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
# This has a matcher for test panics, so we use it even though elsewhere | ||
# we use actions-rs/toolchain. | ||
- uses: hecrj/setup-rust-action@v1 | ||
with: | ||
rust-version: stable${{ matrix.host }} | ||
targets: ${{ matrix.target }} | ||
|
||
# - run: cargo build --features bundled --workspace --all-targets --verbose | ||
- run: cargo test --features bundled --workspace --all-targets --verbose | ||
# - run: cargo test --features bundled --workspace --doc --verbose | ||
|
||
sanitizer: | ||
name: Address Sanitizer | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
# Need nightly rust. | ||
- uses: hecrj/setup-rust-action@v1 | ||
with: | ||
rust-version: nightly | ||
components: rust-src | ||
- name: Tests with asan | ||
env: | ||
RUSTFLAGS: -Zsanitizer=address | ||
RUSTDOCFLAGS: -Zsanitizer=address | ||
ASAN_OPTIONS: "detect_stack_use_after_return=1:detect_leaks=0" | ||
# Work around https://github.com/rust-lang/rust/issues/59125 by | ||
# disabling backtraces. In an ideal world we'd probably suppress the | ||
# leak sanitization, but we don't care about backtraces here, so long | ||
# as the other tests have them. | ||
RUST_BACKTRACE: "0" | ||
run: cargo -Z build-std test --features 'bundled' --target x86_64-unknown-linux-gnu | ||
|
||
# Ensure clippy doesn't complain. | ||
clippy: | ||
name: Clippy | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Install latest nightly | ||
uses: actions-rs/toolchain@v1 | ||
with: | ||
toolchain: nightly | ||
override: true | ||
components: rustfmt, clippy | ||
- name: Cache .cargo | ||
id: cache-cargo | ||
uses: actions/cache@v2 | ||
with: | ||
path: ~/.cargo | ||
key: ${{ runner.os }}-${{ hashFiles('Cargo**') }} | ||
- name: cargo test | ||
uses: actions-rs/cargo@v1 | ||
with: | ||
command: test | ||
- uses: actions-rs/clippy-check@v1 | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
args: --all-features | ||
- uses: actions/checkout@v2 | ||
- uses: hecrj/setup-rust-action@v1 | ||
with: | ||
components: clippy | ||
- run: cargo clippy --all-targets --workspace --features bundled -- -D warnings | ||
|
||
# Ensure patch is formatted. | ||
fmt: | ||
name: Format | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: hecrj/setup-rust-action@v1 | ||
with: | ||
components: rustfmt | ||
- run: cargo fmt --all -- --check | ||
|
||
# Detect cases where documentation links don't resolve and such. | ||
# doc: | ||
# name: Docs | ||
# runs-on: ubuntu-latest | ||
# steps: | ||
# - uses: actions/checkout@v2 | ||
# - uses: hecrj/setup-rust-action@v1 | ||
# with: | ||
# rust-version: nightly | ||
# # Need to use `cargo rustdoc` to actually get it to respect -D | ||
# # warnings... Note: this also requires nightly. | ||
# - run: cargo rustdoc --features 'bundled' -- -D warnings | ||
|
||
codecov: | ||
name: Generate code coverage | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: hecrj/setup-rust-action@v1 | ||
- name: Run cargo-tarpaulin | ||
uses: actions-rs/[email protected] | ||
with: | ||
# Intentionally omit time feature until we're on time 0.3, at which | ||
# point it should be added to `bundled-full`. | ||
args: '--features "bundled"' | ||
|
||
- name: Upload to codecov.io | ||
uses: codecov/codecov-action@v1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,133 @@ | ||
# duckdb-rs (WIP) | ||
Ergonomic bindings to duckdb for Rust | ||
# duckdb-rs | ||
|
||
# TODO | ||
[![Build Status](https://github.com/wangfenjin/duckdb-rs/workflows/CI/badge.svg)](https://github.com/wangfenjin/duckdb-rs/actions) | ||
[![dependency status](https://deps.rs/repo/github/wangfenjin/duckdb-rs/status.svg)](https://deps.rs/repo/github/wangfenjin/duckdb-rs) | ||
[comment]: <> ([![Latest Version](https://img.shields.io/crates/v/duckdb.svg)](https://crates.io/crates/duckdb)) | ||
[comment]: <> ([![Docs](https://docs.rs/rusqlite/badge.svg)](https://docs.rs/rusqlite)) | ||
[![codecov](https://codecov.io/gh/wangfenjin/duckdb-rs/branch/master/graph/badge.svg)](https://codecov.io/gh/wangfenjin/duckdb-rs) | ||
|
||
duckdb-rs is an ergonomic wrapper for using [duckdb](https://github.com/duckdb/duckdb) from Rust. It attempts to expose | ||
an interface similar to [rusqlite](https://github.com/rusqlite/rusqlite). Acctually the initial code and even this README is | ||
forked from rusqlite as duckdb also tries to expose a sqlite3 compatible API. | ||
|
||
```rust | ||
use duckdb::{params, 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_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], | ||
)?; | ||
|
||
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(()) | ||
} | ||
``` | ||
|
||
## Notes on building rusqlite 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](https://github.com/Microsoft/vcpkg) installation for MSVC ABI builds. | ||
|
||
You can adjust this behavior in a number of ways: | ||
|
||
* If you use the `bundled` feature, `libsqlite3-sys` will use the | ||
[cc](https://crates.io/crates/cc) crate to compile DuckDB from source and | ||
link against that. This source is embedded in the `libsqlite3-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](https://github.com/duckdb/duckdb/releases). | ||
This is probably the simplest solution to any build problems. You can enable this by adding the following in your `Cargo.toml` file: | ||
```toml | ||
[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](https://github.com/alexcrichton/pkg-config-rs) | ||
and [vcpkg](https://github.com/mcgoo/vcpkg-rs) 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](https://crates.io/crates/bindgen) to generate the Rust | ||
declarations from DuckDB's C header file. `bindgen` | ||
[recommends](https://github.com/servo/rust-bindgen#library-usage-with-buildrs) | ||
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 | ||
|
||
If running bindgen is problematic for you, `--features bundled` enables | ||
bundled and all features which don't require binding generation, and can be used | ||
instead. | ||
|
||
### Checklist | ||
|
||
- Run `cargo fmt` to ensure your Rust code is correctly formatted. | ||
- Ensure `cargo clippy --all-targets --workspace --features bundled` passes without warnings. | ||
- Ensure `cargo test --all-targets --workspace --features bundled` reports no failures. | ||
|
||
### TODOs | ||
|
||
- [x] Refactor the ErrorCode part, it's borrowed from rusqlite, we should have our own | ||
- [ ] Support more type | ||
- [ ] Update duckdb.h | ||
- [x] Update duckdb.h | ||
- [ ] Adjust the code examples and documentation | ||
- [x] Delete unused code / functions | ||
- [x] Add CI | ||
- [ ] Publish to crate | ||
|
||
## License | ||
|
||
DuckDB and libduckdb-sys are available under the MIT license. See the LICENSE file for more info. |