Skip to content

Commit 7848ebb

Browse files
Maxxensamansminkpeaseeakeslingarsdragonfly
authored
[WIP] Upgrade to V1.2.0 (duckdb#427)
* fetch extension name and version from env variable * set error message * fix: Support boolean lists * test: Add boolean list roundtrip test * Fix link formatting in CONTRIBUTING.md * derive Debug for Savepoint * Use ptr::write when writing uninitialized memory * Use smaller unsafe blocks * Rust BindData/InitData can just use Rust types * Use unsafe blocks inside unsafe fns generated by macro This will prevent the macro generating a warning in edition 2024 * Fix unused import * Better safety docs for vtab methods Contrary to the previous docs, the instances passed to these functions are *not* initialized by the caller. Rather, the called function is responsible for writing into uninitialized memory. * Similar safety fixes in vtab tests * Update pola-rs Try to get the fix for pola-rs/polars#19063 in a better way to fix CI * Remove pola-rs workaround * Upgrade arrow-rs to 54 * Fix test to trigger append error * update to 1.2.0 * update polars again * reexport polars-arrow, fix lifetime clippy * upgrade sources, bindgen * remove polars from default * uh update source again? * upgrade bindgen * limit bindgen * allow unsatble/deprecated c api for now * format that shidd * install openssl * ok, update it and if it doesnt work we're getting rid of it * yeet * remove asan for now * adjust timestamp tests for utc * fix logicaltypeid export * format * add logicaltypeid export again --------- Co-authored-by: Sam Ansmink <[email protected]> Co-authored-by: peasee <[email protected]> Co-authored-by: Alex Kesling <[email protected]> Co-authored-by: Zheyu Shen <[email protected]> Co-authored-by: Martin Pool <[email protected]> Co-authored-by: John Allen <[email protected]> Co-authored-by: nm <[email protected]>
1 parent 6030134 commit 7848ebb

25 files changed

+6123
-10765
lines changed

.github/.codecov.yml

-11
This file was deleted.

.github/workflows/rust.yaml

+3-57
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
name: Download duckdb
4040
with:
4141
repository: "duckdb/duckdb"
42-
tag: "v1.1.1"
42+
tag: "v1.2.0"
4343
fileName: ${{ matrix.duckdb }}
4444
out-file-path: .
4545

@@ -54,11 +54,6 @@ jobs:
5454
- run: cargo fmt --all -- --check
5555
if: matrix.os == 'ubuntu-latest'
5656

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-
6257
- name: run cargo clippy
6358
if: matrix.os == 'ubuntu-latest'
6459
env:
@@ -67,24 +62,7 @@ jobs:
6762
LD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb
6863
run: |
6964
cargo clippy --all-targets --workspace --all-features -- -D warnings -A clippy::redundant-closure
70-
71-
72-
- name: Run cargo-tarpaulin
73-
if: matrix.os == 'ubuntu-latest'
74-
uses: actions-rs/[email protected]
75-
with:
76-
# Intentionally omit time feature until we're on time 0.3, at which
77-
# point it should be added to `bundled-full`.
78-
args: '--features "buildtime_bindgen modern-full vtab-full vtab-loadable" --avoid-cfg-tarpaulin' # TODO restore to normal (https://github.com/xd009642/tarpaulin/issues/756#issuecomment-838769320)
79-
version: 0.22.0
80-
env:
81-
DUCKDB_LIB_DIR: ${{ github.workspace }}/libduckdb
82-
DUCKDB_INCLUDE_DIR: ${{ github.workspace }}/libduckdb
83-
LD_LIBRARY_PATH: ${{ github.workspace }}/libduckdb
84-
85-
- name: Upload to codecov.io
86-
if: matrix.os == 'ubuntu-latest'
87-
uses: codecov/codecov-action@v1
65+
8866

8967
# For windows
9068
- name: Windows extract duckdb
@@ -139,36 +117,4 @@ jobs:
139117
rust-version: stable
140118
targets: x86_64-pc-windows-msvc
141119

142-
- run: cargo install cargo-examples
143-
144-
Sanitizer:
145-
name: Address Sanitizer
146-
needs: test
147-
runs-on: ubuntu-latest
148-
steps:
149-
- uses: actions/checkout@v2
150-
# Need nightly rust.
151-
- uses: hecrj/setup-rust-action@v1
152-
with:
153-
rust-version: nightly
154-
components: rust-src
155-
- name: Tests with asan
156-
env:
157-
RUSTFLAGS: -Zsanitizer=address -C debuginfo=0
158-
RUSTDOCFLAGS: -Zsanitizer=address
159-
ASAN_OPTIONS: "detect_stack_use_after_return=1:detect_leaks=1"
160-
# Work around https://github.com/rust-lang/rust/issues/59125 by
161-
# disabling backtraces. In an ideal world we'd probably suppress the
162-
# leak sanitization, but we don't care about backtraces here, so long
163-
# as the other tests have them.
164-
RUST_BACKTRACE: "0"
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
168-
- name: publish crates --dry-run
169-
uses: katyo/publish-crates@v2
170-
with:
171-
path: './'
172-
args: --allow-dirty --all-features
173-
dry-run: true
174-
ignore-unpublished-changes: true
120+
- run: cargo install cargo-examples

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Most user should use `duckdb`, but our development may happen in both of these c
99
## Development
1010

1111
### duckdb-c-api
12-
Some features are still not implemented in the c api, so we may need pull request in the [duckdb repo]((https://github.com/duckdb/duckdb).
12+
Some features are still not implemented in the c api, so we may need pull request in the [duckdb repo](https://github.com/duckdb/duckdb).
1313

1414
```shell
1515
# build duckdb

Cargo.toml

+8-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ members = [
77
]
88

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

2121
[workspace.dependencies]
22-
duckdb = { version = "1.1.1", path = "crates/duckdb" }
23-
libduckdb-sys = { version = "1.1.1", path = "crates/libduckdb-sys" }
22+
duckdb = { version = "1.2.0", path = "crates/duckdb" }
23+
libduckdb-sys = { version = "1.2.0", path = "crates/libduckdb-sys" }
2424
duckdb-loadable-macros = { version = "0.1.3", path = "crates/duckdb-loadable-macros" }
2525
autocfg = "1.0"
26-
bindgen = { version = "0.69", default-features = false }
26+
bindgen = { version = "0.71.1", default-features = false }
2727
byteorder = "1.3"
2828
calamine = "0.22.0"
2929
cast = "0.3"
@@ -40,8 +40,9 @@ memchr = "2.3"
4040
num = { version = "0.4", default-features = false }
4141
num-integer = "0.1.46"
4242
pkg-config = "0.3.24"
43-
polars = "0.35.4"
44-
polars-core = "0.35.4"
43+
polars = "0.46"
44+
polars-core = "0.46"
45+
polars-arrow = "0.46"
4546
pretty_assertions = "1.4.0"
4647
prettyplease = "0.2.20"
4748
proc-macro2 = "1.0.56"
@@ -62,4 +63,4 @@ unicase = "2.6.0"
6263
url = "2.1"
6364
uuid = "1.0"
6465
vcpkg = "0.2"
65-
arrow = { version = "53", default-features = false }
66+
arrow = { version = "54", default-features = false }

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

+18-7
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ use quote::quote_spanned;
88

99
use darling::{ast::NestedMeta, Error, FromMeta};
1010

11+
use std::env;
12+
1113
/// For parsing the arguments to the duckdb_entrypoint_c_api macro
1214
#[derive(Debug, FromMeta)]
1315
struct CEntryPointMacroArgs {
1416
#[darling(default)]
1517
/// The name to be given to this extension. This name is used in the entrypoint function called by duckdb
16-
ext_name: String,
18+
ext_name: Option<String>,
1719
/// The minimum C API version this extension requires. It is recommended to set this to the lowest possible version
1820
/// at which your extension still compiles
1921
min_duckdb_version: Option<String>,
@@ -40,17 +42,22 @@ pub fn duckdb_entrypoint_c_api(attr: TokenStream, item: TokenStream) -> TokenStr
4042
// Set the minimum duckdb version (dev by default)
4143
let minimum_duckdb_version = match args.min_duckdb_version {
4244
Some(i) => i,
43-
None => "dev".to_string(),
45+
None => env::var("DUCKDB_EXTENSION_MIN_DUCKDB_VERSION").expect("Please either set env var DUCKDB_EXTENSION_MIN_DUCKDB_VERSION or pass it as an argument to the proc macro").to_string()
46+
};
47+
48+
let extension_name = match args.ext_name {
49+
Some(i) => i,
50+
None => env::var("DUCKDB_EXTENSION_NAME").expect("Please either set env var DUCKDB_EXTENSION_MIN_DUCKDB_VERSION or pass it as an argument to the proc macro").to_string()
4451
};
4552

4653
let ast = parse_macro_input!(item as syn::Item);
4754

4855
match ast {
4956
Item::Fn(func) => {
50-
let c_entrypoint = Ident::new(format!("{}_init_c_api", args.ext_name).as_str(), Span::call_site());
57+
let c_entrypoint = Ident::new(format!("{}_init_c_api", extension_name).as_str(), Span::call_site());
5158
let prefixed_original_function = func.sig.ident.clone();
5259
let c_entrypoint_internal = Ident::new(
53-
format!("{}_init_c_api_internal", args.ext_name).as_str(),
60+
format!("{}_init_c_api_internal", extension_name).as_str(),
5461
Span::call_site(),
5562
);
5663

@@ -133,16 +140,20 @@ pub fn duckdb_entrypoint(_attr: TokenStream, item: TokenStream) -> TokenStream {
133140
/// Will be called by duckdb
134141
#[no_mangle]
135142
pub unsafe extern "C" fn #c_entrypoint(db: *mut c_void) {
136-
let connection = Connection::open_from_raw(db.cast()).expect("can't open db connection");
137-
#prefixed_original_function(connection).expect("init failed");
143+
unsafe {
144+
let connection = Connection::open_from_raw(db.cast()).expect("can't open db connection");
145+
#prefixed_original_function(connection).expect("init failed");
146+
}
138147
}
139148

140149
/// # Safety
141150
///
142151
/// Predefined function, don't need to change unless you are sure
143152
#[no_mangle]
144153
pub unsafe extern "C" fn #c_entrypoint_version() -> *const c_char {
145-
ffi::duckdb_library_version()
154+
unsafe {
155+
ffi::duckdb_library_version()
156+
}
146157
}
147158

148159

crates/duckdb/Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "duckdb"
3-
version = "1.1.1"
3+
version = "1.2.0"
44
authors.workspace = true
55
edition.workspace = true
66
repository.workspace = true
@@ -31,7 +31,7 @@ vtab-full = ["vtab-excel", "vtab-arrow", "appender-arrow"]
3131
extensions-full = ["json", "parquet", "vtab-full"]
3232
buildtime_bindgen = ["libduckdb-sys/buildtime_bindgen"]
3333
modern-full = ["chrono", "serde_json", "url", "r2d2", "uuid", "polars"]
34-
polars = ["dep:polars"]
34+
polars = ["dep:polars", "dep:polars-arrow"]
3535
# FIXME: These were added to make clippy happy: these features appear unused and should perhaps be removed
3636
column_decltype = []
3737
extra_check = []
@@ -61,6 +61,7 @@ calamine = { workspace = true, optional = true }
6161
num = { workspace = true, features = ["std"], optional = true }
6262
duckdb-loadable-macros = { workspace = true, optional = true }
6363
polars = { workspace = true, features = ["dtype-full"], optional = true }
64+
polars-arrow = { workspace = true, optional = true }
6465
num-integer = { workspace = true }
6566

6667
[dev-dependencies]

crates/duckdb/examples/hello-ext/main.rs

+18-31
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![warn(unsafe_op_in_unsafe_fn)]
2+
13
extern crate duckdb;
24
extern crate duckdb_loadable_macros;
35
extern crate libduckdb_sys;
@@ -12,25 +14,15 @@ use libduckdb_sys as ffi;
1214
use std::{
1315
error::Error,
1416
ffi::{c_char, c_void, CString},
17+
ptr,
1518
};
1619

17-
#[repr(C)]
1820
struct HelloBindData {
19-
name: *mut c_char,
21+
name: String,
2022
}
2123

22-
impl Free for HelloBindData {
23-
fn free(&mut self) {
24-
unsafe {
25-
if self.name.is_null() {
26-
return;
27-
}
28-
drop(CString::from_raw(self.name));
29-
}
30-
}
31-
}
24+
impl Free for HelloBindData {}
3225

33-
#[repr(C)]
3426
struct HelloInitData {
3527
done: bool,
3628
}
@@ -45,37 +37,32 @@ impl VTab for HelloVTab {
4537

4638
unsafe fn bind(bind: &BindInfo, data: *mut HelloBindData) -> Result<(), Box<dyn std::error::Error>> {
4739
bind.add_result_column("column0", LogicalTypeHandle::from(LogicalTypeId::Varchar));
48-
let param = bind.get_parameter(0).to_string();
40+
let name = bind.get_parameter(0).to_string();
4941
unsafe {
50-
(*data).name = CString::new(param).unwrap().into_raw();
42+
ptr::write(data, HelloBindData { name });
5143
}
5244
Ok(())
5345
}
5446

5547
unsafe fn init(_: &InitInfo, data: *mut HelloInitData) -> Result<(), Box<dyn std::error::Error>> {
5648
unsafe {
57-
(*data).done = false;
49+
ptr::write(data, HelloInitData { done: false });
5850
}
5951
Ok(())
6052
}
6153

6254
unsafe fn func(func: &FunctionInfo, output: &mut DataChunkHandle) -> Result<(), Box<dyn std::error::Error>> {
63-
let init_info = func.get_init_data::<HelloInitData>();
64-
let bind_info = func.get_bind_data::<HelloBindData>();
55+
let init_info = unsafe { func.get_init_data::<HelloInitData>().as_mut().unwrap() };
56+
let bind_info = unsafe { func.get_bind_data::<HelloBindData>().as_mut().unwrap() };
6557

66-
unsafe {
67-
if (*init_info).done {
68-
output.set_len(0);
69-
} else {
70-
(*init_info).done = true;
71-
let vector = output.flat_vector(0);
72-
let name = CString::from_raw((*bind_info).name);
73-
let result = CString::new(format!("Hello {}", name.to_str()?))?;
74-
// Can't consume the CString
75-
(*bind_info).name = CString::into_raw(name);
76-
vector.insert(0, result);
77-
output.set_len(1);
78-
}
58+
if init_info.done {
59+
output.set_len(0);
60+
} else {
61+
init_info.done = true;
62+
let vector = output.flat_vector(0);
63+
let result = CString::new(format!("Hello {}", bind_info.name))?;
64+
vector.insert(0, result);
65+
output.set_len(1);
7966
}
8067
Ok(())
8168
}

crates/duckdb/src/appender/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -288,20 +288,23 @@ mod test {
288288

289289
#[test]
290290
fn test_appender_error() -> Result<(), crate::Error> {
291+
use crate::params;
291292
let conn = Connection::open_in_memory()?;
292293
conn.execute(
293294
r"CREATE TABLE foo (
294295
foobar TEXT,
296+
foobar_int INT,
295297
foobar_split TEXT[] AS (split(trim(foobar), ','))
296298
);",
297299
[],
298300
)?;
299301
let mut appender = conn.appender("foo")?;
300-
match appender.append_row(["foo"]) {
302+
match appender.append_row(params!["foo"]) {
301303
Err(crate::Error::DuckDBFailure(.., Some(msg))) => {
302304
assert_eq!(msg, "Call to EndRow before all columns have been appended to!")
303305
}
304-
_ => panic!("expected error"),
306+
Err(err) => panic!("unexpected error: {:?}", err),
307+
Ok(_) => panic!("expected an error but got Ok"),
305308
}
306309
Ok(())
307310
}

crates/duckdb/src/arrow_batch.rs

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub struct Arrow<'stmt> {
99
pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
1010
}
1111

12+
#[allow(clippy::needless_lifetimes)]
1213
impl<'stmt> Arrow<'stmt> {
1314
#[inline]
1415
pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Arrow<'stmt> {
@@ -22,6 +23,7 @@ impl<'stmt> Arrow<'stmt> {
2223
}
2324
}
2425

26+
#[allow(clippy::needless_lifetimes)]
2527
impl<'stmt> Iterator for Arrow<'stmt> {
2628
type Item = RecordBatch;
2729

@@ -32,11 +34,13 @@ impl<'stmt> Iterator for Arrow<'stmt> {
3234

3335
/// A handle for the resulting RecordBatch of a query in streaming
3436
#[must_use = "Arrow stream is lazy and will not fetch data unless consumed"]
37+
#[allow(clippy::needless_lifetimes)]
3538
pub struct ArrowStream<'stmt> {
3639
pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
3740
pub(crate) schema: SchemaRef,
3841
}
3942

43+
#[allow(clippy::needless_lifetimes)]
4044
impl<'stmt> ArrowStream<'stmt> {
4145
#[inline]
4246
pub(crate) fn new(stmt: &'stmt Statement<'stmt>, schema: SchemaRef) -> ArrowStream<'stmt> {
@@ -53,6 +57,7 @@ impl<'stmt> ArrowStream<'stmt> {
5357
}
5458
}
5559

60+
#[allow(clippy::needless_lifetimes)]
5661
impl<'stmt> Iterator for ArrowStream<'stmt> {
5762
type Item = RecordBatch;
5863

0 commit comments

Comments
 (0)