use std::path::Path;
mod auto_vacuum;
mod connect;
mod journal_mode;
mod locking_mode;
mod parse;
mod synchronous;
use crate::connection::LogSettings;
pub use auto_vacuum::SqliteAutoVacuum;
pub use journal_mode::SqliteJournalMode;
pub use locking_mode::SqliteLockingMode;
use std::cmp::Ordering;
use std::sync::Arc;
use std::{borrow::Cow, time::Duration};
pub use synchronous::SqliteSynchronous;
use crate::common::DebugFn;
use crate::connection::collation::Collation;
use sqlx_core::IndexMap;
#[derive(Clone, Debug)]
pub struct SqliteConnectOptions {
pub(crate) filename: Cow<'static, Path>,
pub(crate) in_memory: bool,
pub(crate) read_only: bool,
pub(crate) create_if_missing: bool,
pub(crate) shared_cache: bool,
pub(crate) statement_cache_capacity: usize,
pub(crate) busy_timeout: Duration,
pub(crate) log_settings: LogSettings,
pub(crate) immutable: bool,
pub(crate) vfs: Option<Cow<'static, str>>,
pub(crate) pragmas: IndexMap<Cow<'static, str>, Option<Cow<'static, str>>>,
pub(crate) extensions: IndexMap<Cow<'static, str>, Option<Cow<'static, str>>>,
pub(crate) command_channel_size: usize,
pub(crate) row_channel_size: usize,
pub(crate) collations: Vec<Collation>,
pub(crate) serialized: bool,
pub(crate) thread_name: Arc<DebugFn<dyn Fn(u64) -> String + Send + Sync + 'static>>,
pub(crate) optimize_on_close: OptimizeOnClose,
#[cfg(feature = "regexp")]
pub(crate) register_regexp_function: bool,
}
#[derive(Clone, Debug)]
pub enum OptimizeOnClose {
Enabled { analysis_limit: Option<u32> },
Disabled,
}
impl Default for SqliteConnectOptions {
fn default() -> Self {
Self::new()
}
}
impl SqliteConnectOptions {
pub fn new() -> Self {
let mut pragmas: IndexMap<Cow<'static, str>, Option<Cow<'static, str>>> = IndexMap::new();
pragmas.insert("key".into(), None);
pragmas.insert("cipher_plaintext_header_size".into(), None);
pragmas.insert("cipher_salt".into(), None);
pragmas.insert("kdf_iter".into(), None);
pragmas.insert("cipher_kdf_algorithm".into(), None);
pragmas.insert("cipher_use_hmac".into(), None);
pragmas.insert("cipher_compatibility".into(), None);
pragmas.insert("cipher_page_size".into(), None);
pragmas.insert("cipher_hmac_algorithm".into(), None);
pragmas.insert("page_size".into(), None);
pragmas.insert("locking_mode".into(), None);
pragmas.insert("auto_vacuum".into(), None);
pragmas.insert("journal_mode".into(), None);
pragmas.insert("foreign_keys".into(), Some("ON".into()));
pragmas.insert("synchronous".into(), None);
pragmas.insert("analysis_limit".into(), None);
Self {
filename: Cow::Borrowed(Path::new(":memory:")),
in_memory: false,
read_only: false,
create_if_missing: false,
shared_cache: false,
statement_cache_capacity: 100,
busy_timeout: Duration::from_secs(5),
log_settings: Default::default(),
immutable: false,
vfs: None,
pragmas,
extensions: Default::default(),
collations: Default::default(),
serialized: false,
thread_name: Arc::new(DebugFn(|id| format!("sqlx-sqlite-worker-{id}"))),
command_channel_size: 50,
row_channel_size: 50,
optimize_on_close: OptimizeOnClose::Disabled,
#[cfg(feature = "regexp")]
register_regexp_function: false,
}
}
pub fn filename(mut self, filename: impl AsRef<Path>) -> Self {
self.filename = Cow::Owned(filename.as_ref().to_owned());
self
}
pub fn get_filename(&self) -> &Path {
&self.filename
}
pub fn foreign_keys(self, on: bool) -> Self {
self.pragma("foreign_keys", if on { "ON" } else { "OFF" })
}
pub fn in_memory(mut self, in_memory: bool) -> Self {
self.in_memory = in_memory;
self
}
pub fn shared_cache(mut self, on: bool) -> Self {
self.shared_cache = on;
self
}
pub fn journal_mode(self, mode: SqliteJournalMode) -> Self {
self.pragma("journal_mode", mode.as_str())
}
pub fn locking_mode(self, mode: SqliteLockingMode) -> Self {
self.pragma("locking_mode", mode.as_str())
}
pub fn read_only(mut self, read_only: bool) -> Self {
self.read_only = read_only;
self
}
pub fn create_if_missing(mut self, create: bool) -> Self {
self.create_if_missing = create;
self
}
pub fn statement_cache_capacity(mut self, capacity: usize) -> Self {
self.statement_cache_capacity = capacity;
self
}
pub fn busy_timeout(mut self, timeout: Duration) -> Self {
self.busy_timeout = timeout;
self
}
pub fn synchronous(self, synchronous: SqliteSynchronous) -> Self {
self.pragma("synchronous", synchronous.as_str())
}
pub fn auto_vacuum(self, auto_vacuum: SqliteAutoVacuum) -> Self {
self.pragma("auto_vacuum", auto_vacuum.as_str())
}
pub fn page_size(self, page_size: u32) -> Self {
self.pragma("page_size", page_size.to_string())
}
pub fn pragma<K, V>(mut self, key: K, value: V) -> Self
where
K: Into<Cow<'static, str>>,
V: Into<Cow<'static, str>>,
{
self.pragmas.insert(key.into(), Some(value.into()));
self
}
pub fn collation<N, F>(mut self, name: N, collate: F) -> Self
where
N: Into<Arc<str>>,
F: Fn(&str, &str) -> Ordering + Send + Sync + 'static,
{
self.collations.push(Collation::new(name, collate));
self
}
pub fn immutable(mut self, immutable: bool) -> Self {
self.immutable = immutable;
self
}
pub fn serialized(mut self, serialized: bool) -> Self {
self.serialized = serialized;
self
}
pub fn thread_name(
mut self,
generator: impl Fn(u64) -> String + Send + Sync + 'static,
) -> Self {
self.thread_name = Arc::new(DebugFn(generator));
self
}
pub fn command_buffer_size(mut self, size: usize) -> Self {
self.command_channel_size = size;
self
}
pub fn row_buffer_size(mut self, size: usize) -> Self {
self.row_channel_size = size;
self
}
pub fn vfs(mut self, vfs_name: impl Into<Cow<'static, str>>) -> Self {
self.vfs = Some(vfs_name.into());
self
}
pub fn extension(mut self, extension_name: impl Into<Cow<'static, str>>) -> Self {
self.extensions.insert(extension_name.into(), None);
self
}
pub fn extension_with_entrypoint(
mut self,
extension_name: impl Into<Cow<'static, str>>,
entry_point: impl Into<Cow<'static, str>>,
) -> Self {
self.extensions
.insert(extension_name.into(), Some(entry_point.into()));
self
}
pub fn optimize_on_close(
mut self,
enabled: bool,
analysis_limit: impl Into<Option<u32>>,
) -> Self {
self.optimize_on_close = if enabled {
OptimizeOnClose::Enabled {
analysis_limit: (analysis_limit.into()),
}
} else {
OptimizeOnClose::Disabled
};
self
}
pub fn analysis_limit(mut self, limit: impl Into<Option<u32>>) -> Self {
if let Some(limit) = limit.into() {
return self.pragma("analysis_limit", limit.to_string());
}
self.pragmas.insert("analysis_limit".into(), None);
self
}
#[cfg(feature = "regexp")]
pub fn with_regexp(mut self) -> Self {
self.register_regexp_function = true;
self
}
}