mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-07-23 01:14:31 +02:00
enable_wal() and disable_wal() refuse to run inside a transaction
Changing the journal mode assigns conn.isolation_level, which commits any open transaction as a side effect - silently breaking the rollback guarantee of atomic() blocks and of user-managed transactions. Both methods now raise RuntimeError if a transaction is open. Calling them when the database is already in the requested mode remains a no-op. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UnLnhsH25Nnv7LHhekUfPd
This commit is contained in:
parent
d6753a9f57
commit
ffec11cfb7
4 changed files with 59 additions and 1 deletions
|
|
@ -854,17 +854,36 @@ class Database:
|
|||
def enable_wal(self) -> None:
|
||||
"""
|
||||
Sets ``journal_mode`` to ``'wal'`` to enable Write-Ahead Log mode.
|
||||
|
||||
:raises RuntimeError: if called while a transaction is open - the
|
||||
journal mode can only be changed outside of a transaction
|
||||
"""
|
||||
if self.journal_mode != "wal":
|
||||
self._ensure_no_open_transaction("enable_wal()")
|
||||
with self.ensure_autocommit_off():
|
||||
self.execute("PRAGMA journal_mode=wal;")
|
||||
|
||||
def disable_wal(self) -> None:
|
||||
"Sets ``journal_mode`` back to ``'delete'`` to disable Write-Ahead Log mode."
|
||||
"""
|
||||
Sets ``journal_mode`` back to ``'delete'`` to disable Write-Ahead Log mode.
|
||||
|
||||
:raises RuntimeError: if called while a transaction is open - the
|
||||
journal mode can only be changed outside of a transaction
|
||||
"""
|
||||
if self.journal_mode != "delete":
|
||||
self._ensure_no_open_transaction("disable_wal()")
|
||||
with self.ensure_autocommit_off():
|
||||
self.execute("PRAGMA journal_mode=delete;")
|
||||
|
||||
def _ensure_no_open_transaction(self, operation: str) -> None:
|
||||
# Changing journal mode assigns conn.isolation_level, which commits
|
||||
# any open transaction as a side effect - breaking the rollback
|
||||
# guarantee of atomic() and of user-managed transactions
|
||||
if self.conn.in_transaction:
|
||||
raise RuntimeError(
|
||||
"{} cannot be used while a transaction is open".format(operation)
|
||||
)
|
||||
|
||||
def _ensure_counts_table(self) -> None:
|
||||
with self.atomic():
|
||||
self.execute(_COUNTS_TABLE_CREATE_SQL.format(self._counts_table_name))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue