use crate::errors::{Error, Result}; use diesel::{ expression::SqlLiteral, query_dsl::load_dsl::LoadQuery, sql_types::{Integer, Text}, SqliteConnection, }; use crate::conn_ext::ConnectionExtension; use std::{ convert::{TryFrom, TryInto}, fmt, str::FromStr, }; pub trait PragmaExtension: ConnectionExtension { fn pragma(&self, key: &str, val: D, schema: Option<&str>) -> Result<()> { let query = match schema { Some(schema) => format!("PRAGMA {}.{} = '{}'", schema, key, val), None => format!("PRAGMA {} = '{}'", key, val), }; log::trace!("SQLITE {}", query); self.exec(&query)?; Ok(()) } fn pragma_ret( &self, key: &str, val: D, schema: Option<&str>, ) -> Result where SqlLiteral: LoadQuery, { let query = match schema { Some(schema) => format!("PRAGMA {}.{} = '{}'", schema, key, val), None => format!("PRAGMA {} = '{}'", key, val), }; log::trace!("SQLITE {}", query); Ok(self.query::(&query)?) } fn pragma_get(&self, key: &str, schema: Option<&str>) -> Result where SqlLiteral: LoadQuery, { let query = match schema { Some(schema) => format!("PRAGMA {}.{}", schema, key), None => format!("PRAGMA {}", key), }; log::trace!("SQLITE {}", query); Ok(self.query::(&query)?) } fn pragma_set_busy_timeout(&self, timeout_ms: i32) -> Result { self.pragma_ret::("busy_timeout", timeout_ms, None) } fn pragma_get_busy_timeout(&self) -> Result { self.pragma_get::("busy_timeout", None) } fn pragma_set_journal_mode( &self, mode: SQLiteJournalMode, schema: Option<&str>, ) -> Result { self.pragma_ret::("journal_mode", mode, schema) } fn pragma_get_journal_mode(&self, schema: Option<&str>) -> Result { Ok(self .pragma_get::("journal_mode", schema)? .parse()?) } fn pragma_set_synchronous( &self, synchronous: SQLiteSynchronous, schema: Option<&str>, ) -> Result<()> { self.pragma("synchronous", synchronous as u8, schema) } fn pragma_get_synchronous(&self, schema: Option<&str>) -> Result { Ok(self .pragma_get::("synchronous", schema)? .try_into()?) } } impl PragmaExtension for SqliteConnection {} #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum SQLiteJournalMode { DELETE, TRUNCATE, PERSIST, MEMORY, WAL, OFF, } impl fmt::Display for SQLiteJournalMode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{}", match self { Self::DELETE => "DELETE", Self::TRUNCATE => "TRUNCATE", Self::PERSIST => "PERSIST", Self::MEMORY => "MEMORY", Self::WAL => "WAL", Self::OFF => "OFF", } ) } } impl FromStr for SQLiteJournalMode { type Err = Error; fn from_str(s: &str) -> Result { match s.to_uppercase().as_ref() { "DELETE" => Ok(Self::DELETE), "TRUNCATE" => Ok(Self::TRUNCATE), "PERSIST" => Ok(Self::PERSIST), "MEMORY" => Ok(Self::MEMORY), "WAL" => Ok(Self::WAL), "OFF" => Ok(Self::OFF), _ => Err(format!("Unknown value {} for JournalMode", s).into()), } } } #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum SQLiteSynchronous { EXTRA = 3, FULL = 2, NORMAL = 1, OFF = 0, } impl fmt::Display for SQLiteSynchronous { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{}", match self { Self::OFF => "OFF", Self::NORMAL => "NORMAL", Self::FULL => "FULL", Self::EXTRA => "EXTRA", } ) } } impl TryFrom for SQLiteSynchronous { type Error = Error; fn try_from(v: i32) -> Result { match v { 0 => Ok(Self::OFF), 1 => Ok(Self::NORMAL), 2 => Ok(Self::FULL), 3 => Ok(Self::EXTRA), _ => Err(format!("Unknown value {} for Synchronous", v).into()), } } } impl FromStr for SQLiteSynchronous { type Err = Error; fn from_str(s: &str) -> Result { match s.to_uppercase().as_ref() { "0" | "OFF" => Ok(Self::OFF), "1" | "NORMAL" => Ok(Self::NORMAL), "2" | "FULL" => Ok(Self::FULL), "3" | "EXTRA" => Ok(Self::EXTRA), _ => Err(format!("Unknown value {} for Synchronous", s).into()), } } }