@@ -3,7 +3,7 @@ use sqlite_loadable::ext::{
33 sqlite3ext_bind_text, sqlite3ext_finalize, sqlite3ext_prepare_v2, sqlite3ext_step,
44} ;
55use sqlite_loadable:: { Error , Result , SQLITE_DONE , SQLITE_OKAY , SQLITE_ROW } ;
6- use std:: ffi:: CString ;
6+ use std:: ffi:: { CStr , CString } ;
77use std:: os:: raw:: { c_char, c_void} ;
88use std:: time:: { SystemTime , UNIX_EPOCH } ;
99
@@ -174,3 +174,40 @@ pub fn now_ms_from_db(db: *mut sqlite3) -> i64 {
174174
175175 now_ms ( )
176176}
177+
178+ pub fn ensure_wal_journal_mode ( db : * mut sqlite3 ) -> Result < ( ) > {
179+ let mut stmt = sqlite_loadable:: exec:: Statement :: prepare ( db, "pragma journal_mode=WAL" )
180+ . map_err ( |err| Error :: new_message ( format ! ( "failed to enable WAL mode: {:?}" , err) ) ) ?;
181+ let mut rows = stmt. execute ( ) ;
182+ let row = match rows. next ( ) {
183+ Some ( Ok ( row) ) => row,
184+ _ => {
185+ return Err ( Error :: new_message (
186+ "failed to read journal_mode after enabling WAL" ,
187+ ) )
188+ }
189+ } ;
190+ let mode = row
191+ . get :: < String > ( 0 )
192+ . map_err ( |err| Error :: new_message ( format ! ( "failed to read journal_mode: {:?}" , err) ) ) ?;
193+ if mode. eq_ignore_ascii_case ( "wal" ) || db_is_in_memory ( db) {
194+ return Ok ( ( ) ) ;
195+ }
196+ Err ( Error :: new_message ( format ! (
197+ "expected journal_mode to be WAL, found {}" ,
198+ mode
199+ ) ) )
200+ }
201+
202+ fn db_is_in_memory ( db : * mut sqlite3 ) -> bool {
203+ let main = CString :: new ( "main" ) . unwrap ( ) ;
204+ let filename_ptr = unsafe { sqlite3ext_sys:: sqlite3_db_filename ( db, main. as_ptr ( ) ) } ;
205+ if filename_ptr. is_null ( ) {
206+ return true ;
207+ }
208+ let filename = unsafe { CStr :: from_ptr ( filename_ptr) }
209+ . to_string_lossy ( )
210+ . into_owned ( ) ;
211+ let trimmed = filename. trim ( ) ;
212+ trimmed. is_empty ( ) || trimmed == ":memory:"
213+ }
0 commit comments