an 0.7 style count() query [ticket:2130].
(also in 0.6.7)
+ - the Query.execution_options() method now passes
+ those options to the Connection rather than
+ the SELECT statement, so that all available
+ options including isolation level and
+ compiled cache may be used. [ticket:2131]
+
- sql
+ - The "compiled_cache" execution option now raises
+ an error when passed to a SELECT statement
+ rather than a Connection. Previously it was
+ being ignored entirely. We may look into
+ having this option work on a per-statement
+ level at some point. [ticket:2131]
+
- Restored the "catchall" constructor on the base
TypeEngine class, with a deprecation warning.
This so that code which does something like
accepted by :meth:`.Executable.execution_options`. Additionally,
it includes options that are applicable only to
:class:`.Connection`.
+
+ :param autocommit: Available on: Connection, statement.
+ When True, a COMMIT will be invoked after execution
+ when executed in 'autocommit' mode, i.e. when an explicit
+ transaction is not begun on the connection. Note that DBAPI
+ connections by default are always in a transaction - SQLAlchemy uses
+ rules applied to different kinds of statements to determine if
+ COMMIT will be invoked in order to provide its "autocommit" feature.
+ Typically, all INSERT/UPDATE/DELETE statements as well as
+ CREATE/DROP statements have autocommit behavior enabled; SELECT
+ constructs do not. Use this option when invoking a SELECT or other
+ specific SQL construct where COMMIT is desired (typically when
+ calling stored procedures and such), and an explicit
+ transaction is not in progress.
+
+ :param compiled_cache: Available on: Connection.
+ A dictionary where :class:`.Compiled` objects
+ will be cached when the :class:`.Connection` compiles a clause
+ expression into a :class:`.Compiled` object.
+ It is the user's responsibility to
+ manage the size of this dictionary, which will have keys
+ corresponding to the dialect, clause element, the column
+ names within the VALUES or SET clause of an INSERT or UPDATE,
+ as well as the "batch" mode for an INSERT or UPDATE statement.
+ The format of this dictionary is not guaranteed to stay the
+ same in future releases.
+
+ Note that the ORM makes use of its own "compiled" caches for
+ some operations, including flush operations. The caching
+ used by the ORM internally supersedes a cache dictionary
+ specified here.
- :param isolation_level: Set the transaction isolation level for
+ :param isolation_level: Available on: Connection.
+ Set the transaction isolation level for
the lifespan of this connection. Valid values include
those string values accepted by the ``isolation_level``
parameter passed to :func:`.create_engine`, and are
is returned to the connection pool, i.e.
the :meth:`.Connection.close` method is called.
- :param \**kw: All options accepted by :meth:`.Executable.execution_options`
- are also accepted.
+ :param stream_results: Available on: Connection, statement.
+ Indicate to the dialect that results should be
+ "streamed" and not pre-buffered, if possible. This is a limitation
+ of many DBAPIs. The flag is currently understood only by the
+ psycopg2 dialect.
"""
c = self._clone()
""" Set non-SQL options which take effect during execution.
The options are the same as those accepted by
- :meth:`sqlalchemy.sql.expression.Executable.execution_options`.
+ :meth:`.Connection.execution_options`.
Note that the ``stream_results`` execution option is enabled
automatically if the :meth:`~sqlalchemy.orm.query.Query.yield_per()`
return self._execute_and_instances(context)
def _execute_and_instances(self, querycontext):
- result = self.session.connection(
+ conn = self.session.connection(
mapper = self._mapper_zero_or_none(),
clause = querycontext.statement,
- close_with_result=True).execute(querycontext.statement, self._params)
+ close_with_result=True)
+ if self._execution_options:
+ conn = conn.execution_options(**self._execution_options)
+
+ result = conn.execute(querycontext.statement, self._params)
return self.instances(result, querycontext)
@property
for_update=for_update,
use_labels=labels)
- if self._execution_options:
- statement = statement.execution_options(
- **self._execution_options)
-
from_clause = inner
for eager_join in eager_joins:
# EagerLoader places a 'stop_on' attribute on the join,
for hint in self._with_hints:
statement = statement.with_hint(*hint)
- if self._execution_options:
- statement = statement.execution_options(
- **self._execution_options)
-
if self._correlate:
statement = statement.correlate(*self._correlate)
def execution_options(self, **kw):
""" Set non-SQL options for the statement which take effect during
execution.
-
- :param autocommit: when True, a COMMIT will be invoked after execution
- when executed in 'autocommit' mode, i.e. when an explicit
- transaction is not begun on the connection. Note that DBAPI
- connections by default are always in a transaction - SQLAlchemy uses
- rules applied to different kinds of statements to determine if
- COMMIT will be invoked in order to provide its "autocommit" feature.
- Typically, all INSERT/UPDATE/DELETE statements as well as
- CREATE/DROP statements have autocommit behavior enabled; SELECT
- constructs do not. Use this option when invoking a SELECT or other
- specific SQL construct where COMMIT is desired (typically when
- calling stored procedures and such).
-
- :param stream_results: indicate to the dialect that results should be
- "streamed" and not pre-buffered, if possible. This is a limitation
- of many DBAPIs. The flag is currently understood only by the
- psycopg2 dialect.
-
- :param compiled_cache: a dictionary where :class:`.Compiled` objects
- will be cached when the :class:`.Connection` compiles a clause
- expression into a dialect- and parameter-specific
- :class:`.Compiled` object. It is the user's responsibility to
- manage the size of this dictionary, which will have keys
- corresponding to the dialect, clause element, the column
- names within the VALUES or SET clause of an INSERT or UPDATE,
- as well as the "batch" mode for an INSERT or UPDATE statement.
- The format of this dictionary is not guaranteed to stay the
- same in future releases.
-
- This option is usually more appropriate
- to use via the
- :meth:`.Connection.execution_options()`
- method of :class:`.Connection`, rather than upon individual
- statement objects, though the effect is the same.
-
- Note that the ORM makes use of its own "compiled" caches for
- some operations, including flush operations. The caching
- used by the ORM internally supersedes a cache dictionary
- specified here.
+
+ Execution options can be set on a per-statement or
+ per :class:`.Connection` basis. Additionally, the
+ :class:`.Engine` and ORM :class:`~.orm.query.Query` objects provide access
+ to execution options which they in turn configure upon connections.
+
+ The :meth:`execution_options` method is generative. A new
+ instance of this statement is returned that contains the options::
+
+ statement = select([table.c.x, table.c.y])
+ statement = statement.execution_options(autocommit=True)
+
+ Note that only a subset of possible execution options can be applied
+ to a statement - these include "autocommit" and "stream_results",
+ but not "isolation_level" or "compiled_cache".
+ See :meth:`.Connection.execution_options` for a full list of
+ possible options.
See also:
- :meth:`.Connection.execution_options()` -
- includes a connection-only option to specify transaction isolation
- level.
+ :meth:`.Connection.execution_options()`
- :meth:`.Query.execution_options()` - applies options to
- the statement
- generated by a :class:`.orm.Query` object.
+ :meth:`.Query.execution_options()`
"""
if 'isolation_level' in kw:
"per-engine using the isolation_level "
"argument to create_engine()."
)
-
+ if 'compiled_cache' in kw:
+ raise exc.ArgumentError(
+ "'compiled_cache' execution option may only be specified "
+ "on Connection.execution_options(), not per statement."
+ )
self._execution_options = self._execution_options.union(kw)
def execute(self, *multiparams, **params):
sess.bind = testing.db
eq_(sess.query().value(sa.literal_column('1').label('x')), 1)
-class StatementOptionsTest(QueryTest):
+class ExecutionOptionsTest(QueryTest):
- def test_query_with_statement_option(self):
+ def test_option_building(self):
User = self.classes.User
sess = create_session(bind=testing.db, autocommit=False)
q3_options = dict(foo='not bar', stream_results=True, answer=42)
assert q3._execution_options == q3_options
- assert q3.statement._execution_options == q3_options
- assert q3._compile_context().statement._execution_options == q3_options
- assert q3.subquery().original._execution_options == q3_options
- # TODO: Test that statement options are passed on to
- # updates/deletes, but currently there are no such options
- # applicable for them.
+ def test_options_in_connection(self):
+ User = self.classes.User
+
+ execution_options = dict(foo='bar', stream_results=True)
+ class TQuery(Query):
+ def instances(self, result, ctx):
+ eq_(
+ result.connection._execution_options,
+ execution_options
+ )
+ return iter([])
+
+ sess = create_session(bind=testing.db, autocommit=False, query_cls=TQuery)
+ q1 = sess.query(User).execution_options(**execution_options)
+ q1.all()
class OptionsTest(QueryTest):
"""Test the _get_paths() method of PropertyOption."""
from sqlalchemy.sql.expression import _clone, _from_objects
from test.lib import *
from sqlalchemy.sql.visitors import *
-from sqlalchemy import util
+from sqlalchemy import util, exc
from sqlalchemy.sql import util as sql_util
-from test.lib.testing import eq_
+from test.lib.testing import eq_, assert_raises
class TraversalTest(fixtures.TestBase, AssertsExecutionResults):
"""test ClauseVisitor's traversal, particularly its
assert s2._execution_options == dict(foo='bar', bar='baz')
assert s3._execution_options == dict(foo='not bar')
+ def test_invalid_options(self):
+ assert_raises(
+ exc.ArgumentError,
+ select().execution_options, compiled_cache={}
+ )
+
+ assert_raises(
+ exc.ArgumentError,
+ select().execution_options,
+ isolation_level='READ_COMMITTED'
+ )
+
# this feature not available yet
def _NOTYET_test_execution_options_in_kwargs(self):
s = select(execution_options=dict(foo='bar'))