@@ -332,6 +332,8 @@ impl std::error::Error for ConnectionPolicyError {
332332}
333333
334334pub ( crate ) fn open ( path : & Path , mode : ConnectionMode ) -> Result < Connection , ConnectionPolicyError > {
335+ let fresh_writer = mode == ConnectionMode :: Writer
336+ && std:: fs:: metadata ( path) . is_ok_and ( |metadata| metadata. len ( ) == 0 ) ;
335337 let flags = match mode {
336338 ConnectionMode :: Reader => OpenFlags :: SQLITE_OPEN_READ_ONLY ,
337339 ConnectionMode :: Writer | ConnectionMode :: Maintenance => OpenFlags :: SQLITE_OPEN_READ_WRITE ,
@@ -340,7 +342,7 @@ pub(crate) fn open(path: &Path, mode: ConnectionMode) -> Result<Connection, Conn
340342 let connection =
341343 Connection :: open_with_flags ( path, flags) . map_err ( |source| policy ( "open" , source) ) ?;
342344
343- apply_pragmas ( & connection, mode) ?;
345+ apply_pragmas ( & connection, mode, fresh_writer ) ?;
344346 assert_compile_options ( & connection) ?;
345347 apply_limits ( & connection, mode) ?;
346348 install_authorizer ( & connection, mode) ?;
@@ -362,7 +364,7 @@ pub fn open_immutable_reader(path: &Path) -> Result<Connection, ConnectionPolicy
362364 | OpenFlags :: SQLITE_OPEN_PRIVATE_CACHE ;
363365 let connection =
364366 Connection :: open_with_flags ( uri, flags) . map_err ( |source| policy ( "open" , source) ) ?;
365- apply_pragmas ( & connection, ConnectionMode :: Reader ) ?;
367+ apply_pragmas ( & connection, ConnectionMode :: Reader , false ) ?;
366368 assert_compile_options ( & connection) ?;
367369 apply_limits ( & connection, ConnectionMode :: Reader ) ?;
368370 install_authorizer ( & connection, ConnectionMode :: Reader ) ?;
@@ -396,6 +398,7 @@ fn immutable_health_uri(path: &Path) -> Result<String, ConnectionPolicyError> {
396398fn apply_pragmas (
397399 connection : & Connection ,
398400 mode : ConnectionMode ,
401+ fresh_writer : bool ,
399402) -> Result < ( ) , ConnectionPolicyError > {
400403 // SQLite must never wait past the runtime's own queue/deadline authority.
401404 connection
@@ -409,6 +412,12 @@ fn apply_pragmas(
409412 . map_err ( |source| policy ( "trusted schema" , source) ) ?;
410413
411414 if mode == ConnectionMode :: Writer {
415+ if fresh_writer {
416+ connection
417+ . pragma_update ( None , "auto_vacuum" , "INCREMENTAL" )
418+ . map_err ( |source| policy ( "fresh auto-vacuum" , source) ) ?;
419+ verify_pragma_i64 ( connection, "auto_vacuum" , 2 ) ?;
420+ }
412421 connection
413422 . pragma_update ( None , "journal_mode" , "WAL" )
414423 . map_err ( |source| policy ( "WAL journal" , source) ) ?;
@@ -578,6 +587,13 @@ fn is_read_only_introspection_pragma(pragma_name: &str) -> bool {
578587 . any ( |candidate| pragma_name. eq_ignore_ascii_case ( candidate) )
579588}
580589
590+ fn is_safe_writer_pragma ( pragma_name : & str , pragma_value : & str ) -> bool {
591+ pragma_name. eq_ignore_ascii_case ( "wal_autocheckpoint" )
592+ || pragma_name. eq_ignore_ascii_case ( "wal_checkpoint" )
593+ || ( pragma_name. eq_ignore_ascii_case ( "auto_vacuum" )
594+ && ( pragma_value. eq_ignore_ascii_case ( "incremental" ) || pragma_value == "2" ) )
595+ }
596+
581597fn authorize ( mode : ConnectionMode , context : AuthContext < ' _ > ) -> Authorization {
582598 if mode == ConnectionMode :: Maintenance {
583599 return Authorization :: Allow ;
@@ -613,12 +629,11 @@ fn authorize(mode: ConnectionMode, context: AuthContext<'_>) -> Authorization {
613629 context. action,
614630 AuthAction :: Pragma {
615631 pragma_name,
616- pragma_value: Some ( _ ) ,
632+ pragma_value: Some ( pragma_value ) ,
617633 }
618634 if !is_read_only_introspection_pragma( pragma_name)
619635 && ( mode != ConnectionMode :: Writer
620- || ( !pragma_name. eq_ignore_ascii_case( "wal_autocheckpoint" )
621- && !pragma_name. eq_ignore_ascii_case( "wal_checkpoint" ) ) )
636+ || !is_safe_writer_pragma( pragma_name, pragma_value) )
622637 )
623638 || ( mode == ConnectionMode :: Reader
624639 && matches ! (
0 commit comments