summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-02-25 19:27:07 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2013-02-25 19:27:07 -0500
commit07cc4ecf05aeb746a54ce51671d7a4b2669141e2 (patch)
tree45d320b5157083f0e8d6d927f36bf796b48d16a7 /lib/sqlalchemy/orm/session.py
parent95297c35442e483bb98b5a4edb677bb168064f5e (diff)
downloadsqlalchemy-07cc4ecf05aeb746a54ce51671d7a4b2669141e2.tar.gz
- A clear error message is emitted if an event handler
attempts to emit SQL on a Session within the after_commit() handler, where there is not a viable transaction in progress. [ticket:2662] - rework how SessionTransaction maintains state, using symbols instead. - add lots of notes and cross-linking for session events. - add a link to :func:`.select()` within :meth:`.FromClause.select`.
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r--lib/sqlalchemy/orm/session.py33
1 files changed, 19 insertions, 14 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 2915fd4c8..5fb9b514d 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -57,6 +57,10 @@ class _SessionClassMethods(object):
return object_session(instance)
+ACTIVE = util.symbol('ACTIVE')
+PREPARED = util.symbol('PREPARED')
+DEACTIVE = util.symbol('DEACTIVE')
+
class SessionTransaction(object):
"""A :class:`.Session`-level transaction.
@@ -144,8 +148,7 @@ class SessionTransaction(object):
self._connections = {}
self._parent = parent
self.nested = nested
- self._active = True
- self._prepared = False
+ self._state = ACTIVE
if not parent and nested:
raise sa_exc.InvalidRequestError(
"Can't start a SAVEPOINT transaction when no existing "
@@ -159,11 +162,17 @@ class SessionTransaction(object):
@property
def is_active(self):
- return self.session is not None and self._active
+ return self.session is not None and self._state is ACTIVE
def _assert_is_active(self):
self._assert_is_open()
- if not self._active:
+ if self._state is PREPARED:
+ raise sa_exc.InvalidRequestError(
+ "This session is in 'prepared' state, where no further "
+ "SQL can be emitted until the transaction is fully "
+ "committed."
+ )
+ elif self._state is DEACTIVE:
if self._rollback_exception:
raise sa_exc.InvalidRequestError(
"This Session's transaction has been rolled back "
@@ -327,12 +336,11 @@ class SessionTransaction(object):
self.rollback()
raise
- self._deactivate()
- self._prepared = True
+ self._state = PREPARED
def commit(self):
self._assert_is_open()
- if not self._prepared:
+ if self._state is not PREPARED:
self._prepare_impl()
if self._parent is None or self.nested:
@@ -355,14 +363,14 @@ class SessionTransaction(object):
for subtransaction in stx._iterate_parents(upto=self):
subtransaction.close()
- if self.is_active or self._prepared:
+ if self._state in (ACTIVE, PREPARED):
for transaction in self._iterate_parents():
if transaction._parent is None or transaction.nested:
transaction._rollback_impl()
- transaction._deactivate()
+ transaction._state = DEACTIVE
break
else:
- transaction._deactivate()
+ transaction._state = DEACTIVE
sess = self.session
@@ -393,9 +401,6 @@ class SessionTransaction(object):
self.session.dispatch.after_rollback(self.session)
- def _deactivate(self):
- self._active = False
-
def close(self):
self.session.transaction = self._parent
if self._parent is None:
@@ -406,7 +411,7 @@ class SessionTransaction(object):
else:
transaction.close()
- self._deactivate()
+ self._state = DEACTIVE
if self.session.dispatch.after_transaction_end:
self.session.dispatch.after_transaction_end(self.session, self)