Skip to main content

sqlite_graphrag/storage/
connection.rs

1use crate::errors::AppError;
2use crate::pragmas::apply_connection_pragmas;
3use rusqlite::Connection;
4use sqlite_vec::sqlite3_vec_init;
5use std::path::Path;
6
7/// Register sqlite-vec GLOBALLY before any connection is opened.
8/// Must be called once at program start.
9pub fn register_vec_extension() {
10    #[allow(clippy::missing_transmute_annotations)]
11    unsafe {
12        rusqlite::ffi::sqlite3_auto_extension(Some(std::mem::transmute(
13            sqlite3_vec_init as *const (),
14        )));
15    }
16}
17
18pub fn open_rw(path: &Path) -> Result<Connection, AppError> {
19    let conn = Connection::open(path)?;
20    apply_connection_pragmas(&conn)?;
21    apply_secure_permissions(path);
22    Ok(conn)
23}
24
25/// Aplica permissões 600 (owner read/write only) ao arquivo SQLite e aos arquivos WAL/SHM
26/// associados no Unix para evitar vazamento de memórias privadas em diretórios compartilhados
27/// (ex: /tmp multi-user, Dropbox, NFS). No-op em Windows. Falhas silenciosas para não
28/// bloquear operação quando o processo não é o dono do arquivo (ex: montagem read-only).
29#[allow(unused_variables)]
30fn apply_secure_permissions(path: &Path) {
31    #[cfg(unix)]
32    {
33        use std::os::unix::fs::PermissionsExt;
34        let candidates = [
35            path.to_path_buf(),
36            path.with_extension(format!(
37                "{}-wal",
38                path.extension()
39                    .and_then(|e| e.to_str())
40                    .unwrap_or("sqlite")
41            )),
42            path.with_extension(format!(
43                "{}-shm",
44                path.extension()
45                    .and_then(|e| e.to_str())
46                    .unwrap_or("sqlite")
47            )),
48        ];
49        for file in candidates.iter() {
50            if file.exists() {
51                if let Ok(meta) = std::fs::metadata(file) {
52                    let mut perms = meta.permissions();
53                    perms.set_mode(0o600);
54                    let _ = std::fs::set_permissions(file, perms);
55                }
56            }
57        }
58    }
59}
60
61pub fn open_ro(path: &Path) -> Result<Connection, AppError> {
62    let conn = Connection::open_with_flags(
63        path,
64        rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY | rusqlite::OpenFlags::SQLITE_OPEN_URI,
65    )?;
66    conn.execute_batch("PRAGMA foreign_keys = ON;")?;
67    Ok(conn)
68}