pub mod schema;
use crate::error::LoreError;
use rusqlite::Connection;
use std::path::Path;
#[derive(Debug)]
pub struct Database {
conn: Connection,
}
impl Database {
pub const fn connection(&self) -> &Connection {
&self.conn
}
pub fn open(path: &Path) -> Result<Self, LoreError> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.map_err(|e| LoreError::Validation(format!("failed to create db dir: {e}")))?;
}
let conn = Connection::open(path)?;
conn.pragma_update(None, "journal_mode", "WAL")?;
schema::init_schema(&conn)?;
Ok(Self { conn })
}
pub fn open_in_memory() -> Result<Self, LoreError> {
let conn = Connection::open_in_memory()?;
conn.pragma_update(None, "journal_mode", "WAL")?;
schema::init_schema(&conn)?;
Ok(Self { conn })
}
pub fn into_connection(self) -> Connection {
self.conn
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::panic)]
use super::*;
#[test]
fn test_open_in_memory_creates_schema() {
let db = Database::open_in_memory().unwrap();
let count: i64 = db
.connection()
.query_row(
"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='entry'",
[],
|row| row.get(0),
)
.unwrap();
assert_eq!(count, 1);
}
#[test]
fn test_fts_table_exists() {
let db = Database::open_in_memory().unwrap();
let count: i64 = db
.connection()
.query_row(
"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='entry_fts'",
[],
|row| row.get(0),
)
.unwrap();
assert_eq!(count, 1);
}
#[test]
fn test_schema_version_initialized() {
let db = Database::open_in_memory().unwrap();
let version: i32 = db
.connection()
.query_row(
"SELECT version FROM schema_version ORDER BY version DESC LIMIT 1",
[],
|row| row.get(0),
)
.unwrap();
assert_eq!(version, 2);
}
#[test]
fn test_wal_mode_enabled() {
let db = Database::open_in_memory().unwrap();
let mode: String =
db.connection().query_row("PRAGMA journal_mode", [], |row| row.get(0)).unwrap();
assert!(!mode.is_empty());
}
}