soar_core/database/
connection.rs1use std::{
2 path::Path,
3 sync::{Arc, Mutex},
4};
5
6use rusqlite::Connection;
7
8use crate::error::SoarError;
9
10use super::{models::RemotePackage, repository::PackageRepository, statements::DbStatements};
11
12type Result<T> = std::result::Result<T, SoarError>;
13
14pub struct Database {
15 pub conn: Arc<Mutex<Connection>>,
16}
17
18impl Database {
19 pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> {
20 let path = path.as_ref();
21 let conn = Connection::open(path)?;
22 let conn = Arc::new(Mutex::new(conn));
23 Ok(Database { conn })
24 }
25
26 pub fn new_multi<P: AsRef<Path>>(paths: &[P]) -> Result<Self> {
27 let conn = Connection::open(&paths[0])?;
28 conn.execute("PRAGMA case_sensitive_like = ON;", [])?;
29
30 for (idx, path) in paths.iter().enumerate().skip(1) {
31 let path = path.as_ref();
32 conn.execute(
33 &format!("ATTACH DATABASE '{}' AS shard{}", path.display(), idx),
34 [],
35 )?;
36 conn.execute(&format!("PRAGMA shard{idx}.case_sensitive_like = ON;"), [])?;
37 }
38 let conn = Arc::new(Mutex::new(conn));
39 Ok(Database { conn })
40 }
41
42 pub fn from_remote_metadata(&self, metadata: &[RemotePackage], repo_name: &str) -> Result<()> {
43 let mut guard = self.conn.lock().unwrap();
44 let _: String = guard.query_row("PRAGMA journal_mode = WAL", [], |row| row.get(0))?;
45
46 let tx = guard.transaction()?;
47 {
48 let statements = DbStatements::new(&tx)?;
49 let mut repo = PackageRepository::new(&tx, statements, repo_name);
50 repo.import_packages(metadata)?;
51 }
52 tx.commit()?;
53 Ok(())
54 }
55}