diff --git a/docs/peewee/database.rst b/docs/peewee/database.rst index 5dc3c5c5e..db12e5d8d 100644 --- a/docs/peewee/database.rst +++ b/docs/peewee/database.rst @@ -1656,8 +1656,11 @@ block. When this happens, a new transaction will be started. .. note:: If you attempt to nest transactions with peewee using the :py:meth:`~Database.transaction` context manager, only the outer-most - transaction will be used. However if an exception occurs in a nested block, - this can lead to unpredictable behavior, so it is strongly recommended that + transaction will be used. If an exception occurs in a nested block, the + transaction will NOT be rolled-back -- only exceptions that bubble-up to + the outer-most transaction will trigger a rollback. + + As this can may lead to unpredictable behavior, it is recommended that you use :py:meth:`~Database.atomic`. Explicit Savepoints diff --git a/peewee.py b/peewee.py index d58629bd5..0f3a37450 100644 --- a/peewee.py +++ b/peewee.py @@ -4405,10 +4405,11 @@ def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): + depth = self.db.transaction_depth() try: - if exc_type: + if exc_type and depth == 1: self.rollback(False) - elif self.db.transaction_depth() == 1: + elif depth == 1: try: self.commit(False) except: diff --git a/tests/transactions.py b/tests/transactions.py index 8ff012908..4eeec813b 100644 --- a/tests/transactions.py +++ b/tests/transactions.py @@ -139,6 +139,17 @@ def test_nesting_transaction_obj(self): self.assertRegister([3, 4, 5]) + with db.transaction() as txn: + self._save(6) + try: + with db.transaction() as txn2: + self._save(7) + raise ValueError() + except ValueError: + pass + + self.assertRegister([3, 4, 5, 6, 7]) + @requires_nested def test_savepoint_commit(self): with db.atomic() as txn: