1use super::{
2 drop_boxed,
3 ffi::{
4 duckdb_bind_add_result_column, duckdb_bind_get_extra_info, duckdb_bind_get_named_parameter,
5 duckdb_bind_get_parameter, duckdb_bind_get_parameter_count, duckdb_bind_info, duckdb_bind_set_bind_data,
6 duckdb_bind_set_cardinality, duckdb_bind_set_error, duckdb_create_table_function, duckdb_data_chunk,
7 duckdb_delete_callback_t, duckdb_destroy_table_function, duckdb_table_function,
8 duckdb_table_function_add_named_parameter, duckdb_table_function_add_parameter, duckdb_table_function_init_t,
9 duckdb_table_function_set_bind, duckdb_table_function_set_extra_info, duckdb_table_function_set_function,
10 duckdb_table_function_set_init, duckdb_table_function_set_local_init, duckdb_table_function_set_name,
11 duckdb_table_function_supports_projection_pushdown, idx_t,
12 },
13 LogicalTypeHandle, VTab, Value,
14};
15use std::{
16 ffi::{c_void, CString},
17 fmt::Debug,
18 marker::PhantomData,
19 os::raw::c_char,
20};
21
22#[derive(Debug)]
24pub struct BindInfo {
25 ptr: duckdb_bind_info,
26}
27
28impl BindInfo {
29 pub fn add_result_column(&self, column_name: &str, column_type: LogicalTypeHandle) {
35 let c_str = CString::new(column_name).unwrap();
36 unsafe {
37 duckdb_bind_add_result_column(self.ptr, c_str.as_ptr() as *const c_char, column_type.ptr);
38 }
39 }
40
41 pub fn set_error(&self, error: &str) {
46 let c_str = CString::new(error).unwrap();
47 unsafe {
48 duckdb_bind_set_error(self.ptr, c_str.as_ptr() as *const c_char);
49 }
50 }
51 pub unsafe fn set_bind_data(&self, data: *mut c_void, free_function: Option<unsafe extern "C" fn(*mut c_void)>) {
60 duckdb_bind_set_bind_data(self.ptr, data, free_function);
61 }
62
63 pub fn get_parameter_count(&self) -> u64 {
65 unsafe { duckdb_bind_get_parameter_count(self.ptr) }
66 }
67
68 pub fn get_parameter(&self, param_index: u64) -> Value {
78 unsafe {
79 let ptr = duckdb_bind_get_parameter(self.ptr, param_index);
80 if ptr.is_null() {
81 panic!("{param_index} is out of range for function definition");
82 } else {
83 Value::from(ptr)
84 }
85 }
86 }
87
88 pub fn get_named_parameter(&self, name: &str) -> Option<Value> {
95 unsafe {
96 let name = &CString::new(name).unwrap();
97 let ptr = duckdb_bind_get_named_parameter(self.ptr, name.as_ptr());
98 if ptr.is_null() {
99 None
100 } else {
101 Some(Value::from(ptr))
102 }
103 }
104 }
105
106 pub fn set_cardinality(&self, cardinality: idx_t, is_exact: bool) {
112 unsafe { duckdb_bind_set_cardinality(self.ptr, cardinality, is_exact) }
113 }
114 pub fn get_extra_info<T>(&self) -> *const T {
116 unsafe { duckdb_bind_get_extra_info(self.ptr).cast() }
117 }
118}
119
120impl From<duckdb_bind_info> for BindInfo {
121 fn from(ptr: duckdb_bind_info) -> Self {
122 Self { ptr }
123 }
124}
125
126use super::ffi::{
127 duckdb_init_get_bind_data, duckdb_init_get_column_count, duckdb_init_get_column_index, duckdb_init_get_extra_info,
128 duckdb_init_info, duckdb_init_set_error, duckdb_init_set_init_data, duckdb_init_set_max_threads,
129};
130
131#[derive(Debug)]
133pub struct InitInfo(duckdb_init_info);
134
135impl From<duckdb_init_info> for InitInfo {
136 fn from(ptr: duckdb_init_info) -> Self {
137 Self(ptr)
138 }
139}
140
141impl InitInfo {
142 pub unsafe fn set_init_data(&self, data: *mut c_void, freeer: Option<unsafe extern "C" fn(*mut c_void)>) {
144 unsafe {
145 duckdb_init_set_init_data(self.0, data, freeer);
146 }
147 }
148
149 pub fn get_column_indices(&self) -> Vec<idx_t> {
155 let mut indices;
156 unsafe {
157 let column_count = duckdb_init_get_column_count(self.0);
158 indices = Vec::with_capacity(column_count as usize);
159 for i in 0..column_count {
160 indices.push(duckdb_init_get_column_index(self.0, i))
161 }
162 }
163 indices
164 }
165
166 pub fn get_extra_info<T>(&self) -> *const T {
168 unsafe { duckdb_init_get_extra_info(self.0).cast() }
169 }
170
171 pub fn get_bind_data<T>(&self) -> *const T {
179 unsafe { duckdb_init_get_bind_data(self.0).cast() }
180 }
181
182 pub fn set_max_threads(&self, max_threads: idx_t) {
187 unsafe { duckdb_init_set_max_threads(self.0, max_threads) }
188 }
189
190 pub fn set_error(&self, error: &str) {
195 let c_str = CString::new(error).unwrap();
196 unsafe { duckdb_init_set_error(self.0, c_str.as_ptr()) }
197 }
198}
199
200#[derive(Debug)]
202pub struct TableFunction {
203 pub(crate) ptr: duckdb_table_function,
204}
205
206impl Drop for TableFunction {
207 fn drop(&mut self) {
208 unsafe {
209 duckdb_destroy_table_function(&mut self.ptr);
210 }
211 }
212}
213
214impl TableFunction {
215 pub fn supports_pushdown(&self, supports: bool) -> &Self {
224 unsafe {
225 duckdb_table_function_supports_projection_pushdown(self.ptr, supports);
226 }
227 self
228 }
229
230 pub fn add_parameter(&self, logical_type: &LogicalTypeHandle) -> &Self {
235 unsafe {
236 duckdb_table_function_add_parameter(self.ptr, logical_type.ptr);
237 }
238 self
239 }
240
241 pub fn add_named_parameter(&self, name: &str, logical_type: &LogicalTypeHandle) -> &Self {
247 unsafe {
248 let string = CString::new(name).unwrap();
249 duckdb_table_function_add_named_parameter(self.ptr, string.as_ptr(), logical_type.ptr);
250 }
251 self
252 }
253
254 pub fn set_function(
259 &self,
260 func: Option<unsafe extern "C" fn(info: duckdb_function_info, output: duckdb_data_chunk)>,
261 ) -> &Self {
262 unsafe {
263 duckdb_table_function_set_function(self.ptr, func);
264 }
265 self
266 }
267
268 pub fn set_init(&self, init_func: Option<unsafe extern "C" fn(duckdb_init_info)>) -> &Self {
273 unsafe {
274 duckdb_table_function_set_init(self.ptr, init_func);
275 }
276 self
277 }
278
279 pub fn set_bind(&self, bind_func: Option<unsafe extern "C" fn(duckdb_bind_info)>) -> &Self {
284 unsafe {
285 duckdb_table_function_set_bind(self.ptr, bind_func);
286 }
287 self
288 }
289
290 pub fn new() -> Self {
292 Self {
293 ptr: unsafe { duckdb_create_table_function() },
294 }
295 }
296
297 pub fn set_name(&self, name: &str) -> &Self {
302 unsafe {
303 let string = CString::from_vec_unchecked(name.as_bytes().into());
304 duckdb_table_function_set_name(self.ptr, string.as_ptr());
305 }
306 self
307 }
308
309 pub unsafe fn set_extra_info_raw(&self, extra_info: *mut c_void, destroy: duckdb_delete_callback_t) {
321 duckdb_table_function_set_extra_info(self.ptr, extra_info, destroy);
322 }
323
324 pub fn set_extra_info<T>(&self, info: T) -> &Self
329 where
330 T: Send + Sync + 'static,
331 {
332 unsafe {
333 let boxed = Box::new(info);
334 let ptr = Box::into_raw(boxed) as *mut c_void;
335 self.set_extra_info_raw(ptr, Some(drop_boxed::<T>));
336 }
337 self
338 }
339
340 pub fn set_local_init(&self, init: duckdb_table_function_init_t) {
345 unsafe { duckdb_table_function_set_local_init(self.ptr, init) };
346 }
347}
348
349impl Default for TableFunction {
350 fn default() -> Self {
351 Self::new()
352 }
353}
354
355use super::ffi::{
356 duckdb_function_get_bind_data, duckdb_function_get_extra_info, duckdb_function_get_init_data,
357 duckdb_function_get_local_init_data, duckdb_function_info, duckdb_function_set_error,
358};
359
360#[derive(Debug)]
362pub struct TableFunctionInfo<V: VTab> {
363 ptr: duckdb_function_info,
364 _vtab: PhantomData<V>,
365}
366
367impl<V: VTab> TableFunctionInfo<V> {
368 pub fn set_error(&self, error: &str) {
373 let c_str = CString::new(error).unwrap();
374 unsafe {
375 duckdb_function_set_error(self.ptr, c_str.as_ptr());
376 }
377 }
378
379 pub fn get_bind_data(&self) -> &V::BindData {
384 unsafe {
385 let bind_data: *const V::BindData = duckdb_function_get_bind_data(self.ptr).cast();
386 bind_data.as_ref().unwrap()
387 }
388 }
389
390 pub fn get_init_data(&self) -> &V::InitData {
398 unsafe {
400 let init_data: *const V::InitData = duckdb_function_get_init_data(self.ptr).cast();
401 init_data.as_ref().unwrap()
402 }
403 }
404
405 pub fn get_extra_info<T>(&self) -> *mut T {
407 unsafe { duckdb_function_get_extra_info(self.ptr).cast() }
408 }
409
410 pub fn get_local_init_data<T>(&self) -> *mut T {
415 unsafe { duckdb_function_get_local_init_data(self.ptr).cast() }
416 }
417}
418
419impl<V: VTab> From<duckdb_function_info> for TableFunctionInfo<V> {
420 fn from(ptr: duckdb_function_info) -> Self {
421 Self {
422 ptr,
423 _vtab: PhantomData,
424 }
425 }
426}