diff options
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r-- | lib/sqlalchemy/sql/base.py | 109 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/ddl.py | 49 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/dml.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 26 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 1 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/functions.py | 48 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/lambdas.py | 8 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/schema.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/selectable.py | 5 |
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 ) |