1 //! Automatic extension loading
2 use super::ffi;
3 use crate::error::{check, to_sqlite_error};
4 use crate::{Connection, Error, Result};
5 use std::os::raw::{c_char, c_int};
6 use std::panic::catch_unwind;
7
8 /// Automatic extension initialization routine
9 pub type AutoExtension = fn(Connection) -> Result<()>;
10
11 /// Raw automatic extension initialization routine
12 pub type RawAutoExtension = unsafe extern "C" fn(
13 db: *mut ffi::sqlite3,
14 pz_err_msg: *mut *mut c_char,
15 _: *const ffi::sqlite3_api_routines,
16 ) -> c_int;
17
18 /// Bridge between `RawAutoExtension` and `AutoExtension`
19 ///
20 /// # Safety
21 /// * Opening a database from an auto-extension handler will lead to
22 /// an endless recursion of the auto-handler triggering itself
23 /// indirectly for each newly-opened database.
24 /// * Results are undefined if the given db is closed by an auto-extension.
25 /// * The list of auto-extensions should not be manipulated from an auto-extension.
init_auto_extension( db: *mut ffi::sqlite3, pz_err_msg: *mut *mut c_char, ax: AutoExtension, ) -> c_int26 pub unsafe fn init_auto_extension(
27 db: *mut ffi::sqlite3,
28 pz_err_msg: *mut *mut c_char,
29 ax: AutoExtension,
30 ) -> c_int {
31 let r = catch_unwind(|| {
32 let c = Connection::from_handle(db);
33 c.and_then(ax)
34 })
35 .unwrap_or_else(|_| Err(Error::UnwindingPanic));
36 match r {
37 Err(e) => to_sqlite_error(&e, pz_err_msg),
38 _ => ffi::SQLITE_OK,
39 }
40 }
41
42 /// Register au auto-extension
43 ///
44 /// # Safety
45 /// * Opening a database from an auto-extension handler will lead to
46 /// an endless recursion of the auto-handler triggering itself
47 /// indirectly for each newly-opened database.
48 /// * Results are undefined if the given db is closed by an auto-extension.
49 /// * The list of auto-extensions should not be manipulated from an auto-extension.
register_auto_extension(ax: RawAutoExtension) -> Result<()>50 pub unsafe fn register_auto_extension(ax: RawAutoExtension) -> Result<()> {
51 check(ffi::sqlite3_auto_extension(Some(ax)))
52 }
53
54 /// Unregister the initialization routine
cancel_auto_extension(ax: RawAutoExtension) -> bool55 pub fn cancel_auto_extension(ax: RawAutoExtension) -> bool {
56 unsafe { ffi::sqlite3_cancel_auto_extension(Some(ax)) == 1 }
57 }
58
59 /// Disable all automatic extensions previously registered
reset_auto_extension()60 pub fn reset_auto_extension() {
61 unsafe { ffi::sqlite3_reset_auto_extension() }
62 }
63