summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/base.py109
-rw-r--r--lib/sqlalchemy/sql/compiler.py4
-rw-r--r--lib/sqlalchemy/sql/ddl.py49
-rw-r--r--lib/sqlalchemy/sql/dml.py3
-rw-r--r--lib/sqlalchemy/sql/elements.py26
-rw-r--r--lib/sqlalchemy/sql/expression.py1
-rw-r--r--lib/sqlalchemy/sql/functions.py48
-rw-r--r--lib/sqlalchemy/sql/lambdas.py8
-rw-r--r--lib/sqlalchemy/sql/schema.py4
-rw-r--r--lib/sqlalchemy/sql/selectable.py5
10 files changed, 107 insertions, 150 deletions
diff --git a/lib/sqlalchemy/sql/base.py b/lib/sqlalchemy/sql/base.py
index 4bcb655d6..0c375b6d7 100644
--- a/lib/sqlalchemy/sql/base.py
+++ b/lib/sqlalchemy/sql/base.py
@@ -32,7 +32,6 @@ coercions = None
elements = None
type_api = None
-PARSE_AUTOCOMMIT = util.symbol("PARSE_AUTOCOMMIT")
NO_ARG = util.symbol("NO_ARG")
@@ -884,34 +883,104 @@ class Executable(roles.StatementRole, Generative):
"""Set non-SQL options for the statement which take effect during
execution.
- Execution options can be set on a per-statement or
- per :class:`_engine.Connection` basis. Additionally, the
- :class:`_engine.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::
+ Execution options can be set at many scopes, including per-statement,
+ per-connection, or per execution, using methods such as
+ :meth:`_engine.Connection.execution_options` and parameters which
+ accept a dictionary of options such as
+ :paramref:`_engine.Connection.execute.execution_options` and
+ :paramref:`_orm.Session.execute.execution_options`.
+
+ The primary characteristic of an execution option, as opposed to
+ other kinds of options such as ORM loader options, is that
+ **execution options never affect the compiled SQL of a query, only
+ things that affect how the SQL statement itself is invoked or how
+ results are fetched**. That is, execution options are not part of
+ what's accommodated by SQL compilation nor are they considered part of
+ the cached state of a statement.
+
+ The :meth:`_sql.Executable.execution_options` method is
+ :term:`generative`, as
+ is the case for the method as applied to the :class:`_engine.Engine`
+ and :class:`_orm.Query` objects, which means when the method is called,
+ a copy of the object is returned, which applies the given parameters to
+ that new copy, but leaves the original unchanged::
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:`_engine.Connection.execution_options` for a full list of
- possible options.
+ new_statement = statement.execution_options(my_option=True)
+
+ An exception to this behavior is the :class:`_engine.Connection`
+ object, where the :meth:`_engine.Connection.execution_options` method
+ is explicitly **not** generative.
+
+ The kinds of options that may be passed to
+ :meth:`_sql.Executable.execution_options` and other related methods and
+ parameter dictionaries include parameters that are explicitly consumed
+ by SQLAlchemy Core or ORM, as well as arbitrary keyword arguments not
+ defined by SQLAlchemy, which means the methods and/or parameter
+ dictionaries may be used for user-defined parameters that interact with
+ custom code, which may access the parameters using methods such as
+ :meth:`_sql.Executable.get_execution_options` and
+ :meth:`_engine.Connection.get_execution_options`, or within selected
+ event hooks using a dedicated ``execution_options`` event parameter
+ such as
+ :paramref:`_events.ConnectionEvents.before_execute.execution_options`
+ or :attr:`_orm.ORMExecuteState.execution_options`, e.g.::
+
+ from sqlalchemy import event
+
+ @event.listens_for(some_engine, "before_execute")
+ def _process_opt(conn, statement, multiparams, params, execution_options):
+ "run a SQL function before invoking a statement"
+
+ if execution_options.get("do_special_thing", False):
+ conn.exec_driver_sql("run_special_function()")
+
+ Within the scope of options that are explicitly recognized by
+ SQLAlchemy, most apply to specific classes of objects and not others.
+ The most common execution options include:
+
+ * :paramref:`_engine.Connection.execution_options.isolation_level` -
+ sets the isolation level for a connection or a class of connections
+ via an :class:`_engine.Engine`. This option is accepted only
+ by :class:`_engine.Connection` or :class:`_engine.Engine`.
+
+ * :paramref:`_engine.Connection.execution_options.stream_results` -
+ indicates results should be fetched using a server side cursor;
+ this option is accepted by :class:`_engine.Connection`, by the
+ :paramref:`_engine.Connection.execute.execution_options` parameter
+ on :meth:`_engine.Connection.execute`, and additionally by
+ :meth:`_sql.Executable.execution_options` on a SQL statement object,
+ as well as by ORM constructs like :meth:`_orm.Session.execute`.
+
+ * :paramref:`_engine.Connection.execution_options.compiled_cache` -
+ indicates a dictionary that will serve as the
+ :ref:`SQL compilation cache <sql_caching>`
+ for a :class:`_engine.Connection` or :class:`_engine.Engine`, as
+ well as for ORM methods like :meth:`_orm.Session.execute`.
+ Can be passed as ``None`` to disable caching for statements.
+ This option is not accepted by
+ :meth:`_sql.Executable.execution_options` as it is inadvisable to
+ carry along a compilation cache within a statement object.
+
+ * :paramref:`_engine.Connection.execution_options.schema_translate_map`
+ - a mapping of schema names used by the
+ :ref:`Schema Translate Map <schema_translating>` feature, accepted
+ by :class:`_engine.Connection`, :class:`_engine.Engine`,
+ :class:`_sql.Executable`, as well as by ORM constructs
+ like :meth:`_orm.Session.execute`.
.. seealso::
:meth:`_engine.Connection.execution_options`
- :meth:`_query.Query.execution_options`
+ :paramref:`_engine.Connection.execute.execution_options`
- :meth:`.Executable.get_execution_options`
+ :paramref:`_orm.Session.execute.execution_options`
- """
+ :ref:`orm_queryguide_execution_options` - documentation on all
+ ORM-specific execution options
+
+ """ # noqa E501
if "isolation_level" in kw:
raise exc.ArgumentError(
"'isolation_level' execution option may only be specified "
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 96349578c..4611c5e13 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -456,11 +456,11 @@ class Compiled(object):
self._gen_time = util.perf_counter()
def _execute_on_connection(
- self, connection, multiparams, params, execution_options
+ self, connection, distilled_params, execution_options
):
if self.can_execute:
return connection._execute_compiled(
- self, multiparams, params, execution_options
+ self, distilled_params, execution_options
)
else:
raise exc.ObjectNotExecutableError(self.statement)
diff --git a/lib/sqlalchemy/sql/ddl.py b/lib/sqlalchemy/sql/ddl.py
index f8985548e..f732ff2b0 100644
--- a/lib/sqlalchemy/sql/ddl.py
+++ b/lib/sqlalchemy/sql/ddl.py
@@ -11,7 +11,6 @@ to invoke them for a create/drop call.
"""
from . import roles
-from .base import _bind_or_error
from .base import _generative
from .base import Executable
from .base import SchemaVisitor
@@ -62,62 +61,18 @@ class DDLElement(roles.DDLRole, Executable, _DDLCompiles):
"""
- _execution_options = Executable._execution_options.union(
- {"autocommit": True}
- )
-
target = None
on = None
dialect = None
callable_ = None
def _execute_on_connection(
- self, connection, multiparams, params, execution_options
+ self, connection, distilled_params, execution_options
):
return connection._execute_ddl(
- self, multiparams, params, execution_options
+ self, distilled_params, execution_options
)
- @util.deprecated_20(
- ":meth:`.DDLElement.execute`",
- alternative="All statement execution in SQLAlchemy 2.0 is performed "
- "by the :meth:`_engine.Connection.execute` method of "
- ":class:`_engine.Connection`, "
- "or in the ORM by the :meth:`.Session.execute` method of "
- ":class:`.Session`.",
- )
- def execute(self, bind=None, target=None):
- """Execute this DDL immediately.
-
- Executes the DDL statement in isolation using the supplied
- :class:`.Connectable` or
- :class:`.Connectable` assigned to the ``.bind``
- property, if not supplied. If the DDL has a conditional ``on``
- criteria, it will be invoked with None as the event.
-
- :param bind:
- Optional, an ``Engine`` or ``Connection``. If not supplied, a valid
- :class:`.Connectable` must be present in the
- ``.bind`` property.
-
- :param target:
- Optional, defaults to None. The target :class:`_schema.SchemaItem`
- for the execute call. This is equivalent to passing the
- :class:`_schema.SchemaItem` to the :meth:`.DDLElement.against`
- method and then invoking :meth:`_schema.DDLElement.execute`
- upon the resulting :class:`_schema.DDLElement` object. See
- :meth:`.DDLElement.against` for further detail.
-
- """
-
- if bind is None:
- bind = _bind_or_error(self)
-
- if self._should_execute(target, bind):
- return bind.execute(self.against(target))
- else:
- bind.engine.logger.info("DDL execution skipped, criteria not met.")
-
@_generative
def against(self, target):
"""Return a copy of this :class:`_schema.DDLElement` which will include
diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py
index ebff0df88..03968d284 100644
--- a/lib/sqlalchemy/sql/dml.py
+++ b/lib/sqlalchemy/sql/dml.py
@@ -223,9 +223,6 @@ class UpdateBase(
__visit_name__ = "update_base"
- _execution_options = Executable._execution_options.union(
- {"autocommit": True}
- )
_hints = util.immutabledict()
named_with_column = False
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index c8faebbd9..a279f634d 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -29,7 +29,6 @@ from .base import Executable
from .base import HasMemoized
from .base import Immutable
from .base import NO_ARG
-from .base import PARSE_AUTOCOMMIT
from .base import SingletonConstant
from .coercions import _document_text_coercion
from .traversals import HasCopyInternals
@@ -319,11 +318,11 @@ class ClauseElement(
return d
def _execute_on_connection(
- self, connection, multiparams, params, execution_options, _force=False
+ self, connection, distilled_params, execution_options, _force=False
):
if _force or self.supports_execution:
return connection._execute_clauseelement(
- self, multiparams, params, execution_options
+ self, distilled_params, execution_options
)
else:
raise exc.ObjectNotExecutableError(self)
@@ -1755,9 +1754,6 @@ class TextClause(
_is_textual = True
_bind_params_regex = re.compile(r"(?<![:\w\x5c]):(\w+)(?!:)", re.UNICODE)
- _execution_options = Executable._execution_options.union(
- {"autocommit": PARSE_AUTOCOMMIT}
- )
_is_implicitly_boolean = False
_render_label_in_columns_clause = False
@@ -1860,19 +1856,8 @@ class TextClause(
:func:`_expression.text` is also used for the construction
of a full, standalone statement using plain text.
As such, SQLAlchemy refers
- to it as an :class:`.Executable` object, and it supports
- the :meth:`Executable.execution_options` method. For example,
- a :func:`_expression.text`
- construct that should be subject to "autocommit"
- can be set explicitly so using the
- :paramref:`.Connection.execution_options.autocommit` option::
-
- t = text("EXEC my_procedural_thing()").\
- execution_options(autocommit=True)
-
- .. deprecated:: 1.4 The "autocommit" execution option is deprecated
- and will be removed in SQLAlchemy 2.0. See
- :ref:`migration_20_autocommit` for discussion.
+ to it as an :class:`.Executable` object and may be used
+ like any other statement passed to an ``.execute()`` method.
:param text:
the text of the SQL statement to be created. Use ``:<param>``
@@ -5044,9 +5029,6 @@ class CollationClause(ColumnElement):
class _IdentifiedClause(Executable, ClauseElement):
__visit_name__ = "identified"
- _execution_options = Executable._execution_options.union(
- {"autocommit": False}
- )
def __init__(self, ident):
self.ident = ident
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 129e628ab..03fe9b567 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -96,7 +96,6 @@ from .base import _from_objects
from .base import _select_iterables
from .base import ColumnCollection
from .base import Executable
-from .base import PARSE_AUTOCOMMIT
from .dml import Delete
from .dml import Insert
from .dml import Update
diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py
index 5729f81f5..35b0cb7d7 100644
--- a/lib/sqlalchemy/sql/functions.py
+++ b/lib/sqlalchemy/sql/functions.py
@@ -134,10 +134,10 @@ class FunctionElement(Executable, ColumnElement, FromClause, Generative):
)
def _execute_on_connection(
- self, connection, multiparams, params, execution_options
+ self, connection, distilled_params, execution_options
):
return connection._execute_function(
- self, multiparams, params, execution_options
+ self, distilled_params, execution_options
)
def scalar_table_valued(self, name, type_=None):
@@ -571,50 +571,6 @@ class FunctionElement(Executable, ColumnElement, FromClause, Generative):
s = s.execution_options(**self._execution_options)
return s
- @util.deprecated_20(
- ":meth:`.FunctionElement.scalar`",
- alternative="Scalar execution in SQLAlchemy 2.0 is performed "
- "by the :meth:`_engine.Connection.scalar` method of "
- ":class:`_engine.Connection`, "
- "or in the ORM by the :meth:`.Session.scalar` method of "
- ":class:`.Session`.",
- )
- def scalar(self):
- """Execute this :class:`.FunctionElement` against an embedded
- 'bind' and return a scalar value.
-
- This first calls :meth:`~.FunctionElement.select` to
- produce a SELECT construct.
-
- Note that :class:`.FunctionElement` can be passed to
- the :meth:`.Connectable.scalar` method of :class:`_engine.Connection`
- or :class:`_engine.Engine`.
-
- """
- return self.select().execute().scalar()
-
- @util.deprecated_20(
- ":meth:`.FunctionElement.execute`",
- alternative="All statement execution in SQLAlchemy 2.0 is performed "
- "by the :meth:`_engine.Connection.execute` method of "
- ":class:`_engine.Connection`, "
- "or in the ORM by the :meth:`.Session.execute` method of "
- ":class:`.Session`.",
- )
- def execute(self):
- """Execute this :class:`.FunctionElement` against an embedded
- 'bind'.
-
- This first calls :meth:`~.FunctionElement.select` to
- produce a SELECT construct.
-
- Note that :class:`.FunctionElement` can be passed to
- the :meth:`.Connectable.execute` method of :class:`_engine.Connection`
- or :class:`_engine.Engine`.
-
- """
- return self.select().execute()
-
def _bind_param(self, operator, obj, type_=None, **kw):
return BindParameter(
None,
diff --git a/lib/sqlalchemy/sql/lambdas.py b/lib/sqlalchemy/sql/lambdas.py
index 03cd05f02..e7c19b9a0 100644
--- a/lib/sqlalchemy/sql/lambdas.py
+++ b/lib/sqlalchemy/sql/lambdas.py
@@ -502,11 +502,11 @@ class StatementLambdaElement(roles.AllowsLambdaRole, LambdaElement):
return LinkedLambdaElement(other, parent_lambda=self, opts=opts)
def _execute_on_connection(
- self, connection, multiparams, params, execution_options
+ self, connection, distilled_params, execution_options
):
if self._rec.expected_expr.supports_execution:
return connection._execute_clauseelement(
- self, multiparams, params, execution_options
+ self, distilled_params, execution_options
)
else:
raise exc.ObjectNotExecutableError(self)
@@ -568,11 +568,11 @@ class NullLambdaStatement(roles.AllowsLambdaRole, elements.ClauseElement):
return NullLambdaStatement(statement)
def _execute_on_connection(
- self, connection, multiparams, params, execution_options
+ self, connection, distilled_params, execution_options
):
if self._resolved.supports_execution:
return connection._execute_clauseelement(
- self, multiparams, params, execution_options
+ self, distilled_params, execution_options
)
else:
raise exc.ObjectNotExecutableError(self)
diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py
index e45e22564..dbd50d5d8 100644
--- a/lib/sqlalchemy/sql/schema.py
+++ b/lib/sqlalchemy/sql/schema.py
@@ -2518,10 +2518,10 @@ class DefaultGenerator(Executable, SchemaItem):
self.column.default = self
def _execute_on_connection(
- self, connection, multiparams, params, execution_options
+ self, connection, distilled_params, execution_options
):
return connection._execute_default(
- self, multiparams, params, execution_options
+ self, distilled_params, execution_options
)
@property
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index 8013477fa..0e5ae89e4 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -2495,8 +2495,7 @@ class Subquery(AliasedReturnsRows):
def _execute_on_connection(
self,
connection,
- multiparams,
- params,
+ distilled_params,
execution_options,
):
util.warn_deprecated(
@@ -2506,7 +2505,7 @@ class Subquery(AliasedReturnsRows):
"1.4",
)
return self.element._execute_on_connection(
- connection, multiparams, params, execution_options, _force=True
+ connection, distilled_params, execution_options, _force=True
)