Repository: diesel-rs/diesel
File: diesel/src/sqlite/connection/mod.rs (Rust)

Code before:
///
/// // SAFETY: We do not close or store the connection handle,
/// // and we do not modify state that Diesel depends on.
/// let version = unsafe {
///     conn.with_raw_connection(|_raw_conn| {
///         // Use raw_conn with SQLite C API functions from your own
///         // `libsqlite3-sys` (native) or `sqlite-wasm-rs` (WASM) dependency.
///         // For example: ffi::sqlite3session_create(raw_conn, ...)
///         42 // return a value
///     })
/// };
/// assert_eq!(version, 42);
/// ```
///
/// # Platform Notes
///
/// This trait works identically on both native and WASM targets. However,
/// you must depend on the appropriate FFI crate for your target:
///
/// - **Native**: Add `libsqlite3-sys` as a dependency
/// - **WASM** (`wasm32-unknown-unknown`): Add `sqlite-wasm-rs` as a dependency
///
/// Both crates expose a compatible `sqlite3` type that can be used with the
/// pointer returned by this method.
#[allow(unsafe_code)]
pub trait WithRawConnection {
    /// Provides temporary access to the raw SQLite connection handle.
    ///
    /// The callback receives a raw pointer to the underlying `sqlite3` handle,
    /// which can be used with SQLite C API functions.
    ///
    /// # Safety
    ///
    /// See the trait-level documentation for safety requirements.
    unsafe fn with_raw_connection<R, F>(&mut self, f: F) -> R
    where
        F: FnOnce(*mut ffi::sqlite3) -> R;
}

#[allow(unsafe_code)]
impl WithRawConnection for SqliteConnection {
    unsafe fn with_raw_connection<R, F>(&mut self, f: F) -> R
    where
        F: FnOnce(*mut ffi::sqlite3) -> R,
    {
        f(self.raw_connection.internal_connection.as_ptr())
    }
}

fn error_message(err_code: libc::c_int) -> &'static str {
    ffi::code_to_str(err_code)

Review comment (suggestion):
Instead of having a trait for this, I would rather turn this in a method on `SqliteConnection`. That safes some code and after all this will only be implemented by `SqliteConnection` at all.

Code after:
    pub unsafe fn with_raw_connection<R, F>(&mut self, f: F) -> R
    where
        F: FnOnce(*mut ffi::sqlite3) -> R,
    {
        f(self.raw_connection.internal_connection.as_ptr())
    }

    fn register_diesel_sql_functions(&self) -> QueryResult<()> {
        use crate::sql_types::{Integer, Text};

        functions::register::<Text, Integer, _, _, _>(
            &self.raw_connection,
            "diesel_manage_updated_at",
            false,
            |conn, table_name: String| {
                conn.exec(&alloc::format!(
                    include_str!("diesel_manage_updated_at.sql"),
                    table_name = table_name
                ))
                .expect("Failed to create trigger");
                0 // have to return *something*
            },
        )
    }

    fn establish_inner(database_url: &str) -> Result<SqliteConnection, ConnectionError> {
        use crate::result::ConnectionError::CouldntSetupConfiguration;
        let raw_connection = RawConnection::establish(database_url)?;
        let conn = Self {
            statement_cache: StatementCache::new(),
            raw_connection,
            transaction_state: AnsiTransactionManager::default(),
            metadata_lookup: (),
            instrumentation: DynInstrumentation::none(),
        };
        conn.register_diesel_sql_functions()
            .map_err(CouldntSetupConfiguration)?;
        Ok(conn)
    }
}

fn error_message(err_code: libc::c_int) -> &'static str {
    ffi::code_to_str(err_code)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::dsl::sql;
    use crate::prelude::*;
    use crate::sql_types::{Integer, Text};