sqlite_tiny/ffi/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! FFI bindings to the shipped sqlite variant

#![allow(unused, reason = "Includes autogenerated bindings")]
#![allow(non_snake_case, reason = "Includes autogenerated bindings")]
#![allow(non_camel_case_types, reason = "Includes autogenerated bindings")]

include!("bindgen.rs");

// Glue bindings
extern "C" {
    /// Internal helper to get the pointer constant to define "transient" ownership (i.e. order SQLite to copy the value
    /// immediately)
    //sqlite3_destructor_type sqlite3_transient()
    #[doc(hidden)]
    pub fn sqlite3_transient() -> sqlite3_destructor_type;
}

/// Gets the last error from the database as [`crate::error::Error`]
///
/// # Safety
/// This function operates on a raw SQLite handle. If `database` is not `NULL` but invalid or points to an invalid
/// handle, the behaviour is undefined.
#[doc(hidden)]
pub unsafe fn sqlite3_last_error(retval: i32, database: *mut sqlite3) -> crate::error::Error {
    use std::{borrow::Cow, ffi::CStr};

    // Get the error string
    let error = sqlite3_errstr(retval);
    let mut message = match error.is_null() {
        true => Cow::Borrowed("Unknown"),
        false => CStr::from_ptr(error).to_string_lossy(),
    };

    // Append database specific error
    if !database.is_null() {
        // Get error from database
        let error = sqlite3_errmsg(database);
        let message_ = CStr::from_ptr(error).to_string_lossy();
        message = Cow::Owned(format!("{message} ({message_})"));
    }
    crate::err!("SQLite error: {message}")
}

/// Helper to translate a result code into a `Result`
///
/// # Safety
/// This function operates on a raw SQLite handle. If `database` is not `NULL` but invalid or points to an invalid
/// handle, the behaviour is undefined.
#[doc(hidden)]
#[inline]
pub unsafe fn sqlite3_check_result(retval: i32, database: *mut sqlite3) -> Result<(), crate::error::Error> {
    match retval {
        SQLITE_OK => Ok(()),
        _ => Err(sqlite3_last_error(retval, database)),
    }
}

/// Asserts that sqlite is compiled threadsafe
#[test]
fn assert_threadsafe() {
    let threadsafe = unsafe { sqlite3_threadsafe() };
    assert_ne!(threadsafe, 0, "sqlite is not compiled threadsafe?!")
}