Skip to content

Commit

Permalink
bump duckdb, handle errors during initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
samansmink committed Oct 4, 2024
1 parent 0bc3647 commit f333e73
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
name: Download duckdb
with:
repository: "duckdb/duckdb"
tag: "v1.1.0"
tag: "v1.1.1"
fileName: ${{ matrix.duckdb }}
out-file-path: .

Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ members = [
]

[workspace.package]
version = "1.1.0"
version = "1.1.1"
authors = ["wangfenjin <[email protected]>"]
edition = "2021"
repository = "https://github.com/duckdb/duckdb-rs"
Expand All @@ -19,8 +19,8 @@ license = "MIT"
categories = ["database"]

[workspace.dependencies]
duckdb = { version = "1.1.0", path = "crates/duckdb" }
libduckdb-sys = { version = "1.1.0", path = "crates/libduckdb-sys" }
duckdb = { version = "1.1.1", path = "crates/duckdb" }
libduckdb-sys = { version = "1.1.1", path = "crates/libduckdb-sys" }
duckdb-loadable-macros = { version = "0.1.2", path = "crates/duckdb-loadable-macros" }
autocfg = "1.0"
bindgen = { version = "0.69", default-features = false }
Expand Down
45 changes: 35 additions & 10 deletions crates/duckdb-loadable-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,24 +51,49 @@ pub fn duckdb_entrypoint_c_api(attr: TokenStream, item: TokenStream) -> TokenStr
let c_entrypoint = Ident::new(format!("{}_init_c_api", args.ext_name).as_str(), Span::call_site());
let original_funcname = func.sig.ident.to_string();
let prefixed_original_function = func.sig.ident.clone();
let c_entrypoint_internal = Ident::new(format!("{}_init_c_api_internal", args.ext_name).as_str(), Span::call_site());

