sql_middleware/sqlite/connection/
core.rs1use std::fmt;
2use std::sync::Arc;
3
4use crate::middleware::SqlMiddlewareDbError;
5
6use crate::sqlite::config::{SharedSqliteConnection, SqlitePooledConnection};
7use tokio::sync::oneshot;
8
9pub struct SqliteConnection {
11 pub(crate) conn: SqlitePooledConnection,
12 pub(crate) in_transaction: bool,
13}
14
15impl SqliteConnection {
16 pub(crate) fn new(conn: SqlitePooledConnection) -> Self {
17 Self {
18 conn,
19 in_transaction: false,
20 }
21 }
22
23 pub async fn with_connection<F, R>(&self, func: F) -> Result<R, SqlMiddlewareDbError>
28 where
29 F: FnOnce(&mut rusqlite::Connection) -> Result<R, SqlMiddlewareDbError> + Send + 'static,
30 R: Send + 'static,
31 {
32 if self.in_transaction {
33 return Err(SqlMiddlewareDbError::ExecutionError(
34 "SQLite transaction in progress; operation not permitted (with connection)".into(),
35 ));
36 }
37 run_blocking(self.conn_handle(), func).await
38 }
39
40 pub(crate) fn conn_handle(&self) -> SharedSqliteConnection {
41 Arc::clone(&*self.conn)
42 }
43
44 pub(crate) fn ensure_not_in_tx(&self, ctx: &str) -> Result<(), SqlMiddlewareDbError> {
45 if self.in_transaction {
46 Err(SqlMiddlewareDbError::ExecutionError(format!(
47 "SQLite transaction in progress; operation not permitted ({ctx})"
48 )))
49 } else {
50 Ok(())
51 }
52 }
53}
54
55impl fmt::Debug for SqliteConnection {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.debug_struct("SqliteConnection")
58 .field("conn", &self.conn)
59 .field("in_transaction", &self.in_transaction)
60 .finish()
61 }
62}
63
64pub(crate) async fn run_blocking<F, R>(
65 conn: SharedSqliteConnection,
66 func: F,
67) -> Result<R, SqlMiddlewareDbError>
68where
69 F: FnOnce(&mut rusqlite::Connection) -> Result<R, SqlMiddlewareDbError> + Send + 'static,
70 R: Send + 'static,
71{
72 let (tx, rx) = oneshot::channel();
73 conn.execute(move |conn| {
74 let _ = tx.send(func(conn));
75 })?;
76 rx.await.map_err(|e| {
77 SqlMiddlewareDbError::ExecutionError(format!("sqlite worker receive error: {e}"))
78 })?
79}
80
81pub async fn apply_wal_pragmas(
86 conn: &mut SqlitePooledConnection,
87) -> Result<(), SqlMiddlewareDbError> {
88 let handle = Arc::clone(&*conn);
89 run_blocking(handle, |guard| {
90 guard
91 .execute_batch("PRAGMA journal_mode = WAL;")
92 .map_err(SqlMiddlewareDbError::SqliteError)
93 })
94 .await
95}