Skip to main content

rusqlite/
auto_extension.rs

1//! Automatic extension loading
2use super::ffi;
3use crate::error::{check, to_sqlite_error};
4use crate::{Connection, Error, Result};
5use std::ffi::{c_char, c_int};
6use std::panic::catch_unwind;
7
8/// Automatic extension initialization routine
9pub type AutoExtension = fn(Connection) -> Result<()>;
10
11/// Raw automatic extension initialization routine
12pub 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.
26pub 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    unsafe {
32        let r = catch_unwind(|| {
33            let c = Connection::from_handle(db);
34            c.and_then(ax)
35        })
36        .unwrap_or_else(|_| Err(Error::UnwindingPanic));
37        match r {
38            Err(e) => to_sqlite_error(&e, pz_err_msg),
39            _ => ffi::SQLITE_OK,
40        }
41    }
42}
43
44/// Register au auto-extension
45///
46/// # Safety
47/// * Opening a database from an auto-extension handler will lead to
48///   an endless recursion of the auto-handler triggering itself
49///   indirectly for each newly-opened database.
50/// * Results are undefined if the given db is closed by an auto-extension.
51/// * The list of auto-extensions should not be manipulated from an auto-extension.
52pub unsafe fn register_auto_extension(ax: RawAutoExtension) -> Result<()> {
53    check(unsafe { ffi::sqlite3_auto_extension(Some(ax)) })
54}
55
56/// Unregister the initialization routine
57pub fn cancel_auto_extension(ax: RawAutoExtension) -> bool {
58    unsafe { ffi::sqlite3_cancel_auto_extension(Some(ax)) == 1 }
59}
60
61/// Disable all automatic extensions previously registered
62pub fn reset_auto_extension() {
63    unsafe { ffi::sqlite3_reset_auto_extension() }
64}