winbrew_database/
connection.rs1use anyhow::{Context, Result};
2use r2d2::{ManageConnection, Pool};
3use rusqlite::{Connection, OpenFlags};
4use std::path::{Path, PathBuf};
5use std::time::Duration;
6
7#[derive(Clone, Debug)]
8pub struct SqliteConnectionManager {
9 path: PathBuf,
10 read_only: bool,
11}
12
13impl ManageConnection for SqliteConnectionManager {
14 type Connection = Connection;
15 type Error = rusqlite::Error;
16
17 fn connect(&self) -> std::result::Result<Self::Connection, Self::Error> {
18 open_connection(&self.path, self.read_only)
19 }
20
21 fn is_valid(&self, conn: &mut Self::Connection) -> std::result::Result<(), Self::Error> {
22 conn.execute_batch("SELECT 1;")
23 }
24
25 fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
26 false
27 }
28}
29
30pub(crate) fn open_connection(
31 path: &Path,
32 read_only: bool,
33) -> std::result::Result<Connection, rusqlite::Error> {
34 let conn = if read_only {
35 if !path.exists() {
36 return Err(rusqlite::Error::SqliteFailure(
37 rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_CANTOPEN),
38 Some(format!("catalog database not found: {}", path.display())),
39 ));
40 }
41
42 Connection::open_with_flags(path, OpenFlags::SQLITE_OPEN_READ_ONLY)?
43 } else {
44 Connection::open(path)?
45 };
46 conn.busy_timeout(Duration::from_secs(5))?;
47
48 if read_only {
49 conn.execute_batch("PRAGMA query_only=ON; PRAGMA foreign_keys=ON;")?;
50 } else {
51 conn.execute_batch(
52 "PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL; PRAGMA foreign_keys=ON;",
53 )?;
54 }
55
56 Ok(conn)
57}
58
59pub(crate) fn build_pool(
60 path: PathBuf,
61 read_only: bool,
62 max_size: u32,
63 migrate: Option<fn(&Connection) -> Result<()>>,
64) -> Result<Pool<SqliteConnectionManager>> {
65 let pool = Pool::builder()
66 .max_size(max_size)
67 .build(SqliteConnectionManager { path, read_only })
68 .context("failed to initialize SQLite connection pool")?;
69
70 if let Some(migrate) = migrate {
71 let conn = pool
72 .get()
73 .context("failed to get database connection for migrations")?;
74 migrate(&conn)?;
75 }
76
77 Ok(pool)
78}