mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-23 00:45:37 +01:00
Enable staticly linking with builtin extensions
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1270,6 +1270,8 @@ dependencies = [
|
||||
"libloading",
|
||||
"limbo_ext",
|
||||
"limbo_macros",
|
||||
"limbo_percentile",
|
||||
"limbo_uuid",
|
||||
"log",
|
||||
"miette",
|
||||
"mimalloc",
|
||||
|
||||
@@ -14,15 +14,17 @@ name = "limbo_core"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["fs", "json", "uuid", "io_uring"]
|
||||
default = ["fs", "json", "uuid", "io_uring", "percentile", "static"]
|
||||
fs = []
|
||||
json = [
|
||||
"dep:jsonb",
|
||||
"dep:pest",
|
||||
"dep:pest_derive",
|
||||
]
|
||||
uuid = ["dep:uuid"]
|
||||
uuid = ["dep:uuid", "limbo_uuid"]
|
||||
io_uring = ["dep:io-uring", "rustix/io_uring"]
|
||||
percentile = ["limbo_percentile"]
|
||||
static = ["limbo_uuid/static", "limbo_percentile/static"]
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
io-uring = { version = "0.6.1", optional = true }
|
||||
@@ -33,6 +35,7 @@ rustix = "0.38.34"
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
mimalloc = { version = "*", default-features = false }
|
||||
libloading = "0.8.6"
|
||||
|
||||
[dependencies]
|
||||
limbo_ext = { path = "../extensions/core" }
|
||||
@@ -58,8 +61,9 @@ rand = "0.8.5"
|
||||
bumpalo = { version = "3.16.0", features = ["collections", "boxed"] }
|
||||
limbo_macros = { path = "../macros" }
|
||||
uuid = { version = "1.11.0", features = ["v4", "v7"], optional = true }
|
||||
limbo_uuid = { path = "../extensions/uuid", optional = true, features = ["static"] }
|
||||
limbo_percentile = { path = "../extensions/percentile", optional = true, features = ["static"] }
|
||||
miette = "7.4.0"
|
||||
libloading = "0.8.6"
|
||||
|
||||
[target.'cfg(not(target_family = "windows"))'.dev-dependencies]
|
||||
pprof = { version = "0.14.0", features = ["criterion", "flamegraph"] }
|
||||
|
||||
@@ -73,4 +73,31 @@ impl Database {
|
||||
register_aggregate_function,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_builtins(&self) -> Result<(), String> {
|
||||
#[cfg(feature = "uuid")]
|
||||
self.register_uuid()?;
|
||||
#[cfg(feature = "percentile")]
|
||||
self.register_percentile()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "uuid")]
|
||||
pub fn register_uuid(&self) -> Result<(), String> {
|
||||
let ext_api = Box::new(self.build_limbo_ext());
|
||||
if unsafe { !::limbo_uuid::register_extension_static(&ext_api).is_ok() } {
|
||||
return Err("Failed to register uuid extension".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "percentile")]
|
||||
pub fn register_percentile(&self) -> Result<(), String> {
|
||||
let ext_api = self.build_limbo_ext();
|
||||
let res = unsafe { ::limbo_percentile::register_extension(&ext_api) };
|
||||
if !res.is_ok() {
|
||||
return Err("Failed to register percentile extension".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod error;
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
mod ext;
|
||||
mod function;
|
||||
mod io;
|
||||
@@ -138,6 +139,9 @@ impl Database {
|
||||
_shared_wal: shared_wal.clone(),
|
||||
syms,
|
||||
};
|
||||
if let Err(e) = db.register_builtins() {
|
||||
return Err(LimboError::ExtensionError(e));
|
||||
}
|
||||
let db = Arc::new(db);
|
||||
let conn = Rc::new(Connection {
|
||||
db: db.clone(),
|
||||
|
||||
@@ -7,7 +7,10 @@ license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
|
||||
[features]
|
||||
static = []
|
||||
|
||||
[dependencies]
|
||||
limbo_ext = { path = "../core" }
|
||||
|
||||
@@ -9,8 +9,10 @@ repository.workspace = true
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
|
||||
[features]
|
||||
static= []
|
||||
|
||||
[dependencies]
|
||||
limbo_ext = { path = "../core"}
|
||||
limbo_ext = { path = "../core" }
|
||||
uuid = { version = "1.11.0", features = ["v4", "v7"] }
|
||||
log = "0.4.20"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use limbo_ext::{register_extension, scalar, Value, ValueType};
|
||||
|
||||
#[cfg(feature = "static")]
|
||||
register_extension! {
|
||||
scalars: { uuid4_str, uuid4_blob, uuid7_str, uuid7, uuid7_ts, uuid_str, uuid_blob }
|
||||
static_build: true,
|
||||
scalars: {uuid4_str, uuid4_blob, uuid7_str, uuid7, uuid7_ts, uuid_str, uuid_blob },
|
||||
}
|
||||
|
||||
#[scalar(name = "uuid4_str", alias = "gen_random_uuid")]
|
||||
@@ -133,3 +135,9 @@ fn uuid_to_unix(uuid: &[u8; 16]) -> u64 {
|
||||
| ((uuid[4] as u64) << 8)
|
||||
| (uuid[5] as u64)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "static"))]
|
||||
register_extension! {
|
||||
static_build: false,
|
||||
scalars: { uuid4_str, uuid4_blob, uuid7_str, uuid7, uuid7_ts, uuid_str, uuid_blob }
|
||||
}
|
||||
|
||||
@@ -6,43 +6,56 @@ use syn::{Ident, LitStr, Token};
|
||||
pub(crate) struct RegisterExtensionInput {
|
||||
pub aggregates: Vec<Ident>,
|
||||
pub scalars: Vec<Ident>,
|
||||
pub is_static: bool,
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for RegisterExtensionInput {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut aggregates = Vec::new();
|
||||
let mut scalars = Vec::new();
|
||||
let mut is_static = false;
|
||||
|
||||
while !input.is_empty() {
|
||||
if input.peek(syn::Ident) && input.peek2(Token![:]) {
|
||||
let section_name: Ident = input.parse()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
let content;
|
||||
syn::braced!(content in input);
|
||||
|
||||
if section_name == "aggregates" {
|
||||
aggregates = Punctuated::<Ident, Token![,]>::parse_terminated(&content)?
|
||||
.into_iter()
|
||||
.collect();
|
||||
} else if section_name == "scalars" {
|
||||
scalars = Punctuated::<Ident, Token![,]>::parse_terminated(&content)?
|
||||
if section_name == "static_build" {
|
||||
let val: syn::LitBool = input.parse()?;
|
||||
is_static = val.value;
|
||||
|
||||
if input.peek(Token![,]) {
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
} else if section_name == "aggregates" || section_name == "scalars" {
|
||||
let content;
|
||||
syn::braced!(content in input);
|
||||
|
||||
let parsed_items = Punctuated::<Ident, Token![,]>::parse_terminated(&content)?
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
if section_name == "aggregates" {
|
||||
aggregates = parsed_items;
|
||||
} else {
|
||||
scalars = parsed_items;
|
||||
}
|
||||
|
||||
if input.peek(Token![,]) {
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
} else {
|
||||
return Err(syn::Error::new(section_name.span(), "Unknown section"));
|
||||
}
|
||||
} else {
|
||||
return Err(input.error("Expected aggregates: or scalars: section"));
|
||||
}
|
||||
|
||||
if input.peek(Token![,]) {
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
aggregates,
|
||||
scalars,
|
||||
is_static,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,10 +359,10 @@ pub fn derive_agg_func(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro]
|
||||
pub fn register_extension(input: TokenStream) -> TokenStream {
|
||||
let input_ast = parse_macro_input!(input as RegisterExtensionInput);
|
||||
|
||||
let RegisterExtensionInput {
|
||||
aggregates,
|
||||
scalars,
|
||||
is_static,
|
||||
} = input_ast;
|
||||
|
||||
let scalar_calls = scalars.iter().map(|scalar_ident| {
|
||||
@@ -390,15 +390,28 @@ pub fn register_extension(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
});
|
||||
|
||||
let expanded = quote! {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn register_extension(api: &::limbo_ext::ExtensionApi) -> ::limbo_ext::ResultCode {
|
||||
let expanded = if is_static {
|
||||
quote! {
|
||||
pub unsafe extern "C" fn register_extension_static(api: &::limbo_ext::ExtensionApi) -> ::limbo_ext::ResultCode {
|
||||
let api = unsafe { &*api };
|
||||
#(#scalar_calls)*
|
||||
|
||||
#(#aggregate_calls)*
|
||||
|
||||
::limbo_ext::ResultCode::OK
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn register_extension(api: &::limbo_ext::ExtensionApi) -> ::limbo_ext::ResultCode {
|
||||
let api = unsafe { &*api };
|
||||
#(#scalar_calls)*
|
||||
|
||||
#(#aggregate_calls)*
|
||||
|
||||
::limbo_ext::ResultCode::OK
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user