diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-01-15 18:24:56 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-01-15 20:14:34 -0500 |
commit | c5b4af959e13f8214121f62f322c668bb178d41f (patch) | |
tree | 7369dfbf35c7005ec2cfcf965f77a42d4ed98671 /lib/sqlalchemy/orm/session.py | |
parent | 5be3c030b321ecc342bf4cd84cbb0838efacd155 (diff) | |
download | sqlalchemy-c5b4af959e13f8214121f62f322c668bb178d41f.tar.gz |
Guard against re-entrant autobegin in Core, ORM
Fixed bug in "future" version of :class:`.Engine` where emitting SQL during
the :meth:`.EngineEvents.do_begin` event hook would cause a re-entrant
condition due to autobegin, including the recipe documented for SQLite to
allow for savepoints and serializable isolation support.
Fixed issue in new :class:`_orm.Session` similar to that of the
:class:`_engine.Connection` where the new "autobegin" logic could be
tripped into a re-entrant state if SQL were executed within the
:meth:`.SessionEvents.after_transaction_create` event hook.
Also repair the new "testing_engine" pytest fixture to
set up for "future" engine appropriately, which wasn't working
leading to the test_execute.py tests not using the future
engine since recent f1e96cb0874927a475d0c11139.
Fixes: #5845
Change-Id: Ib2432d8c8bd753e24be60720ec47affb2df15a4a
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r-- | lib/sqlalchemy/orm/session.py | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index e8312f393..8a7a64f78 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -531,6 +531,10 @@ class SessionTransaction(object): self._take_snapshot(autobegin=autobegin) + # make sure transaction is assigned before we call the + # dispatch + self.session._transaction = self + self.session.dispatch.after_transaction_create(self.session, self) @property @@ -1242,7 +1246,8 @@ class Session(_SessionClassMethods): def _autobegin(self): if not self.autocommit and self._transaction is None: - self._transaction = SessionTransaction(self, autobegin=True) + trans = SessionTransaction(self, autobegin=True) + assert self._transaction is trans return True return False @@ -1299,7 +1304,7 @@ class Session(_SessionClassMethods): if self._transaction is not None: if subtransactions or _subtrans or nested: trans = self._transaction._begin(nested=nested) - self._transaction = trans + assert self._transaction is trans if nested: self._nested_transaction = trans else: @@ -1307,7 +1312,8 @@ class Session(_SessionClassMethods): "A transaction is already begun on this Session." ) else: - self._transaction = SessionTransaction(self, nested=nested) + trans = SessionTransaction(self, nested=nested) + assert self._transaction is trans return self._transaction # needed for __enter__/__exit__ hook def begin_nested(self): |