mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-25 03:54:21 +01:00
98 lines
3.2 KiB
Rust
98 lines
3.2 KiB
Rust
use crate::{function::ExternalFunc, Database};
|
|
use limbo_ext::{ExtensionApi, InitAggFunction, ResultCode, ScalarFunction};
|
|
pub use limbo_ext::{FinalizeFunction, StepFunction, Value as ExtValue, ValueType as ExtValueType};
|
|
use std::{
|
|
ffi::{c_char, c_void, CStr},
|
|
rc::Rc,
|
|
};
|
|
type ExternAggFunc = (InitAggFunction, StepFunction, FinalizeFunction);
|
|
|
|
unsafe extern "C" fn register_scalar_function(
|
|
ctx: *mut c_void,
|
|
name: *const c_char,
|
|
func: ScalarFunction,
|
|
) -> ResultCode {
|
|
let c_str = unsafe { CStr::from_ptr(name) };
|
|
let name_str = match c_str.to_str() {
|
|
Ok(s) => s.to_string(),
|
|
Err(_) => return ResultCode::InvalidArgs,
|
|
};
|
|
if ctx.is_null() {
|
|
return ResultCode::Error;
|
|
}
|
|
let db = unsafe { &*(ctx as *const Database) };
|
|
db.register_scalar_function_impl(&name_str, func)
|
|
}
|
|
|
|
unsafe extern "C" fn register_aggregate_function(
|
|
ctx: *mut c_void,
|
|
name: *const c_char,
|
|
args: i32,
|
|
init_func: InitAggFunction,
|
|
step_func: StepFunction,
|
|
finalize_func: FinalizeFunction,
|
|
) -> ResultCode {
|
|
let c_str = unsafe { CStr::from_ptr(name) };
|
|
let name_str = match c_str.to_str() {
|
|
Ok(s) => s.to_string(),
|
|
Err(_) => return ResultCode::InvalidArgs,
|
|
};
|
|
if ctx.is_null() {
|
|
return ResultCode::Error;
|
|
}
|
|
let db = unsafe { &*(ctx as *const Database) };
|
|
db.register_aggregate_function_impl(&name_str, args, (init_func, step_func, finalize_func))
|
|
}
|
|
|
|
impl Database {
|
|
fn register_scalar_function_impl(&self, name: &str, func: ScalarFunction) -> ResultCode {
|
|
self.syms.borrow_mut().functions.insert(
|
|
name.to_string(),
|
|
Rc::new(ExternalFunc::new_scalar(name.to_string(), func)),
|
|
);
|
|
ResultCode::OK
|
|
}
|
|
|
|
fn register_aggregate_function_impl(
|
|
&self,
|
|
name: &str,
|
|
args: i32,
|
|
func: ExternAggFunc,
|
|
) -> ResultCode {
|
|
self.syms.borrow_mut().functions.insert(
|
|
name.to_string(),
|
|
Rc::new(ExternalFunc::new_aggregate(name.to_string(), args, func)),
|
|
);
|
|
ResultCode::OK
|
|
}
|
|
|
|
pub fn build_limbo_ext(&self) -> ExtensionApi {
|
|
ExtensionApi {
|
|
ctx: self as *const _ as *mut c_void,
|
|
register_scalar_function,
|
|
register_aggregate_function,
|
|
}
|
|
}
|
|
|
|
pub fn register_builtins(&self) -> Result<(), String> {
|
|
let ext_api = self.build_limbo_ext();
|
|
#[cfg(feature = "uuid")]
|
|
if unsafe { !limbo_uuid::register_extension_static(&ext_api).is_ok() } {
|
|
return Err("Failed to register uuid extension".to_string());
|
|
}
|
|
#[cfg(feature = "vector")]
|
|
if unsafe { !limbo_vector::register_extension_static(&ext_api).is_ok() } {
|
|
return Err("Failed to register vector extension".to_string());
|
|
}
|
|
#[cfg(feature = "percentile")]
|
|
if unsafe { !limbo_percentile::register_extension_static(&ext_api).is_ok() } {
|
|
return Err("Failed to register percentile extension".to_string());
|
|
}
|
|
#[cfg(feature = "regexp")]
|
|
if unsafe { !limbo_regexp::register_extension_static(&ext_api).is_ok() } {
|
|
return Err("Failed to register regexp extension".to_string());
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|