-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial experimental(!) implementation of loadable extensions with C extension API See duckdb/duckdb#12682 for more info on the DuckDB C extension API --------- Co-authored-by: martin <martincharles07@gmail.com>
- Loading branch information
1 parent
f887844
commit 71b01f7
Showing
25 changed files
with
19,839 additions
and
123 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
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
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,4 +1,3 @@ | ||
[submodule "crates/libduckdb-sys/duckdb-sources"] | ||
path = crates/libduckdb-sys/duckdb-sources | ||
url = https://github.com/duckdb/duckdb | ||
update = none |
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
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
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
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
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
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
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,93 @@ | ||
extern crate duckdb; | ||
extern crate duckdb_loadable_macros; | ||
extern crate libduckdb_sys; | ||
|
||
use duckdb::{ | ||
core::{DataChunkHandle, Inserter, LogicalTypeHandle, LogicalTypeId}, | ||
vtab::{BindInfo, Free, FunctionInfo, InitInfo, VTab}, | ||
Connection, Result, | ||
}; | ||
use duckdb_loadable_macros::duckdb_entrypoint_c_api; | ||
use libduckdb_sys as ffi; | ||
use std::{ | ||
error::Error, | ||
ffi::{c_char, CString}, | ||
}; | ||
|
||
#[repr(C)] | ||
struct HelloBindData { | ||
name: *mut c_char, | ||
} | ||
|
||
impl Free for HelloBindData { | ||
fn free(&mut self) { | ||
unsafe { | ||
if self.name.is_null() { | ||
return; | ||
} | ||
drop(CString::from_raw(self.name)); | ||
} | ||
} | ||
} | ||
|
||
#[repr(C)] | ||
struct HelloInitData { | ||
done: bool, | ||
} | ||
|
||
struct HelloVTab; | ||
|
||
impl Free for HelloInitData {} | ||
|
||
impl VTab for HelloVTab { | ||
type InitData = HelloInitData; | ||
type BindData = HelloBindData; | ||
|
||
unsafe fn bind(bind: &BindInfo, data: *mut HelloBindData) -> Result<(), Box<dyn std::error::Error>> { | ||
bind.add_result_column("column0", LogicalTypeHandle::from(LogicalTypeId::Varchar)); | ||
let param = bind.get_parameter(0).to_string(); | ||
unsafe { | ||
(*data).name = CString::new(param).unwrap().into_raw(); | ||
} | ||
Ok(()) | ||
} | ||
|
||
unsafe fn init(_: &InitInfo, data: *mut HelloInitData) -> Result<(), Box<dyn std::error::Error>> { | ||
unsafe { | ||
(*data).done = false; | ||
} | ||
Ok(()) | ||
} | ||
|
||
unsafe fn func(func: &FunctionInfo, output: &mut DataChunkHandle) -> Result<(), Box<dyn std::error::Error>> { | ||
let init_info = func.get_init_data::<HelloInitData>(); | ||
let bind_info = func.get_bind_data::<HelloBindData>(); | ||
|
||
unsafe { | ||
if (*init_info).done { | ||
output.set_len(0); | ||
} else { | ||
(*init_info).done = true; | ||
let vector = output.flat_vector(0); | ||
let name = CString::from_raw((*bind_info).name); | ||
let result = CString::new(format!("Hello {}", name.to_str()?))?; | ||
// Can't consume the CString | ||
(*bind_info).name = CString::into_raw(name); | ||
vector.insert(0, result); | ||
output.set_len(1); | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn parameters() -> Option<Vec<LogicalTypeHandle>> { | ||
Some(vec![LogicalTypeHandle::from(LogicalTypeId::Varchar)]) | ||
} | ||
} | ||
|
||
#[duckdb_entrypoint_c_api(ext_name = "rusty_quack", min_duckdb_version = "v0.0.1")] | ||
pub fn extension_entrypoint(con: Connection) -> Result<(), Box<dyn Error>> { | ||
con.register_table_function::<HelloVTab>("hello") | ||
.expect("Failed to register hello table function"); | ||
Ok(()) | ||
} |
Oops, something went wrong.