mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-25 02:21:37 +08:00
Add a minimal loadable extension example
This commit is contained in:
parent
81585a75cb
commit
8051b048db
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@ -65,6 +65,9 @@ jobs:
|
|||||||
- run: cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
|
- run: cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
|
||||||
- run: cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
|
- run: cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
|
||||||
|
|
||||||
|
- name: loadable extension
|
||||||
|
run: cargo build --example loadable_extension --features "loadable_extension modern_sqlite functions vtab trace"
|
||||||
|
|
||||||
# TODO: move into own action for better caching
|
# TODO: move into own action for better caching
|
||||||
- name: Static build
|
- name: Static build
|
||||||
# Do we expect this to work / should we test with gnu toolchain?
|
# Do we expect this to work / should we test with gnu toolchain?
|
||||||
|
@ -157,6 +157,11 @@ harness = false
|
|||||||
name = "exec"
|
name = "exec"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "loadable_extension"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
required-features = ["loadable_extension", "modern_sqlite", "functions", "vtab", "trace"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["modern-full"]
|
features = ["modern-full"]
|
||||||
all-features = false
|
all-features = false
|
||||||
|
48
examples/loadable_extension.rs
Normal file
48
examples/loadable_extension.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//! Adaptation of https://sqlite.org/loadext.html#programming_loadable_extensions
|
||||||
|
use std::os::raw::{c_char, c_int};
|
||||||
|
|
||||||
|
use rusqlite::ffi;
|
||||||
|
use rusqlite::functions::FunctionFlags;
|
||||||
|
use rusqlite::types::{ToSqlOutput, Value};
|
||||||
|
use rusqlite::{to_sqlite_error, Connection, Result};
|
||||||
|
|
||||||
|
/// # build
|
||||||
|
/// ```sh
|
||||||
|
/// cargo build --example loadable_extension --features "loadable_extension modern_sqlite functions vtab trace"
|
||||||
|
/// ```
|
||||||
|
/// # test
|
||||||
|
/// ```sh
|
||||||
|
/// sqlite> .log on
|
||||||
|
/// sqlite> .load target/debug/examples/libloadable_extension.so
|
||||||
|
/// (28) Rusqlite extension initialized
|
||||||
|
/// sqlite> SELECT rusqlite_test_function();
|
||||||
|
/// Rusqlite extension loaded correctly!
|
||||||
|
/// ```
|
||||||
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sqlite3_extension_init(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
pz_err_msg: *mut *mut c_char,
|
||||||
|
p_api: *mut ffi::sqlite3_api_routines,
|
||||||
|
) -> c_int {
|
||||||
|
if let Err(err) = extension_init(db, p_api) {
|
||||||
|
return unsafe { to_sqlite_error(&err, pz_err_msg) };
|
||||||
|
}
|
||||||
|
ffi::SQLITE_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extension_init(db: *mut ffi::sqlite3, p_api: *mut ffi::sqlite3_api_routines) -> Result<()> {
|
||||||
|
let db = unsafe { Connection::extension_init2(db, p_api)? };
|
||||||
|
db.create_scalar_function(
|
||||||
|
"rusqlite_test_function",
|
||||||
|
0,
|
||||||
|
FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
|
|_ctx| {
|
||||||
|
Ok(ToSqlOutput::Owned(Value::Text(
|
||||||
|
"Rusqlite extension loaded correctly!".to_string(),
|
||||||
|
)))
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
rusqlite::trace::log(ffi::SQLITE_WARNING, "Rusqlite extension initialized");
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user