mod bootstrap;
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
mod native;
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
mod wasm;
use rusqlite::Connection;
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
use std::path::Path;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum DbError {
#[error("rusqlite error: {0}")]
Rusqlite(#[from] rusqlite::Error),
#[error("bootstrap error: {0}")]
Bootstrap(String),
#[cfg(all(target_family = "wasm", target_os = "unknown", feature = "opfs"))]
#[error("OPFS/SAH-pool error: {0}")]
Opfs(String),
}
pub type DbResult<T> = Result<T, DbError>;
pub struct DucConnection(pub(crate) Connection);
impl DucConnection {
pub fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(&Connection) -> R,
{
f(&self.0)
}
pub fn into_inner(self) -> Connection {
self.0
}
pub fn open_raw(path: &str) -> DbResult<Self> {
let conn = Connection::open(path).map_err(DbError::from)?;
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
conn.execute_batch("PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON;")
.map_err(|e| DbError::Bootstrap(format!("pragma apply failed: {e}")))?;
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
conn.execute_batch("PRAGMA journal_mode = MEMORY; PRAGMA foreign_keys = ON;")
.map_err(|e| DbError::Bootstrap(format!("pragma apply failed: {e}")))?;
Ok(Self(conn))
}
pub fn from_inner(conn: Connection) -> Self {
Self(conn)
}
}
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
pub fn open_file(path: impl AsRef<Path>) -> DbResult<DucConnection> {
native::open_file(path)
}
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
pub fn open_memory() -> DbResult<DucConnection> {
native::open_memory()
}
#[cfg(all(target_family = "wasm", target_os = "unknown", feature = "opfs"))]
pub async fn open_file_opfs(name: &str) -> DbResult<DucConnection> {
wasm::open_file_opfs(name).await
}
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
pub fn open_memory() -> DbResult<DucConnection> {
wasm::open_memory()
}
pub fn open_memory_compact() -> DbResult<DucConnection> {
let conn = Connection::open_in_memory()?;
conn.execute_batch("PRAGMA page_size = 1024;")
.map_err(|e| DbError::Bootstrap(format!("page_size pragma: {e}")))?;
bootstrap::bootstrap(&conn)?;
Ok(DucConnection(conn))
}