mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-07-22 17:04:31 +02:00
Rename ensure_autocommit_off() to ensure_autocommit_on(), closes #705
This commit is contained in:
parent
02281f77ed
commit
50938ee6f8
4 changed files with 27 additions and 7 deletions
|
|
@ -13,6 +13,7 @@ Breaking changes:
|
|||
|
||||
- ``table.foreign_keys`` now returns ``ForeignKey`` objects that are dataclasses rather than ``namedtuple`` instances, so they can no longer be unpacked or indexed as ``(table, column, other_table, other_column)`` tuples - access their fields by name instead. Compound (multi-column) foreign keys are now represented as a single ``ForeignKey`` with ``is_compound=True`` and populated ``columns``/``other_columns`` tuples, where ``column`` and ``other_column`` are ``None``. Previously they were returned as one ``ForeignKey`` per column, misleadingly suggesting several independent foreign keys. See :ref:`upgrading_3_to_4` for details. (:issue:`594`)
|
||||
- Removed support for using ``sqlean.py`` as a drop-in replacement for the Python standard library ``sqlite3`` module. ``sqlite-utils`` will now use ``pysqlite3`` if it is installed, otherwise it will use ``sqlite3`` from the standard library.
|
||||
- The ``db.ensure_autocommit_off()`` context manager has been renamed to ``db.ensure_autocommit_on()``, because the old name described the opposite of what it did. The method temporarily puts the connection into driver-level autocommit mode - by setting ``isolation_level = None`` - so that statements such as ``PRAGMA journal_mode=wal`` can run outside of an implicit transaction. (:issue:`705`)
|
||||
|
||||
Compound foreign key support:
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ Python API changes
|
|||
|
||||
**table.convert() no longer skips falsey values.** Matching the CLI change above, ``table.convert()`` now converts every value. The ``skip_false`` parameter has been removed - previously it defaulted to ``True``, skipping empty strings and other falsey values.
|
||||
|
||||
**ensure_autocommit_off() is now ensure_autocommit_on().** The ``db.ensure_autocommit_off()`` context manager has been renamed to ``db.ensure_autocommit_on()``. The old name described the opposite of what the method did: it temporarily puts the connection into driver-level autocommit mode (by setting ``isolation_level = None``), so that statements such as ``PRAGMA journal_mode=wal`` can run outside of an implicit transaction. The behavior is unchanged - update any calls to use the new name.
|
||||
|
||||
**View.enable_fts() has been removed.** The ``View`` class previously had an ``enable_fts()`` method that existed only to raise ``NotImplementedError`` - full-text search is not supported for views. Calling it now raises ``AttributeError`` like any other missing method.
|
||||
|
||||
**ForeignKey is now a dataclass, not a namedtuple.** The ``ForeignKey`` objects returned by ``table.foreign_keys`` gained new fields - ``columns``, ``other_columns``, ``is_compound``, ``on_delete`` and ``on_update`` - so that compound (multi-column) foreign keys and foreign key actions can be represented. To make room for those fields cleanly ``ForeignKey`` is now a dataclass rather than a ``namedtuple``, so it can no longer be unpacked or indexed as a tuple. Access its fields by name instead:
|
||||
|
|
|
|||
|
|
@ -610,16 +610,22 @@ class Database:
|
|||
self.conn.execute("ROLLBACK")
|
||||
|
||||
@contextlib.contextmanager
|
||||
def ensure_autocommit_off(self) -> Generator[None, None, None]:
|
||||
def ensure_autocommit_on(self) -> Generator[None, None, None]:
|
||||
"""
|
||||
Ensure autocommit is off for this database connection.
|
||||
Ensure the connection is in driver-level autocommit mode for the
|
||||
duration of a block of code.
|
||||
|
||||
This temporarily sets ``isolation_level = None`` on the underlying
|
||||
``sqlite3`` connection, so the driver does not open implicit
|
||||
transactions. This is useful for statements such as
|
||||
``PRAGMA journal_mode=wal`` which cannot run inside a transaction.
|
||||
|
||||
Example usage::
|
||||
|
||||
with db.ensure_autocommit_off():
|
||||
with db.ensure_autocommit_on():
|
||||
# do stuff here
|
||||
|
||||
This will reset to the previous autocommit state at the end of the block.
|
||||
The previous ``isolation_level`` is restored at the end of the block.
|
||||
"""
|
||||
old_isolation_level = self.conn.isolation_level
|
||||
try:
|
||||
|
|
@ -783,7 +789,7 @@ class Database:
|
|||
if self.conn.in_transaction:
|
||||
cursor = self.conn.execute(sql, *args)
|
||||
else:
|
||||
with self.ensure_autocommit_off():
|
||||
with self.ensure_autocommit_on():
|
||||
cursor = self.conn.execute(sql, *args)
|
||||
if cursor.description is None:
|
||||
raise ValueError(message)
|
||||
|
|
@ -1085,7 +1091,7 @@ class Database:
|
|||
"""
|
||||
if self.journal_mode != "wal":
|
||||
self._ensure_no_open_transaction("enable_wal()")
|
||||
with self.ensure_autocommit_off():
|
||||
with self.ensure_autocommit_on():
|
||||
self.execute("PRAGMA journal_mode=wal;")
|
||||
|
||||
def disable_wal(self) -> None:
|
||||
|
|
@ -1097,7 +1103,7 @@ class Database:
|
|||
"""
|
||||
if self.journal_mode != "delete":
|
||||
self._ensure_no_open_transaction("disable_wal()")
|
||||
with self.ensure_autocommit_off():
|
||||
with self.ensure_autocommit_on():
|
||||
self.execute("PRAGMA journal_mode=delete;")
|
||||
|
||||
def _ensure_no_open_transaction(self, operation: str) -> None:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,17 @@ def test_disable_wal_inside_transaction_raises(db_path_tmpdir):
|
|||
assert [r["id"] for r in db["test"].rows] == [1]
|
||||
|
||||
|
||||
def test_ensure_autocommit_on(db_path_tmpdir):
|
||||
db, path, tmpdir = db_path_tmpdir
|
||||
previous_isolation_level = db.conn.isolation_level
|
||||
assert previous_isolation_level is not None
|
||||
with db.ensure_autocommit_on():
|
||||
# isolation_level of None means driver-level autocommit mode
|
||||
assert db.conn.isolation_level is None
|
||||
# Restored afterwards
|
||||
assert db.conn.isolation_level == previous_isolation_level
|
||||
|
||||
|
||||
def test_enable_wal_noop_inside_transaction_is_allowed(db_path_tmpdir):
|
||||
# Calling enable_wal() when WAL is already enabled is a no-op,
|
||||
# so it is fine inside a transaction
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue