Skip to content

Commit caa2842

Browse files
authored
Merge branch 'main' into enable-union-test
2 parents 6693513 + 2bd811e commit caa2842

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+20424
-365
lines changed

.github/workflows/rust.yaml

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ jobs:
3333
rust-version: stable${{ matrix.host }}
3434
targets: ${{ matrix.target }}
3535
components: 'rustfmt, clippy'
36+
3637
# download libduckdb
3738
- uses: robinraju/[email protected]
3839
name: Download duckdb
3940
with:
4041
repository: "duckdb/duckdb"
41-
tag: "v1.0.0"
42+
tag: "v1.1.1"
4243
fileName: ${{ matrix.duckdb }}
4344
out-file-path: .
4445

@@ -49,15 +50,25 @@ jobs:
4950
with:
5051
file_path: ${{ github.workspace }}/${{ matrix.duckdb }}
5152
extract_dir: libduckdb
53+
5254
- run: cargo fmt --all -- --check
5355
if: matrix.os == 'ubuntu-latest'
54-
- run: cargo clippy --all-targets --workspace --all-features -- -D warnings -A clippy::redundant-closure
56+
57+
# TODO: remove
58+
- name: Workaround for https://github.com/pola-rs/polars/issues/19063
59+
run: |
60+
cargo update [email protected] --precise 2.5.0
61+
62+
- name: run cargo clippy
5563
if: matrix.os == 'ubuntu-latest'
56-
name: run cargo clippy
5764
env:
5865
DUCKDB_LIB_DIR: ${{ github.workspace }}/libduckdb
5966
DUCKDB_INCLUDE_DIR: ${{ github.workspace }}/libduckdb
6067
LD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb
68+
run: |
69+
cargo clippy --all-targets --workspace --all-features -- -D warnings -A clippy::redundant-closure
70+
71+
6172
- name: Run cargo-tarpaulin
6273
if: matrix.os == 'ubuntu-latest'
6374
uses: actions-rs/[email protected]
@@ -70,6 +81,7 @@ jobs:
7081
DUCKDB_LIB_DIR: ${{ github.workspace }}/libduckdb
7182
DUCKDB_INCLUDE_DIR: ${{ github.workspace }}/libduckdb
7283
LD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb
84+
7385
- name: Upload to codecov.io
7486
if: matrix.os == 'ubuntu-latest'
7587
uses: codecov/codecov-action@v1
@@ -88,19 +100,28 @@ jobs:
88100
with:
89101
name: PATH
90102
value: $env:PATH;${{ github.workspace }}/libduckdb
103+
91104
- name: Run cargo-test
92105
if: matrix.os == 'windows-latest'
93106
run: cargo test --features "modern-full vtab-full vtab-loadable"
94107
env:
95108
DUCKDB_LIB_DIR: ${{ github.workspace }}/libduckdb
96109
DUCKDB_INCLUDE_DIR: ${{ github.workspace }}/libduckdb
110+
97111
- name: Build loadable extension
98112
run: cargo build --example hello-ext --features="vtab-loadable"
99113
env:
100114
DUCKDB_LIB_DIR: ${{ github.workspace }}/libduckdb
101115
DUCKDB_INCLUDE_DIR: ${{ github.workspace }}/libduckdb
102116
LD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb
103117

118+
- name: Build loadable extension
119+
run: cargo build --example hello-ext-capi --features="vtab-loadable loadable-extension"
120+
env:
121+
DUCKDB_LIB_DIR: ${{ github.workspace }}/libduckdb
122+
DUCKDB_INCLUDE_DIR: ${{ github.workspace }}/libduckdb
123+
LD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb
124+
104125
Windows:
105126
name: Windows build from source
106127
needs: test
@@ -117,6 +138,7 @@ jobs:
117138
with:
118139
rust-version: stable
119140
targets: x86_64-pc-windows-msvc
141+
120142
- run: cargo install cargo-examples
121143

122144
Sanitizer:
@@ -140,7 +162,9 @@ jobs:
140162
# leak sanitization, but we don't care about backtraces here, so long
141163
# as the other tests have them.
142164
RUST_BACKTRACE: "0"
143-
run: cargo -Z build-std test --features "modern-full extensions-full" --target x86_64-unknown-linux-gnu
165+
run: |
166+
# TODO switch back to modern-full once polars is fixed
167+
cargo -Z build-std test --features "chrono serde_json url r2d2 uuid extensions-full" --target x86_64-unknown-linux-gnu --package duckdb
144168
- name: publish crates --dry-run
145169
uses: katyo/publish-crates@v2
146170
with:

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ Cargo.lock
2727

2828
*.db
2929

30-
crates/libduckdb-sys/duckdb-sources/
30+
crates/libduckdb-sys/duckdb-sources/*
3131
crates/libduckdb-sys/duckdb/
3232
crates/libduckdb-sys/._duckdb

.gitmodules

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
[submodule "crates/libduckdb-sys/duckdb-sources"]
22
path = crates/libduckdb-sys/duckdb-sources
33
url = https://github.com/duckdb/duckdb
4-
update = none

Cargo.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ members = [
77
]
88

99
[workspace.package]
10-
version = "1.0.0"
10+
version = "1.1.1"
1111
authors = ["wangfenjin <[email protected]>"]
1212
edition = "2021"
1313
repository = "https://github.com/duckdb/duckdb-rs"
@@ -19,9 +19,9 @@ license = "MIT"
1919
categories = ["database"]
2020

2121
[workspace.dependencies]
22-
duckdb = { version = "1.0.0", path = "crates/duckdb" }
23-
libduckdb-sys = { version = "1.0.0", path = "crates/libduckdb-sys" }
24-
duckdb-loadable-macros = { version = "0.1.2", path = "crates/duckdb-loadable-macros" }
22+
duckdb = { version = "1.1.1", path = "crates/duckdb" }
23+
libduckdb-sys = { version = "1.1.1", path = "crates/libduckdb-sys" }
24+
duckdb-loadable-macros = { version = "0.1.3", path = "crates/duckdb-loadable-macros" }
2525
autocfg = "1.0"
2626
bindgen = { version = "0.69", default-features = false }
2727
byteorder = "1.3"
@@ -34,14 +34,16 @@ doc-comment = "0.3"
3434
fallible-iterator = "0.3"
3535
fallible-streaming-iterator = "0.1"
3636
flate2 = "1.0"
37-
hashlink = "0.8"
37+
hashlink = "0.9"
3838
lazy_static = "1.4"
3939
memchr = "2.3"
4040
num = { version = "0.4", default-features = false }
41+
num-integer = "0.1.46"
4142
pkg-config = "0.3.24"
4243
polars = "0.35.4"
4344
polars-core = "0.35.4"
4445
pretty_assertions = "1.4.0"
46+
prettyplease = "0.2.20"
4547
proc-macro2 = "1.0.56"
4648
quote = "1.0.21"
4749
r2d2 = "0.8.9"
@@ -60,4 +62,4 @@ unicase = "2.6.0"
6062
url = "2.1"
6163
uuid = "1.0"
6264
vcpkg = "0.2"
63-
arrow = { version = "52", default-features = false }
65+
arrow = { version = "53", default-features = false }

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ all:
1111
cargo clippy --all-targets --workspace --features buildtime_bindgen --features modern-full -- -D warnings -A clippy::redundant-closure
1212

1313
test:
14-
cargo test --features bundled --features modern-full -- --nocapture
14+
cargo test --features bundled --features modern-full -- --nocapture

add_rustfmt_hook.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ command -v rustfmt >/dev/null 2>&1 || { echo >&2 "Rustfmt is required but it's n
88
# write a whole script to pre-commit hook
99
# NOTE: it will overwrite pre-commit file!
1010
cat > .git/hooks/pre-commit <<'EOF'
11-
#!/bin/bash -e
11+
#!/bin/bash
1212
declare -a rust_files=()
1313
files=$(git diff-index --name-only --cached HEAD)
1414
echo 'Formatting source files'

crates/duckdb-loadable-macros/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "duckdb-loadable-macros"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
authors.workspace = true
55
edition.workspace = true
66
license.workspace = true
@@ -14,6 +14,7 @@ description = "Native bindings to the libduckdb library, C API; build loadable e
1414
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1515

1616
[dependencies]
17+
darling = "0.20.10"
1718
proc-macro2 = { workspace = true }
1819
quote = { workspace = true }
1920
syn = { workspace = true, features = ["extra-traits", "full", "fold", "parsing"] }

crates/duckdb-loadable-macros/src/lib.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,108 @@ use syn::{parse_macro_input, spanned::Spanned, Item};
66
use proc_macro::TokenStream;
77
use quote::quote_spanned;
88

9+
use darling::{ast::NestedMeta, Error, FromMeta};
10+
11+
/// For parsing the arguments to the duckdb_entrypoint_c_api macro
12+
#[derive(Debug, FromMeta)]
13+
struct CEntryPointMacroArgs {
14+
#[darling(default)]
15+
/// The name to be given to this extension. This name is used in the entrypoint function called by duckdb
16+
ext_name: String,
17+
/// The minimum C API version this extension requires. It is recommended to set this to the lowest possible version
18+
/// at which your extension still compiles
19+
min_duckdb_version: Option<String>,
20+
}
21+
22+
/// Wraps an entrypoint function to expose an unsafe extern "C" function of the same name.
23+
/// Warning: experimental!
24+
#[proc_macro_attribute]
25+
pub fn duckdb_entrypoint_c_api(attr: TokenStream, item: TokenStream) -> TokenStream {
26+
let attr_args = match NestedMeta::parse_meta_list(attr.into()) {
27+
Ok(v) => v,
28+
Err(e) => {
29+
return TokenStream::from(Error::from(e).write_errors());
30+
}
31+
};
32+
33+
let args = match CEntryPointMacroArgs::from_list(&attr_args) {
34+
Ok(v) => v,
35+
Err(e) => {
36+
return TokenStream::from(e.write_errors());
37+
}
38+
};
39+
40+
// Set the minimum duckdb version (dev by default)
41+
let minimum_duckdb_version = match args.min_duckdb_version {
42+
Some(i) => i,
43+
None => "dev".to_string(),
44+
};
45+
46+
let ast = parse_macro_input!(item as syn::Item);
47+
48+
match ast {
49+
Item::Fn(func) => {
50+
let c_entrypoint = Ident::new(format!("{}_init_c_api", args.ext_name).as_str(), Span::call_site());
51+
let prefixed_original_function = func.sig.ident.clone();
52+
let c_entrypoint_internal = Ident::new(
53+
format!("{}_init_c_api_internal", args.ext_name).as_str(),
54+
Span::call_site(),
55+
);
56+
57+
quote_spanned! {func.span()=>
58+
/// # Safety
59+
///
60+
/// Internal Entrypoint for error handling
61+
pub unsafe fn #c_entrypoint_internal(info: ffi::duckdb_extension_info, access: *const ffi::duckdb_extension_access) -> Result<bool, Box<dyn std::error::Error>> {
62+
let have_api_struct = ffi::duckdb_rs_extension_api_init(info, access, #minimum_duckdb_version).unwrap();
63+
64+
if !have_api_struct {
65+
// initialization failed to return an api struct, likely due to an API version mismatch, we can simply return here
66+
return Ok(false);
67+
}
68+
69+
// TODO: handle error here?
70+
let db : ffi::duckdb_database = *(*access).get_database.unwrap()(info);
71+
let connection = Connection::open_from_raw(db.cast())?;
72+
73+
#prefixed_original_function(connection)?;
74+
75+
Ok(true)
76+
}
77+
78+
/// # Safety
79+
///
80+
/// Entrypoint that will be called by DuckDB
81+
#[no_mangle]
82+
pub unsafe extern "C" fn #c_entrypoint(info: ffi::duckdb_extension_info, access: *const ffi::duckdb_extension_access) -> bool {
83+
let init_result = #c_entrypoint_internal(info, access);
84+
85+
if let Err(x) = init_result {
86+
let error_c_string = std::ffi::CString::new(x.to_string());
87+
88+
match error_c_string {
89+
Ok(e) => {
90+
(*access).set_error.unwrap()(info, e.as_ptr());
91+
},
92+
Err(_e) => {
93+
let error_alloc_failure = c"An error occured but the extension failed to allocate memory for an error string";
94+
(*access).set_error.unwrap()(info, error_alloc_failure.as_ptr());
95+
}
96+
}
97+
return false;
98+
}
99+
100+
init_result.unwrap()
101+
}
102+
103+
#func
104+
}
105+
.into()
106+
}
107+
_ => panic!("Only function items are allowed on duckdb_entrypoint"),
108+
}
109+
}
110+
9111
/// Wraps an entrypoint function to expose an unsafe extern "C" function of the same name.
10112
#[proc_macro_attribute]
11113
pub fn duckdb_entrypoint(_attr: TokenStream, item: TokenStream) -> TokenStream {

crates/duckdb/Cargo.toml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "duckdb"
3-
version = "1.0.0"
3+
version = "1.1.1"
44
authors.workspace = true
55
edition.workspace = true
66
repository.workspace = true
@@ -32,6 +32,11 @@ extensions-full = ["json", "parquet", "vtab-full"]
3232
buildtime_bindgen = ["libduckdb-sys/buildtime_bindgen"]
3333
modern-full = ["chrono", "serde_json", "url", "r2d2", "uuid", "polars"]
3434
polars = ["dep:polars"]
35+
# FIXME: These were added to make clippy happy: these features appear unused and should perhaps be removed
36+
column_decltype = []
37+
extra_check = []
38+
# Warning: experimental feature
39+
loadable-extension = ["libduckdb-sys/loadable-extension"]
3540

3641
[dependencies]
3742
libduckdb-sys = { workspace = true }
@@ -56,7 +61,7 @@ calamine = { workspace = true, optional = true }
5661
num = { workspace = true, features = ["std"], optional = true }
5762
duckdb-loadable-macros = { workspace = true, optional = true }
5863
polars = { workspace = true, features = ["dtype-full"], optional = true }
59-
num-integer = {version = "0.1.46"}
64+
num-integer = { workspace = true }
6065

6166
[dev-dependencies]
6267
doc-comment = { workspace = true }
@@ -90,3 +95,8 @@ all-features = false
9095
name = "hello-ext"
9196
crate-type = ["cdylib"]
9297
required-features = ["vtab-loadable"]
98+
99+
[[example]]
100+
name = "hello-ext-capi"
101+
crate-type = ["cdylib"]
102+
required-features = ["vtab-loadable", "loadable-extension"]

0 commit comments

Comments
 (0)