quote_spanned! {func.span()=>
pub unsafe fn #c_entrypoint_internal(info: ffi::duckdb_extension_info, access: *const ffi::duckdb_extension_access) -> Result<bool, Box<dyn std::error::Error>> {
let have_api_struct = ffi::duckdb_rs_extension_api_init(info, access, #minimum_duckdb_version).unwrap();

if !have_api_struct {
// initialization failed to return an api struct, likely due to an API version mismatch, we can simply return here
return Ok(false);
}

// TODO: handle error here?
let db : ffi::duckdb_database = *(*access).get_database.unwrap()(info);
let connection = Connection::open_from_raw(db.cast())?;

#prefixed_original_function(connection)?;

return Ok(true);
}

/// # Safety
///
/// Will be called by duckdb
/// Entrypoint that will be called by DuckDB
#[no_mangle]
pub unsafe extern "C" fn #c_entrypoint(info: ffi::duckdb_extension_info, access: *const ffi::duckdb_extension_access) {
let res = ffi::duckdb_rs_extension_api_init(info, access, #minimum_duckdb_version);

if let Err(x) = res {
// Error will be handled by DuckDB
return;
pub unsafe extern "C" fn #c_entrypoint(info: ffi::duckdb_extension_info, access: *const ffi::duckdb_extension_access) -> bool {
let init_result = #c_entrypoint_internal(info, access);

if let Err(x) = init_result {
let error_c_string = std::ffi::CString::new(x.description());

match error_c_string {
Ok(e) => {
(*access).set_error.unwrap()(info, e.as_ptr());
},
Err(e) => {
let error_alloc_failure = c"An error occured but the extension failed to allocate memory for an error string";
(*access).set_error.unwrap()(info, error_alloc_failure.as_ptr());
}
}
return false;
}

let db : ffi::duckdb_database = *(*access).get_database.unwrap()(info);
let connection = Connection::open_from_raw(db.cast()).expect("can't open db connection");
#prefixed_original_function(connection).expect("init failed");
return init_result.unwrap();
}

#func
Expand Down
2 changes: 1 addition & 1 deletion crates/duckdb/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "duckdb"
version = "1.1.0"
version = "1.1.1"
authors.workspace = true
edition.workspace = true
repository.workspace = true
Expand Down
3 changes: 2 additions & 1 deletion crates/duckdb/examples/hello-ext-capi/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use duckdb_loadable_macros::duckdb_entrypoint_c_api;
use libduckdb_sys as ffi;
use std::{
error::Error,
ffi::{c_char, c_void, CString},
ffi::{c_char, CString},
};

#[repr(C)]
Expand Down Expand Up @@ -87,6 +87,7 @@ impl VTab for HelloVTab {

#[duckdb_entrypoint_c_api(ext_name = "rusty_quack", min_duckdb_version = "v0.0.1")]
pub unsafe fn ExtensionEntrypoint(con: Connection) -> Result<(), Box<dyn Error>> {
return Err("SHIT THIS THE FAN request".into());
con.register_table_function::<HelloVTab>("hello")
.expect("Failed to register hello table function");
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/duckdb/src/appender/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ mod test {
let mut appender = conn.appender("foo")?;
match appender.append_row(["foo"]) {
Err(crate::Error::DuckDBFailure(.., Some(msg))) => {
assert_eq!(msg, "Call to EndRow before all rows have been appended to!")
assert_eq!(msg, "Call to EndRow before all columns have been appended to!")
}
_ => panic!("expected error"),
}
Expand Down
2 changes: 1 addition & 1 deletion crates/libduckdb-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libduckdb-sys"
version = "1.1.0"
version = "1.1.1"
authors.workspace = true
edition.workspace = true
license.workspace = true
Expand Down
8 changes: 5 additions & 3 deletions crates/libduckdb-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,14 +431,16 @@ mod bindings {
// (3) generate rust code similar to DUCKDB_EXTENSION_API_INIT macro
let tokens = quote::quote! {
/// Like DUCKDB_EXTENSION_API_INIT macro
pub unsafe fn duckdb_rs_extension_api_init(info: duckdb_extension_info, access: *const duckdb_extension_access, version: &str) -> ::std::result::Result<(), &'static str> {
pub unsafe fn duckdb_rs_extension_api_init(info: duckdb_extension_info, access: *const duckdb_extension_access, version: &str) -> ::std::result::Result<bool, &'static str> {
let version_c_string = std::ffi::CString::new(version).unwrap();
let #p_api = (*access).get_api.unwrap()(info, version_c_string.as_ptr()) as *const duckdb_ext_api_v0;
if #p_api.is_null() {
return Err("DuckDB passed a nullpointer while trying to initialize the extension");
// get_api can return a nullptr when the version is not matched. In this case, we don't need to set
// an error, but can instead just stop the initialization process and let duckdb handle things
return Ok(false);
}
#(#stores)*
Ok(())
Ok(true)
}
};
output.push_str(&prettyplease::unparse(
Expand Down
2 changes: 1 addition & 1 deletion crates/libduckdb-sys/duckdb-sources
Submodule duckdb-sources updated 277 files
Binary file modified crates/libduckdb-sys/duckdb.tar.gz
Binary file not shown.
1 change: 1 addition & 0 deletions crates/libduckdb-sys/src/bindgen_bundled_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ pub const DUCKDB_TYPE_DUCKDB_TYPE_TIME_TZ: DUCKDB_TYPE = 30;
pub const DUCKDB_TYPE_DUCKDB_TYPE_TIMESTAMP_TZ: DUCKDB_TYPE = 31;
pub const DUCKDB_TYPE_DUCKDB_TYPE_ANY: DUCKDB_TYPE = 34;
pub const DUCKDB_TYPE_DUCKDB_TYPE_VARINT: DUCKDB_TYPE = 35;
pub const DUCKDB_TYPE_DUCKDB_TYPE_SQLNULL: DUCKDB_TYPE = 36;
#[doc = "! An enum over DuckDB's internal types."]
pub type DUCKDB_TYPE = ::std::os::raw::c_uint;
#[doc = "! An enum over DuckDB's internal types."]
Expand Down
9 changes: 4 additions & 5 deletions crates/libduckdb-sys/src/bindgen_bundled_version_loadable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ pub const DUCKDB_TYPE_DUCKDB_TYPE_TIME_TZ: DUCKDB_TYPE = 30;
pub const DUCKDB_TYPE_DUCKDB_TYPE_TIMESTAMP_TZ: DUCKDB_TYPE = 31;
pub const DUCKDB_TYPE_DUCKDB_TYPE_ANY: DUCKDB_TYPE = 34;
pub const DUCKDB_TYPE_DUCKDB_TYPE_VARINT: DUCKDB_TYPE = 35;
pub const DUCKDB_TYPE_DUCKDB_TYPE_SQLNULL: DUCKDB_TYPE = 36;
#[doc = "! An enum over DuckDB's internal types."]
pub type DUCKDB_TYPE = ::std::os::raw::c_uint;
#[doc = "! An enum over DuckDB's internal types."]
Expand Down Expand Up @@ -14026,14 +14027,12 @@ pub unsafe fn duckdb_rs_extension_api_init(
info: duckdb_extension_info,
access: *const duckdb_extension_access,
version: &str,
) -> ::std::result::Result<(), &'static str> {
) -> ::std::result::Result<bool, &'static str> {
let version_c_string = std::ffi::CString::new(version).unwrap();
let p_api = (*access).get_api.unwrap()(info, version_c_string.as_ptr())
as *const duckdb_ext_api_v0;
if p_api.is_null() {
return Err(
"DuckDB passed a nullpointer while trying to initialize the extension",
);
return Ok(false);
}
if let Some(fun) = (*p_api).duckdb_open {
__DUCKDB_OPEN
Expand Down Expand Up @@ -15519,6 +15518,6 @@ pub unsafe fn duckdb_rs_extension_api_init(
__DUCKDB_STREAM_FETCH_CHUNK
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
}
Ok(())
Ok(true)
}

3 changes: 1 addition & 2 deletions crates/libduckdb-sys/upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ mkdir -p "$SCRIPT_DIR/../../target" "$SCRIPT_DIR/duckdb"
export DUCKDB_LIB_DIR="$SCRIPT_DIR/duckdb"

# Download and extract amalgamation
# todo: fix this version
DUCKDB_VERSION=v1.1.0
DUCKDB_VERSION=v1.1.1
git submodule update --init --checkout
cd "$SCRIPT_DIR/duckdb-sources"
git fetch
Expand Down

0 comments on commit f333e73

Please sign in to comment.