mirror of
https://github.com/isar/rusqlite.git
synced 2025-04-01 03:22:58 +08:00
Add bindings to automatic extension loading API (#1487)
* Add bindings to automatic extension loading API it doesn't seem possible to directly register an `AutoExtension`.
This commit is contained in:
parent
381be988cc
commit
57a3a8f62e
@ -140,6 +140,9 @@ bencher = "0.1"
|
|||||||
path = "libsqlite3-sys"
|
path = "libsqlite3-sys"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "auto_ext"
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "config_log"
|
name = "config_log"
|
||||||
harness = false
|
harness = false
|
||||||
|
@ -5,8 +5,8 @@ extern "C" {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
@ -16,8 +16,8 @@ extern "C" {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
|
@ -554,8 +554,8 @@ mod bindings {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
@ -568,8 +568,8 @@ mod bindings {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
|
@ -5,8 +5,8 @@ extern "C" {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
@ -16,8 +16,8 @@ extern "C" {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
|
@ -5,8 +5,8 @@ extern "C" {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
@ -16,8 +16,8 @@ extern "C" {
|
|||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
unsafe extern "C" fn(
|
unsafe extern "C" fn(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||||
pThunk: *const sqlite3_api_routines,
|
_: *const sqlite3_api_routines,
|
||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
|
57
src/auto_extension.rs
Normal file
57
src/auto_extension.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//! Automatic axtension loading
|
||||||
|
use super::ffi;
|
||||||
|
use crate::error::{check, to_sqlite_error};
|
||||||
|
use crate::{Connection, Result};
|
||||||
|
use std::os::raw::{c_char, c_int};
|
||||||
|
|
||||||
|
/// Automatic extension initialization routine
|
||||||
|
pub type AutoExtension = fn(Connection) -> Result<()>;
|
||||||
|
|
||||||
|
/// Raw automatic extension initialization routine
|
||||||
|
pub type RawAutoExtension = unsafe extern "C" fn(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
pz_err_msg: *mut *mut c_char,
|
||||||
|
_: *const ffi::sqlite3_api_routines,
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
/// Bridge bewteen `RawAutoExtension` and `AutoExtension`
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// * Opening a database from an auto-extension handler will lead to
|
||||||
|
/// an endless recursion of the auto-handler triggering itself
|
||||||
|
/// indirectly for each newly-opened database.
|
||||||
|
/// * Results are undefined if the given db is closed by an auto-extension.
|
||||||
|
/// * The list of auto-extensions should not be manipulated from an auto-extension.
|
||||||
|
pub unsafe fn init_auto_extension(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
pz_err_msg: *mut *mut c_char,
|
||||||
|
ax: AutoExtension,
|
||||||
|
) -> c_int {
|
||||||
|
let c = Connection::from_handle(db);
|
||||||
|
match c.and_then(ax) {
|
||||||
|
Err(e) => to_sqlite_error(&e, pz_err_msg),
|
||||||
|
_ => ffi::SQLITE_OK,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register au auto-extension
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// * Opening a database from an auto-extension handler will lead to
|
||||||
|
/// an endless recursion of the auto-handler triggering itself
|
||||||
|
/// indirectly for each newly-opened database.
|
||||||
|
/// * Results are undefined if the given db is closed by an auto-extension.
|
||||||
|
/// * The list of auto-extensions should not be manipulated from an auto-extension.
|
||||||
|
pub unsafe fn register_auto_extension(ax: RawAutoExtension) -> Result<()> {
|
||||||
|
check(ffi::sqlite3_auto_extension(Some(ax)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unregister the initialization routine
|
||||||
|
pub fn cancel_auto_extension(ax: RawAutoExtension) -> bool {
|
||||||
|
unsafe { ffi::sqlite3_cancel_auto_extension(Some(ax)) == 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable all automatic extensions previously registered
|
||||||
|
pub fn reset_auto_extension() {
|
||||||
|
unsafe { ffi::sqlite3_reset_auto_extension() }
|
||||||
|
}
|
@ -93,6 +93,8 @@ pub use rusqlite_macros::__bind;
|
|||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "loadable_extension"))]
|
||||||
|
pub mod auto_extension;
|
||||||
#[cfg(feature = "backup")]
|
#[cfg(feature = "backup")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "backup")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "backup")))]
|
||||||
pub mod backup;
|
pub mod backup;
|
||||||
|
41
tests/auto_ext.rs
Normal file
41
tests/auto_ext.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#[cfg(all(feature = "bundled", not(feature = "loadable_extension")))]
|
||||||
|
#[test]
|
||||||
|
fn auto_ext() -> rusqlite::Result<()> {
|
||||||
|
use rusqlite::auto_extension::*;
|
||||||
|
use rusqlite::{ffi, Connection, Error, Result};
|
||||||
|
use std::os::raw::{c_char, c_int};
|
||||||
|
|
||||||
|
fn test_ok(_: Connection) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
unsafe extern "C" fn sqlite_test_ok(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
pz_err_msg: *mut *mut c_char,
|
||||||
|
_: *const ffi::sqlite3_api_routines,
|
||||||
|
) -> c_int {
|
||||||
|
init_auto_extension(db, pz_err_msg, test_ok)
|
||||||
|
}
|
||||||
|
fn test_err(_: Connection) -> Result<()> {
|
||||||
|
Err(Error::SqliteFailure(
|
||||||
|
ffi::Error::new(ffi::SQLITE_CORRUPT),
|
||||||
|
Some("AutoExtErr".to_owned()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
unsafe extern "C" fn sqlite_test_err(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
pz_err_msg: *mut *mut c_char,
|
||||||
|
_: *const ffi::sqlite3_api_routines,
|
||||||
|
) -> c_int {
|
||||||
|
init_auto_extension(db, pz_err_msg, test_err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//assert!(!cancel_auto_extension(sqlite_test_ok));
|
||||||
|
unsafe { register_auto_extension(sqlite_test_ok)? };
|
||||||
|
Connection::open_in_memory()?;
|
||||||
|
assert!(cancel_auto_extension(sqlite_test_ok));
|
||||||
|
assert!(!cancel_auto_extension(sqlite_test_ok));
|
||||||
|
unsafe { register_auto_extension(sqlite_test_err)? };
|
||||||
|
Connection::open_in_memory().unwrap_err();
|
||||||
|
reset_auto_extension();
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user