sqlite_graphrag/storage/
connection.rs1use crate::errors::AppError;
7use crate::pragmas::apply_connection_pragmas;
8use rusqlite::Connection;
9use sqlite_vec::sqlite3_vec_init;
10use std::path::Path;
11
12pub fn register_vec_extension() {
15 #[allow(clippy::missing_transmute_annotations)]
24 unsafe {
25 rusqlite::ffi::sqlite3_auto_extension(Some(std::mem::transmute(
26 sqlite3_vec_init as *const (),
27 )));
28 }
29}
30
31pub fn open_rw(path: &Path) -> Result<Connection, AppError> {
32 let conn = Connection::open(path)?;
33 apply_connection_pragmas(&conn)?;
34 apply_secure_permissions(path);
35 Ok(conn)
36}
37
38pub fn ensure_schema(conn: &mut Connection) -> Result<(), AppError> {
39 crate::migrations::runner()
40 .run(conn)
41 .map_err(|e| AppError::Internal(anyhow::anyhow!("migration failed: {e}")))?;
42 conn.execute_batch(&format!(
43 "PRAGMA user_version = {};",
44 crate::constants::SCHEMA_USER_VERSION
45 ))?;
46 Ok(())
47}
48
49#[allow(unused_variables)]
54fn apply_secure_permissions(path: &Path) {
55 #[cfg(unix)]
56 {
57 use std::os::unix::fs::PermissionsExt;
58 let candidates = [
59 path.to_path_buf(),
60 path.with_extension(format!(
61 "{}-wal",
62 path.extension()
63 .and_then(|e| e.to_str())
64 .unwrap_or("sqlite")
65 )),
66 path.with_extension(format!(
67 "{}-shm",
68 path.extension()
69 .and_then(|e| e.to_str())
70 .unwrap_or("sqlite")
71 )),
72 ];
73 for file in candidates.iter() {
74 if file.exists() {
75 if let Ok(meta) = std::fs::metadata(file) {
76 let mut perms = meta.permissions();
77 perms.set_mode(0o600);
78 let _ = std::fs::set_permissions(file, perms);
79 }
80 }
81 }
82 }
83}
84
85pub fn open_ro(path: &Path) -> Result<Connection, AppError> {
86 let conn = Connection::open_with_flags(
87 path,
88 rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY | rusqlite::OpenFlags::SQLITE_OPEN_URI,
89 )?;
90 conn.execute_batch("PRAGMA foreign_keys = ON;")?;
91 Ok(conn)
92}