From 131d89c4ea1939a02725f5aeabb909620084e593 Mon Sep 17 00:00:00 2001 From: Adam Gutglick Date: Thu, 18 Jun 2026 15:04:39 +0100 Subject: [PATCH 1/3] Split vortex-duckdb from the extension Signed-off-by: Adam Gutglick --- Cargo.lock | 7 ++++++ Cargo.toml | 1 + vortex-duckdb-extension/Cargo.toml | 26 ++++++++++++++++++++++ vortex-duckdb-extension/src/lib.rs | 34 +++++++++++++++++++++++++++++ vortex-duckdb/Cargo.toml | 2 +- vortex-duckdb/README.md | 10 +++++++-- vortex-duckdb/include/vortex.h | 6 ----- vortex-duckdb/src/lib.rs | 35 ++++++++---------------------- 8 files changed, 86 insertions(+), 35 deletions(-) create mode 100644 vortex-duckdb-extension/Cargo.toml create mode 100644 vortex-duckdb-extension/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 693082a77f8..93ec0a374df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9719,6 +9719,13 @@ dependencies = [ "zip", ] +[[package]] +name = "vortex-duckdb-extension" +version = "0.1.0" +dependencies = [ + "vortex-duckdb", +] + [[package]] name = "vortex-error" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 8cf6e741a8b..77f0cf29b4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ members = [ "vortex-bench", "vortex-datafusion", "vortex-duckdb", + "vortex-duckdb-extension", "vortex-cuda", "vortex-cuda/cub", "vortex-cuda/ffi", diff --git a/vortex-duckdb-extension/Cargo.toml b/vortex-duckdb-extension/Cargo.toml new file mode 100644 index 00000000000..4f1bac85ead --- /dev/null +++ b/vortex-duckdb-extension/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "vortex-duckdb-extension" +version = { workspace = true } +description = "C-compatible Vortex DuckDB extension artifacts" +homepage = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +license = { workspace = true } +publish = false +keywords = { workspace = true } +include = { workspace = true } +edition = { workspace = true } +rust-version = { workspace = true } +categories = { workspace = true } +readme = { workspace = true } + +[lib] +name = "vortex_duckdb_extension" +path = "src/lib.rs" +crate-type = ["staticlib", "cdylib"] + +[dependencies] +vortex-duckdb = { workspace = true } + +[lints] +workspace = true diff --git a/vortex-duckdb-extension/src/lib.rs b/vortex-duckdb-extension/src/lib.rs new file mode 100644 index 00000000000..a6542f1afbe --- /dev/null +++ b/vortex-duckdb-extension/src/lib.rs @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +#![expect(clippy::missing_safety_doc)] + +use std::ffi::c_char; +use std::ffi::c_void; + +/// Global symbol visibility in the Vortex extension: +/// - Rust functions use C ABI with "_rust" suffix (e.g., vortex_init_rust) +/// - C++ wrapper functions have the expected name without suffix (e.g., vortex_init) +/// - C++ wrappers are annotated with DUCKDB_EXTENSION_API to ensure global visibility +/// - C++ wrappers call the corresponding Rust functions +/// +/// This ensures DuckDB can find the symbols when loading the extension. +/// +/// The DuckDB extension ABI initialization function. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn vortex_init_rust(db: *mut c_void) { + unsafe { vortex_duckdb::initialize_extension_from_raw(db) }; +} + +/// The DuckDB extension ABI version function. +/// This function returns the version of the DuckDB library the extension is built against. +#[unsafe(no_mangle)] +pub extern "C" fn vortex_version_rust() -> *const c_char { + vortex_duckdb::duckdb_library_version() +} + +/// An additional function we export to expose the version of the extension itself to C++ code. +#[unsafe(no_mangle)] +pub extern "C" fn vortex_extension_version_rust() -> *const c_char { + vortex_duckdb::extension_version() +} diff --git a/vortex-duckdb/Cargo.toml b/vortex-duckdb/Cargo.toml index 7dc239a4b1a..b6896910a89 100644 --- a/vortex-duckdb/Cargo.toml +++ b/vortex-duckdb/Cargo.toml @@ -21,7 +21,7 @@ links = "duckdb" [lib] name = "vortex_duckdb" path = "src/lib.rs" -crate-type = ["staticlib", "cdylib", "rlib"] +crate-type = ["rlib"] [dependencies] async-fs = { workspace = true } diff --git a/vortex-duckdb/README.md b/vortex-duckdb/README.md index 9230e2420be..b0082e626fe 100644 --- a/vortex-duckdb/README.md +++ b/vortex-duckdb/README.md @@ -18,12 +18,18 @@ Link against the precompiled DuckDB release build. cargo build -p vortex-duckdb ``` +Build the C-compatible DuckDB extension artifacts with: + +```bash +cargo build -p vortex-duckdb-extension +``` + ### Debug Build Opt into DuckDB debug build: `VX_DUCKDB_DEBUG=1`. ```bash -VX_DUCKDB_DEBUG=1 cargo build -p vortex-duckdb +VX_DUCKDB_DEBUG=1 cargo build -p vortex-duckdb-extension ``` ### AddressSanitizer & ThreadSanitizer @@ -31,7 +37,7 @@ VX_DUCKDB_DEBUG=1 cargo build -p vortex-duckdb Enable both ASAN & TSAN: `VX_DUCKDB_SAN=1`. ```bash -VX_DUCKDB_DEBUG=1 VX_DUCKDB_SAN=1 cargo build -p vortex-duckdb +VX_DUCKDB_DEBUG=1 VX_DUCKDB_SAN=1 cargo build -p vortex-duckdb-extension ``` ## Environment Variables diff --git a/vortex-duckdb/include/vortex.h b/vortex-duckdb/include/vortex.h index 42edf13655c..57339009ba8 100644 --- a/vortex-duckdb/include/vortex.h +++ b/vortex-duckdb/include/vortex.h @@ -15,12 +15,6 @@ extern "C" { #endif // __cplusplus -extern void vortex_init_rust(duckdb_database db); - -extern const char *vortex_version_rust(void); - -extern const char *vortex_extension_version_rust(void); - extern void duckdb_table_function_to_string(void *bind_data, duckdb_vx_string_map map); extern diff --git a/vortex-duckdb/src/lib.rs b/vortex-duckdb/src/lib.rs index b21801b4564..4a4d563e55b 100644 --- a/vortex-duckdb/src/lib.rs +++ b/vortex-duckdb/src/lib.rs @@ -3,8 +3,8 @@ #![expect(clippy::missing_safety_doc)] -use std::ffi::CStr; use std::ffi::c_char; +use std::ffi::c_void; use std::sync::LazyLock; use std::sync::OnceLock; @@ -79,19 +79,10 @@ pub fn initialize(db: &DatabaseRef) -> VortexResult<()> { db.register_copy_function() } -/// Global symbol visibility in the Vortex extension: -/// - Rust functions use C ABI with "_rust" suffix (e.g., vortex_init_rust) -/// - C++ wrapper functions have the expected name without suffix (e.g., vortex_init) -/// - C++ wrappers are annotated with DUCKDB_EXTENSION_API to ensure global visibility -/// - C++ wrappers call the corresponding Rust functions -/// -/// This ensures DuckDB can find the symbols when loading the extension. -/// -/// The DuckDB extension ABI initialization function. -#[unsafe(no_mangle)] -pub unsafe extern "C" fn vortex_init_rust(db: cpp::duckdb_database) { +/// Initialize the DuckDB extension from a raw DuckDB database pointer. +pub unsafe fn initialize_extension_from_raw(db: *mut c_void) { init_tracing(); - let database = unsafe { Database::borrow(db) }; + let database = unsafe { Database::borrow(db.cast()) }; database .register_vortex_scan_replacement() @@ -99,20 +90,12 @@ pub unsafe extern "C" fn vortex_init_rust(db: cpp::duckdb_database) { initialize(database).vortex_expect("Failed to initialize Vortex extension"); } -/// The DuckDB extension ABI version function. -/// This function returns the version of the DuckDB library the extension is built against. -#[unsafe(no_mangle)] -pub extern "C" fn vortex_version_rust() -> *const c_char { +/// Returns the version of the DuckDB library the extension is built against. +pub fn duckdb_library_version() -> *const c_char { unsafe { cpp::duckdb_library_version() } } -/// An additional function we export to expose the version of the extension itself to C++ code. -#[unsafe(no_mangle)] -pub extern "C" fn vortex_extension_version_rust() -> *const c_char { - // We do some fiddly macros here to get ourselves a _static_ C-style string. - // Otherwise, we'd be leaking memory. - unsafe { - CStr::from_bytes_with_nul_unchecked(concat!(env!("CARGO_PKG_VERSION"), "\0").as_bytes()) - } - .as_ptr() +/// Returns the version of the Vortex DuckDB extension. +pub fn extension_version() -> *const c_char { + concat!(env!("CARGO_PKG_VERSION"), "\0").as_ptr().cast() } From aa195e82a0f8e7eb76367e90642d6183b106c608 Mon Sep 17 00:00:00 2001 From: Adam Gutglick Date: Thu, 18 Jun 2026 15:41:00 +0100 Subject: [PATCH 2/3] Remove extension crate Signed-off-by: Adam Gutglick --- Cargo.lock | 7 ------ Cargo.toml | 1 - vortex-duckdb-extension/Cargo.toml | 26 ----------------------- vortex-duckdb-extension/src/lib.rs | 34 ------------------------------ 4 files changed, 68 deletions(-) delete mode 100644 vortex-duckdb-extension/Cargo.toml delete mode 100644 vortex-duckdb-extension/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 93ec0a374df..693082a77f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9719,13 +9719,6 @@ dependencies = [ "zip", ] -[[package]] -name = "vortex-duckdb-extension" -version = "0.1.0" -dependencies = [ - "vortex-duckdb", -] - [[package]] name = "vortex-error" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 77f0cf29b4b..8cf6e741a8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ members = [ "vortex-bench", "vortex-datafusion", "vortex-duckdb", - "vortex-duckdb-extension", "vortex-cuda", "vortex-cuda/cub", "vortex-cuda/ffi", diff --git a/vortex-duckdb-extension/Cargo.toml b/vortex-duckdb-extension/Cargo.toml deleted file mode 100644 index 4f1bac85ead..00000000000 --- a/vortex-duckdb-extension/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "vortex-duckdb-extension" -version = { workspace = true } -description = "C-compatible Vortex DuckDB extension artifacts" -homepage = { workspace = true } -repository = { workspace = true } -authors = { workspace = true } -license = { workspace = true } -publish = false -keywords = { workspace = true } -include = { workspace = true } -edition = { workspace = true } -rust-version = { workspace = true } -categories = { workspace = true } -readme = { workspace = true } - -[lib] -name = "vortex_duckdb_extension" -path = "src/lib.rs" -crate-type = ["staticlib", "cdylib"] - -[dependencies] -vortex-duckdb = { workspace = true } - -[lints] -workspace = true diff --git a/vortex-duckdb-extension/src/lib.rs b/vortex-duckdb-extension/src/lib.rs deleted file mode 100644 index a6542f1afbe..00000000000 --- a/vortex-duckdb-extension/src/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright the Vortex contributors - -#![expect(clippy::missing_safety_doc)] - -use std::ffi::c_char; -use std::ffi::c_void; - -/// Global symbol visibility in the Vortex extension: -/// - Rust functions use C ABI with "_rust" suffix (e.g., vortex_init_rust) -/// - C++ wrapper functions have the expected name without suffix (e.g., vortex_init) -/// - C++ wrappers are annotated with DUCKDB_EXTENSION_API to ensure global visibility -/// - C++ wrappers call the corresponding Rust functions -/// -/// This ensures DuckDB can find the symbols when loading the extension. -/// -/// The DuckDB extension ABI initialization function. -#[unsafe(no_mangle)] -pub unsafe extern "C" fn vortex_init_rust(db: *mut c_void) { - unsafe { vortex_duckdb::initialize_extension_from_raw(db) }; -} - -/// The DuckDB extension ABI version function. -/// This function returns the version of the DuckDB library the extension is built against. -#[unsafe(no_mangle)] -pub extern "C" fn vortex_version_rust() -> *const c_char { - vortex_duckdb::duckdb_library_version() -} - -/// An additional function we export to expose the version of the extension itself to C++ code. -#[unsafe(no_mangle)] -pub extern "C" fn vortex_extension_version_rust() -> *const c_char { - vortex_duckdb::extension_version() -} From 196084dc39feb2d8a2bfa24b127fb51096c68149 Mon Sep 17 00:00:00 2001 From: Adam Gutglick Date: Thu, 18 Jun 2026 16:22:49 +0100 Subject: [PATCH 3/3] restore readme Signed-off-by: Adam Gutglick --- vortex-duckdb/README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/vortex-duckdb/README.md b/vortex-duckdb/README.md index b0082e626fe..9230e2420be 100644 --- a/vortex-duckdb/README.md +++ b/vortex-duckdb/README.md @@ -18,18 +18,12 @@ Link against the precompiled DuckDB release build. cargo build -p vortex-duckdb ``` -Build the C-compatible DuckDB extension artifacts with: - -```bash -cargo build -p vortex-duckdb-extension -``` - ### Debug Build Opt into DuckDB debug build: `VX_DUCKDB_DEBUG=1`. ```bash -VX_DUCKDB_DEBUG=1 cargo build -p vortex-duckdb-extension +VX_DUCKDB_DEBUG=1 cargo build -p vortex-duckdb ``` ### AddressSanitizer & ThreadSanitizer @@ -37,7 +31,7 @@ VX_DUCKDB_DEBUG=1 cargo build -p vortex-duckdb-extension Enable both ASAN & TSAN: `VX_DUCKDB_SAN=1`. ```bash -VX_DUCKDB_DEBUG=1 VX_DUCKDB_SAN=1 cargo build -p vortex-duckdb-extension +VX_DUCKDB_DEBUG=1 VX_DUCKDB_SAN=1 cargo build -p vortex-duckdb ``` ## Environment Variables