//! Shared SQLite open policy, expanded against the plugin's own rusqlite version. /// Open SQLite under an already-held Sausage host lock. The caller must depend /// on `rusqlite` (bundled) and hold the SAME host lock for EVERY connection's /// entire lifetime, including reads and old/new plugin versions. This macro does /// not acquire the lock. Do not use it for the host journal or databases accessed /// outside Sausage. Native builds retain OS locks; WASI selects `unix-none`, so /// crash-leftover dotfile lock directories cannot block recovery. /// /// Temporary tables/sorts stay in memory before any schema access. Writable opens /// use DELETE journals; SQLite rolls back hot journals itself. Never delete a /// leftover journal. Read-only opens cannot recover a hot journal: recover with /// a writable open first. /// /// The flags form preserves the caller's open flags. A macro avoids coupling the /// SDK to a particular rusqlite/libsqlite3-sys version (the host and plugins use /// different versions, which cannot coexist as dependencies due to `links`). /// /// ```ignore /// let _guard = sausage_plugin::lock("/state/example/db.lock").await?; /// let c = sausage_plugin::sqlite_open!("/state/example/db.sqlite")?; /// // Query here; c must drop before _guard. /// ``` #[macro_export] macro_rules! sqlite_open { ($path:expr) => { $crate::sqlite_open!($path, ::rusqlite::OpenFlags::default()) }; ($path:expr, $flags:expr) => {{ (|| -> ::rusqlite::Result<::rusqlite::Connection> { let flags = $flags; #[cfg(target_os = "wasi")] let c = ::rusqlite::Connection::open_with_flags_and_vfs($path, flags, "unix-none")?; #[cfg(not(target_os = "wasi"))] let c = ::rusqlite::Connection::open_with_flags($path, flags)?; c.pragma_update(None, "temp_store", "MEMORY")?; if !flags.contains(::rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY) { c.pragma_update(None, "journal_mode", "DELETE")?; } Ok(c) })() }}; }