1 //! Adaptation of https://sqlite.org/loadext.html#programming_loadable_extensions
2 use std::os::raw::{c_char, c_int};
3
4 use rusqlite::ffi;
5 use rusqlite::functions::FunctionFlags;
6 use rusqlite::types::{ToSqlOutput, Value};
7 use rusqlite::{Connection, Result};
8
9 /// # build
10 /// ```sh
11 /// cargo build --example loadable_extension --features "loadable_extension functions trace"
12 /// ```
13 /// # test
14 /// ```sh
15 /// sqlite> .log on
16 /// sqlite> .load target/debug/examples/libloadable_extension.so
17 /// (28) Rusqlite extension initialized
18 /// sqlite> SELECT rusqlite_test_function();
19 /// Rusqlite extension loaded correctly!
20 /// ```
21 #[allow(clippy::not_unsafe_ptr_arg_deref)]
22 #[no_mangle]
sqlite3_extension_init( db: *mut ffi::sqlite3, pz_err_msg: *mut *mut c_char, p_api: *mut ffi::sqlite3_api_routines, ) -> c_int23 pub unsafe extern "C" fn sqlite3_extension_init(
24 db: *mut ffi::sqlite3,
25 pz_err_msg: *mut *mut c_char,
26 p_api: *mut ffi::sqlite3_api_routines,
27 ) -> c_int {
28 Connection::extension_init2(db, pz_err_msg, p_api, extension_init)
29 }
30
extension_init(db: Connection) -> Result<bool>31 fn extension_init(db: Connection) -> Result<bool> {
32 db.create_scalar_function(
33 "rusqlite_test_function",
34 0,
35 FunctionFlags::SQLITE_DETERMINISTIC,
36 |_ctx| {
37 Ok(ToSqlOutput::Owned(Value::Text(
38 "Rusqlite extension loaded correctly!".to_string(),
39 )))
40 },
41 )?;
42 rusqlite::trace::log(ffi::SQLITE_WARNING, "Rusqlite extension initialized");
43 Ok(false)
44 }
45