use std::ffi::CString;
use std::os::raw::c_void;
use libduckdb_sys::{
duckdb_bind_add_result_column, duckdb_bind_get_extra_info, duckdb_bind_get_named_parameter,
duckdb_bind_get_parameter, duckdb_bind_info, duckdb_bind_set_cardinality,
duckdb_bind_set_error, duckdb_function_get_extra_info, duckdb_function_info,
duckdb_function_set_error, duckdb_init_get_extra_info, duckdb_init_info, duckdb_init_set_error,
duckdb_value, idx_t,
};
#[cfg(feature = "duckdb-1-5")]
use libduckdb_sys::{duckdb_client_context, duckdb_table_function_get_client_context};
use crate::types::{LogicalType, TypeId};
use crate::value::Value;
#[mutants::skip] fn str_to_cstring(s: &str) -> CString {
CString::new(s).unwrap_or_else(|_| {
let pos = s.bytes().position(|b| b == 0).unwrap_or(s.len());
CString::new(&s.as_bytes()[..pos]).unwrap_or_default()
})
}
pub struct BindInfo {
info: duckdb_bind_info,
}
impl BindInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_bind_info) -> Self {
Self { info }
}
pub fn add_result_column(&self, name: &str, type_id: TypeId) -> &Self {
let c_name = str_to_cstring(name);
let lt = LogicalType::new(type_id);
unsafe {
duckdb_bind_add_result_column(self.info, c_name.as_ptr(), lt.as_raw());
}
self
}
pub fn add_result_column_with_type(&self, name: &str, logical_type: &LogicalType) -> &Self {
let c_name = str_to_cstring(name);
unsafe {
duckdb_bind_add_result_column(self.info, c_name.as_ptr(), logical_type.as_raw());
}
self
}
pub fn set_cardinality(&self, rows: u64, is_exact: bool) -> &Self {
unsafe {
duckdb_bind_set_cardinality(self.info, rows as idx_t, is_exact);
}
self
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe {
duckdb_bind_set_error(self.info, c_msg.as_ptr());
}
}
#[mutants::skip]
#[must_use]
pub fn parameter_count(&self) -> usize {
usize::try_from(unsafe { libduckdb_sys::duckdb_bind_get_parameter_count(self.info) })
.unwrap_or(0)
}
pub unsafe fn get_parameter(&self, index: u64) -> duckdb_value {
unsafe { duckdb_bind_get_parameter(self.info, index) }
}
pub unsafe fn get_named_parameter(&self, name: &str) -> duckdb_value {
let c_name = str_to_cstring(name);
unsafe { duckdb_bind_get_named_parameter(self.info, c_name.as_ptr()) }
}
pub unsafe fn get_parameter_value(&self, index: u64) -> Value {
let raw = unsafe { duckdb_bind_get_parameter(self.info, index) };
unsafe { Value::from_raw(raw) }
}
pub unsafe fn get_named_parameter_value(&self, name: &str) -> Value {
let c_name = str_to_cstring(name);
let raw = unsafe { duckdb_bind_get_named_parameter(self.info, c_name.as_ptr()) };
unsafe { Value::from_raw(raw) }
}
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_bind_get_extra_info(self.info) }
}
#[cfg(feature = "duckdb-1-5")]
pub unsafe fn get_client_context(&self) -> crate::client_context::ClientContext {
let mut ctx: duckdb_client_context = core::ptr::null_mut();
unsafe { duckdb_table_function_get_client_context(self.info, &raw mut ctx) };
unsafe { crate::client_context::ClientContext::from_raw(ctx) }
}
#[must_use]
#[inline]
pub const fn as_raw(&self) -> duckdb_bind_info {
self.info
}
}
pub struct InitInfo {
info: duckdb_init_info,
}
impl InitInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_init_info) -> Self {
Self { info }
}
#[mutants::skip]
#[must_use]
pub fn projected_column_count(&self) -> usize {
usize::try_from(unsafe { libduckdb_sys::duckdb_init_get_column_count(self.info) })
.unwrap_or(0)
}
#[mutants::skip]
#[must_use]
pub fn projected_column_index(&self, projection_idx: usize) -> usize {
usize::try_from(unsafe {
libduckdb_sys::duckdb_init_get_column_index(self.info, projection_idx as idx_t)
})
.unwrap_or(0)
}
#[mutants::skip]
pub fn set_max_threads(&self, n: u64) {
unsafe { libduckdb_sys::duckdb_init_set_max_threads(self.info, n as idx_t) };
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe { duckdb_init_set_error(self.info, c_msg.as_ptr()) };
}
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_init_get_extra_info(self.info) }
}
#[must_use]
#[inline]
pub const fn as_raw(&self) -> duckdb_init_info {
self.info
}
}
pub struct FunctionInfo {
info: duckdb_function_info,
}
impl FunctionInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_function_info) -> Self {
Self { info }
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe { duckdb_function_set_error(self.info, c_msg.as_ptr()) };
}
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_function_get_extra_info(self.info) }
}
#[must_use]
#[inline]
pub const fn as_raw(&self) -> duckdb_function_info {
self.info
}
}