summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-02-04 17:07:15 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2015-02-04 18:35:01 -0500
commit9cbe235810b7c0c24d2556b4bb581b0207812e2d (patch)
treea842ee456f9d6ce69db3676d19e8428df35acb05 /lib/sqlalchemy/orm/session.py
parent9ea19b374630e6ae14cb144942007aa0f8686583 (diff)
downloadsqlalchemy-9cbe235810b7c0c24d2556b4bb581b0207812e2d.tar.gz
- A warning is emitted if the ``isolation_level`` parameter is used
with :meth:`.Connection.execution_options` when a :class:`.Transaction` is in play; DBAPIs and/or SQLAlchemy dialects such as psycopg2, MySQLdb may implicitly rollback or commit the transaction, or not change the setting til next transaction, so this is never safe. - Added new parameter :paramref:`.Session.connection.execution_options` which may be used to set up execution options on a :class:`.Connection` when it is first checked out, before the transaction has begun. This is used to set up options such as isolation level on the connection before the transaction starts. - added new documentation section detailing best practices for setting transaction isolation with sessions. fixes #3296
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r--lib/sqlalchemy/orm/session.py41
1 files changed, 33 insertions, 8 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 0e272dc95..3df6dce7a 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -226,10 +226,10 @@ class SessionTransaction(object):
def _is_transaction_boundary(self):
return self.nested or not self._parent
- def connection(self, bindkey, **kwargs):
+ def connection(self, bindkey, execution_options=None, **kwargs):
self._assert_active()
bind = self.session.get_bind(bindkey, **kwargs)
- return self._connection_for_bind(bind)
+ return self._connection_for_bind(bind, execution_options)
def _begin(self, nested=False):
self._assert_active()
@@ -301,14 +301,18 @@ class SessionTransaction(object):
self._parent._deleted.update(self._deleted)
self._parent._key_switches.update(self._key_switches)
- def _connection_for_bind(self, bind):
+ def _connection_for_bind(self, bind, execution_options):
self._assert_active()
if bind in self._connections:
+ if execution_options:
+ util.warn(
+ "Connection is already established for the "
+ "given bind; execution_options ignored")
return self._connections[bind][0]
if self._parent:
- conn = self._parent._connection_for_bind(bind)
+ conn = self._parent._connection_for_bind(bind, execution_options)
if not self.nested:
return conn
else:
@@ -321,6 +325,9 @@ class SessionTransaction(object):
else:
conn = bind.contextual_connect()
+ if execution_options:
+ conn = conn.execution_options(**execution_options)
+
if self.session.twophase and self._parent is None:
transaction = conn.begin_twophase()
elif self.nested:
@@ -793,6 +800,7 @@ class Session(_SessionClassMethods):
def connection(self, mapper=None, clause=None,
bind=None,
close_with_result=False,
+ execution_options=None,
**kw):
"""Return a :class:`.Connection` object corresponding to this
:class:`.Session` object's transactional state.
@@ -837,6 +845,18 @@ class Session(_SessionClassMethods):
configured with ``autocommit=True`` and does not already have a
transaction in progress.
+ :param execution_options: a dictionary of execution options that will
+ be passed to :meth:`.Connection.execution_options`, **when the
+ connection is first procured only**. If the connection is already
+ present within the :class:`.Session`, a warning is emitted and
+ the arguments are ignored.
+
+ .. versionadded:: 0.9.9
+
+ .. seealso::
+
+ :ref:`session_transaction_isolation`
+
:param \**kw:
Additional keyword arguments are sent to :meth:`get_bind()`,
allowing additional arguments to be passed to custom
@@ -847,13 +867,18 @@ class Session(_SessionClassMethods):
bind = self.get_bind(mapper, clause=clause, **kw)
return self._connection_for_bind(bind,
- close_with_result=close_with_result)
+ close_with_result=close_with_result,
+ execution_options=execution_options)
- def _connection_for_bind(self, engine, **kwargs):
+ def _connection_for_bind(self, engine, execution_options=None, **kw):
if self.transaction is not None:
- return self.transaction._connection_for_bind(engine)
+ return self.transaction._connection_for_bind(
+ engine, execution_options)
else:
- return engine.contextual_connect(**kwargs)
+ conn = engine.contextual_connect(**kw)
+ if execution_options:
+ conn = conn.execution_options(**execution_options)
+ return conn
def execute(self, clause, params=None, mapper=None, bind=None, **kw):
"""Execute a SQL expression construct or string statement within