sql_middleware/sqlite/config.rs
1use deadpool_sqlite::{Config as DeadpoolSqliteConfig, Runtime};
2
3use crate::middleware::{ConfigAndPool, DatabaseType, MiddlewarePool, SqlMiddlewareDbError};
4
5impl ConfigAndPool {
6 /// Asynchronous initializer for `ConfigAndPool` with Sqlite using `deadpool_sqlite`
7 ///
8 /// # Errors
9 /// Returns `SqlMiddlewareDbError::ConnectionError` if pool creation or connection test fails.
10 pub async fn new_sqlite(db_path: String) -> Result<Self, SqlMiddlewareDbError> {
11 Self::new_sqlite_with_translation(db_path, false).await
12 }
13
14 /// Asynchronous initializer for `ConfigAndPool` with Sqlite using `deadpool_sqlite`
15 /// and optional placeholder translation default.
16 ///
17 /// # Errors
18 /// Returns `SqlMiddlewareDbError::ConnectionError` if pool creation or connection test fails.
19 ///
20 /// Warning: translation skips placeholders inside quoted strings, comments, and dollar-quoted
21 /// blocks via a lightweight state machine; it may miss edge cases in complex SQL. Prefer
22 /// backend-specific SQL instead of relying on translation:
23 /// ```rust
24 /// # use sql_middleware::prelude::*;
25 /// let query = match &conn {
26 /// MiddlewarePoolConnection::Postgres { .. } => r#"$function$
27 /// BEGIN
28 /// RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
29 /// END;
30 /// $function$"#,
31 /// MiddlewarePoolConnection::Sqlite { .. } | MiddlewarePoolConnection::Turso { .. } => {
32 /// include_str!("../sql/functions/sqlite/03_sp_get_scores.sql")
33 /// }
34 /// };
35 /// ```
36 pub async fn new_sqlite_with_translation(
37 db_path: String,
38 translate_placeholders: bool,
39 ) -> Result<Self, SqlMiddlewareDbError> {
40 // Configure deadpool_sqlite
41 let cfg: DeadpoolSqliteConfig = DeadpoolSqliteConfig::new(db_path.clone());
42
43 // Create the pool
44 let pool = cfg.create_pool(Runtime::Tokio1).map_err(|e| {
45 SqlMiddlewareDbError::ConnectionError(format!("Failed to create SQLite pool: {e}"))
46 })?;
47
48 // Initialize the database (e.g., create tables)
49 {
50 let conn = pool
51 .get()
52 .await
53 .map_err(SqlMiddlewareDbError::PoolErrorSqlite)?;
54 let _res = conn
55 .interact(|conn| {
56 conn.execute_batch(
57 "
58 PRAGMA journal_mode = WAL;
59 ",
60 )
61 .map_err(SqlMiddlewareDbError::SqliteError)
62 })
63 .await?;
64 }
65
66 Ok(ConfigAndPool {
67 pool: MiddlewarePool::Sqlite(pool),
68 db_type: DatabaseType::Sqlite,
69 translate_placeholders,
70 })
71 }
72}
73
74/// Convert `InteractError` to a more specific `SqlMiddlewareDbError`
75impl From<deadpool_sqlite::InteractError> for SqlMiddlewareDbError {
76 fn from(err: deadpool_sqlite::InteractError) -> Self {
77 SqlMiddlewareDbError::ConnectionError(format!("SQLite Interact Error: {err}"))
78 }
79}