Skip to main content

sqlite_graphrag/
pragmas.rs

1//! SQLite PRAGMA helpers applied at connection open and on each transaction.
2
3use crate::errors::AppError;
4use rusqlite::Connection;
5
6/// Applies one-time PRAGMAs on a freshly opened connection (e.g. `auto_vacuum`).
7///
8/// Calls [`apply_connection_pragmas`] internally and then sets `wal_autocheckpoint`.
9/// Must be called once per database file, not once per connection.
10///
11/// # Errors
12/// Returns `Err` when any PRAGMA execution fails.
13pub fn apply_init_pragmas(conn: &Connection) -> Result<(), AppError> {
14    conn.execute_batch("PRAGMA auto_vacuum = INCREMENTAL;")?;
15    apply_connection_pragmas(conn)?;
16    conn.execute_batch(&format!(
17        "PRAGMA wal_autocheckpoint = {};",
18        crate::constants::WAL_AUTOCHECKPOINT_PAGES
19    ))?;
20    Ok(())
21}
22
23/// Re-asserts `PRAGMA journal_mode = WAL` after operations that may revert it
24/// (notably refinery-driven migrations, which can open internal handles that
25/// reset the journal mode in some scenarios). Idempotent and cheap; emits
26/// `tracing::warn!` if WAL fails to engage so degraded behaviour is observable.
27pub fn ensure_wal_mode(conn: &Connection) -> Result<(), AppError> {
28    let mode: String = conn.query_row("PRAGMA journal_mode = WAL;", [], |r| r.get(0))?;
29    if mode != "wal" {
30        tracing::warn!(mode = %mode, "journal_mode did not switch to WAL after re-assertion");
31    }
32    Ok(())
33}
34
35/// Applies per-connection PRAGMAs: synchronous, foreign keys, busy timeout, cache, mmap, WAL.
36///
37/// Safe to call on every new connection; all settings are idempotent.
38///
39/// # Errors
40/// Returns `Err` when any PRAGMA execution fails.
41pub fn apply_connection_pragmas(conn: &Connection) -> Result<(), AppError> {
42    conn.execute_batch(&format!(
43        "PRAGMA synchronous   = NORMAL;
44         PRAGMA foreign_keys  = ON;
45         PRAGMA busy_timeout  = {busy};
46         PRAGMA cache_size    = {cache};
47         PRAGMA temp_store    = MEMORY;
48         PRAGMA mmap_size     = {mmap};",
49        busy = crate::constants::BUSY_TIMEOUT_MILLIS,
50        cache = crate::constants::CACHE_SIZE_KB,
51        mmap = crate::constants::MMAP_SIZE_BYTES,
52    ))?;
53    let mode: String = conn.query_row("PRAGMA journal_mode = WAL;", [], |r| r.get(0))?;
54    if mode != "wal" {
55        tracing::warn!(mode = %mode, "journal_mode did not switch to WAL");
56    }
57    Ok(())
58}