From 827af37d681b61de1300d7dacc5c50ff23a4fbf9 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 14 Mar 2021 12:28:46 -0400 Subject: [PATCH] Document NestedTransaction Fixes: #3550 Change-Id: Ic2ff36ea434923590d2adbd101580025da319f66 --- doc/build/core/connections.rst | 6 +++ doc/build/orm/session_transaction.rst | 6 +++ lib/sqlalchemy/engine/base.py | 73 +++++++++++++++++++++++++-- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/doc/build/core/connections.rst b/doc/build/core/connections.rst index 7d90d1cae0..17fca63bfe 100644 --- a/doc/build/core/connections.rst +++ b/doc/build/core/connections.rst @@ -1804,12 +1804,18 @@ Connection / Engine API .. autoclass:: NestedTransaction :members: + :inherited-members: + +.. autoclass:: RootTransaction + :members: + :inherited-members: .. autoclass:: Transaction :members: .. autoclass:: TwoPhaseTransaction :members: + :inherited-members: Result Set API diff --git a/doc/build/orm/session_transaction.rst b/doc/build/orm/session_transaction.rst index 7daa47ef74..1deefc8df3 100644 --- a/doc/build/orm/session_transaction.rst +++ b/doc/build/orm/session_transaction.rst @@ -171,6 +171,12 @@ session is expired, thus causing all subsequent attribute/instance access to reference the full state of the :class:`~sqlalchemy.orm.session.Session` right before :meth:`~.Session.begin_nested` was called. +.. seealso:: + + :class:`_engine.NestedTransaction` - the :class:`.NestedTransaction` class is the + Core-level construct that is used by the :class:`_orm.Session` internally + to produce SAVEPOINT blocks. + .. _orm_session_vs_engine: Session-level vs. Engine level transaction control diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 362c811eeb..906de08bb4 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -2211,14 +2211,43 @@ class Transaction(object): assert not self.is_active def rollback(self): - """Roll back this :class:`.Transaction`.""" + """Roll back this :class:`.Transaction`. + + The implementation of this may vary based on the type of transaction in + use: + + * For a simple database transaction (e.g. :class:`.RootTransaction`), + it corresponds to a ROLLBACK. + + * For a :class:`.NestedTransaction`, it corresponds to a + "ROLLBACK TO SAVEPOINT" operation. + + * For a :class:`.TwoPhaseTransaction`, DBAPI-specific methods for two + phase transactions may be used. + + + """ try: self._do_rollback() finally: assert not self.is_active def commit(self): - """Commit this :class:`.Transaction`.""" + """Commit this :class:`.Transaction`. + + The implementation of this may vary based on the type of transaction in + use: + + * For a simple database transaction (e.g. :class:`.RootTransaction`), + it corresponds to a COMMIT. + + * For a :class:`.NestedTransaction`, it corresponds to a + "RELEASE SAVEPOINT" operation. + + * For a :class:`.TwoPhaseTransaction`, DBAPI-specific methods for two + phase transactions may be used. + + """ try: self._do_commit() @@ -2296,6 +2325,18 @@ class MarkerTransaction(Transaction): class RootTransaction(Transaction): + """Represent the "root" transaction on a :class:`_engine.Connection`. + + This corresponds to the current "BEGIN/COMMIT/ROLLBACK" that's occurring + for the :class:`_engine.Connection`. + + The :class:`_engine.RootTransaction` object is accessible via the + :attr:`_engine.Connection.get_transaction` method of + :class:`_engine.Connection`. + + + """ + _is_root = True __slots__ = ("connection", "is_active") @@ -2400,10 +2441,32 @@ class RootTransaction(Transaction): class NestedTransaction(Transaction): """Represent a 'nested', or SAVEPOINT transaction. - A new :class:`.NestedTransaction` object may be procured - using the :meth:`_engine.Connection.begin_nested` method. + The :class:`.NestedTransaction` object is created by calling the + :meth:`_engine.Connection.begin_nested` method of + :class:`_engine.Connection`. + + When using :class:`.NestedTransaction`, the semantics of "begin" / + "commit" / "rollback" are as follows: + + * the "begin" operation corresponds to the "BEGIN SAVEPOINT" command, where + the savepoint is given an explicit name that is part of the state + of this object. + + * The :meth:`.NestedTransaction.commit` method corresponds to a + "RELEASE SAVEPOINT" operation, using the savepoint identifier associated + with this :class:`.NestedTransaction`. + + * The :meth:`.NestedTransaction.rollback` method corresponds to a + "ROLLBACK TO SAVEPOINT" operation, using the savepoint identifier + associated with this :class:`.NestedTransaction`. + + The rationale for mimicking the semantics of an outer transaction in + terms of savepoints so that code may deal with a "savepoint" transaction + and an "outer" transaction in an agnostic way. + + .. seealso:: - The interface is the same as that of :class:`.Transaction`. + :ref:`session_begin_nested` - ORM version of the SAVEPOINT API. """ -- 2.47.2