summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-01-15 18:24:56 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2021-01-15 20:14:34 -0500
commitc5b4af959e13f8214121f62f322c668bb178d41f (patch)
tree7369dfbf35c7005ec2cfcf965f77a42d4ed98671 /lib/sqlalchemy/orm/session.py
parent5be3c030b321ecc342bf4cd84cbb0838efacd155 (diff)
downloadsqlalchemy-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.py12
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):