Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/sql/dml.py: 47%
330 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
1# sql/dml.py
2# Copyright (C) 2009-2022 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7"""
8Provide :class:`_expression.Insert`, :class:`_expression.Update` and
9:class:`_expression.Delete`.
11"""
12from sqlalchemy.types import NullType
13from . import coercions
14from . import roles
15from . import util as sql_util
16from .base import _entity_namespace_key
17from .base import _exclusive_against
18from .base import _from_objects
19from .base import _generative
20from .base import ColumnCollection
21from .base import CompileState
22from .base import DialectKWArgs
23from .base import Executable
24from .base import HasCompileState
25from .elements import BooleanClauseList
26from .elements import ClauseElement
27from .elements import Null
28from .selectable import HasCTE
29from .selectable import HasPrefixes
30from .selectable import ReturnsRows
31from .visitors import InternalTraversal
32from .. import exc
33from .. import util
34from ..util import collections_abc
37class DMLState(CompileState):
38 _no_parameters = True
39 _dict_parameters = None
40 _multi_parameters = None
41 _ordered_values = None
42 _parameter_ordering = None
43 _has_multi_parameters = False
44 isupdate = False
45 isdelete = False
46 isinsert = False
48 def __init__(self, statement, compiler, **kw):
49 raise NotImplementedError()
51 @classmethod
52 def get_entity_description(cls, statement):
53 return {"name": statement.table.name, "table": statement.table}
55 @classmethod
56 def get_returning_column_descriptions(cls, statement):
57 return [
58 {
59 "name": c.key,
60 "type": c.type,
61 "expr": c,
62 }
63 for c in statement._all_selected_columns
64 ]
66 @property
67 def dml_table(self):
68 return self.statement.table
70 @classmethod
71 def _get_crud_kv_pairs(cls, statement, kv_iterator):
72 return [
73 (
74 coercions.expect(roles.DMLColumnRole, k),
75 coercions.expect(
76 roles.ExpressionElementRole,
77 v,
78 type_=NullType(),
79 is_crud=True,
80 ),
81 )
82 for k, v in kv_iterator
83 ]
85 def _make_extra_froms(self, statement):
86 froms = []
88 all_tables = list(sql_util.tables_from_leftmost(statement.table))
89 seen = {all_tables[0]}
91 for crit in statement._where_criteria:
92 for item in _from_objects(crit):
93 if not seen.intersection(item._cloned_set):
94 froms.append(item)
95 seen.update(item._cloned_set)
97 froms.extend(all_tables[1:])
98 return froms
100 def _process_multi_values(self, statement):
101 if not statement._supports_multi_parameters:
102 raise exc.InvalidRequestError(
103 "%s construct does not support "
104 "multiple parameter sets." % statement.__visit_name__.upper()
105 )
107 for parameters in statement._multi_values:
108 multi_parameters = [
109 {
110 c.key: value
111 for c, value in zip(statement.table.c, parameter_set)
112 }
113 if isinstance(parameter_set, collections_abc.Sequence)
114 else parameter_set
115 for parameter_set in parameters
116 ]
118 if self._no_parameters:
119 self._no_parameters = False
120 self._has_multi_parameters = True
121 self._multi_parameters = multi_parameters
122 self._dict_parameters = self._multi_parameters[0]
123 elif not self._has_multi_parameters:
124 self._cant_mix_formats_error()
125 else:
126 self._multi_parameters.extend(multi_parameters)
128 def _process_values(self, statement):
129 if self._no_parameters:
130 self._has_multi_parameters = False
131 self._dict_parameters = statement._values
132 self._no_parameters = False
133 elif self._has_multi_parameters:
134 self._cant_mix_formats_error()
136 def _process_ordered_values(self, statement):
137 parameters = statement._ordered_values
139 if self._no_parameters:
140 self._no_parameters = False
141 self._dict_parameters = dict(parameters)
142 self._ordered_values = parameters
143 self._parameter_ordering = [key for key, value in parameters]
144 elif self._has_multi_parameters:
145 self._cant_mix_formats_error()
146 else:
147 raise exc.InvalidRequestError(
148 "Can only invoke ordered_values() once, and not mixed "
149 "with any other values() call"
150 )
152 def _process_select_values(self, statement):
153 parameters = {
154 coercions.expect(roles.DMLColumnRole, name, as_key=True): Null()
155 for name in statement._select_names
156 }
158 if self._no_parameters:
159 self._no_parameters = False
160 self._dict_parameters = parameters
161 else:
162 # this condition normally not reachable as the Insert
163 # does not allow this construction to occur
164 assert False, "This statement already has parameters"
166 def _cant_mix_formats_error(self):
167 raise exc.InvalidRequestError(
168 "Can't mix single and multiple VALUES "
169 "formats in one INSERT statement; one style appends to a "
170 "list while the other replaces values, so the intent is "
171 "ambiguous."
172 )
175@CompileState.plugin_for("default", "insert")
176class InsertDMLState(DMLState):
177 isinsert = True
179 include_table_with_column_exprs = False
181 def __init__(self, statement, compiler, **kw):
182 self.statement = statement
184 self.isinsert = True
185 if statement._select_names:
186 self._process_select_values(statement)
187 if statement._values is not None:
188 self._process_values(statement)
189 if statement._multi_values:
190 self._process_multi_values(statement)
192 @util.memoized_property
193 def _insert_col_keys(self):
194 # this is also done in crud.py -> _key_getters_for_crud_column
195 return [
196 coercions.expect_as_key(roles.DMLColumnRole, col)
197 for col in self._dict_parameters
198 ]
201@CompileState.plugin_for("default", "update")
202class UpdateDMLState(DMLState):
203 isupdate = True
205 include_table_with_column_exprs = False
207 def __init__(self, statement, compiler, **kw):
208 self.statement = statement
209 self.isupdate = True
210 self._preserve_parameter_order = statement._preserve_parameter_order
211 if statement._ordered_values is not None:
212 self._process_ordered_values(statement)
213 elif statement._values is not None:
214 self._process_values(statement)
215 elif statement._multi_values:
216 self._process_multi_values(statement)
217 self._extra_froms = ef = self._make_extra_froms(statement)
218 self.is_multitable = mt = ef and self._dict_parameters
219 self.include_table_with_column_exprs = (
220 mt and compiler.render_table_with_column_in_update_from
221 )
224@CompileState.plugin_for("default", "delete")
225class DeleteDMLState(DMLState):
226 isdelete = True
228 def __init__(self, statement, compiler, **kw):
229 self.statement = statement
231 self.isdelete = True
232 self._extra_froms = self._make_extra_froms(statement)
235class UpdateBase(
236 roles.DMLRole,
237 HasCTE,
238 HasCompileState,
239 DialectKWArgs,
240 HasPrefixes,
241 ReturnsRows,
242 Executable,
243 ClauseElement,
244):
245 """Form the base for ``INSERT``, ``UPDATE``, and ``DELETE`` statements."""
247 __visit_name__ = "update_base"
249 _execution_options = Executable._execution_options.union(
250 {"autocommit": True}
251 )
252 _hints = util.immutabledict()
253 named_with_column = False
255 _return_defaults = False
256 _return_defaults_columns = None
257 _returning = ()
259 is_dml = True
261 @classmethod
262 def _constructor_20_deprecations(cls, fn_name, clsname, names):
264 param_to_method_lookup = dict(
265 whereclause=(
266 "The :paramref:`%(func)s.whereclause` parameter "
267 "will be removed "
268 "in SQLAlchemy 2.0. Please refer to the "
269 ":meth:`%(classname)s.where` method."
270 ),
271 values=(
272 "The :paramref:`%(func)s.values` parameter will be removed "
273 "in SQLAlchemy 2.0. Please refer to the "
274 ":meth:`%(classname)s.values` method."
275 ),
276 bind=(
277 "The :paramref:`%(func)s.bind` parameter will be removed in "
278 "SQLAlchemy 2.0. Please use explicit connection execution."
279 ),
280 inline=(
281 "The :paramref:`%(func)s.inline` parameter will be "
282 "removed in "
283 "SQLAlchemy 2.0. Please use the "
284 ":meth:`%(classname)s.inline` method."
285 ),
286 prefixes=(
287 "The :paramref:`%(func)s.prefixes parameter will be "
288 "removed in "
289 "SQLAlchemy 2.0. Please use the "
290 ":meth:`%(classname)s.prefix_with` "
291 "method."
292 ),
293 return_defaults=(
294 "The :paramref:`%(func)s.return_defaults` parameter will be "
295 "removed in SQLAlchemy 2.0. Please use the "
296 ":meth:`%(classname)s.return_defaults` method."
297 ),
298 returning=(
299 "The :paramref:`%(func)s.returning` parameter will be "
300 "removed in SQLAlchemy 2.0. Please use the "
301 ":meth:`%(classname)s.returning`` method."
302 ),
303 preserve_parameter_order=(
304 "The :paramref:`%(func)s.preserve_parameter_order` parameter "
305 "will be removed in SQLAlchemy 2.0. Use the "
306 ":meth:`%(classname)s.ordered_values` method with a list "
307 "of tuples. "
308 ),
309 )
311 return util.deprecated_params(
312 **{
313 name: (
314 "2.0",
315 param_to_method_lookup[name]
316 % {
317 "func": "_expression.%s" % fn_name,
318 "classname": "_expression.%s" % clsname,
319 },
320 )
321 for name in names
322 }
323 )
325 def _generate_fromclause_column_proxies(self, fromclause):
326 fromclause._columns._populate_separate_keys(
327 col._make_proxy(fromclause) for col in self._returning
328 )
330 def params(self, *arg, **kw):
331 """Set the parameters for the statement.
333 This method raises ``NotImplementedError`` on the base class,
334 and is overridden by :class:`.ValuesBase` to provide the
335 SET/VALUES clause of UPDATE and INSERT.
337 """
338 raise NotImplementedError(
339 "params() is not supported for INSERT/UPDATE/DELETE statements."
340 " To set the values for an INSERT or UPDATE statement, use"
341 " stmt.values(**parameters)."
342 )
344 @_generative
345 def with_dialect_options(self, **opt):
346 """Add dialect options to this INSERT/UPDATE/DELETE object.
348 e.g.::
350 upd = table.update().dialect_options(mysql_limit=10)
352 .. versionadded: 1.4 - this method supersedes the dialect options
353 associated with the constructor.
356 """
357 self._validate_dialect_kwargs(opt)
359 def _validate_dialect_kwargs_deprecated(self, dialect_kw):
360 util.warn_deprecated_20(
361 "Passing dialect keyword arguments directly to the "
362 "%s constructor is deprecated and will be removed in SQLAlchemy "
363 "2.0. Please use the ``with_dialect_options()`` method."
364 % (self.__class__.__name__)
365 )
366 self._validate_dialect_kwargs(dialect_kw)
368 def bind(self):
369 """Return a 'bind' linked to this :class:`.UpdateBase`
370 or a :class:`_schema.Table` associated with it.
372 """
373 return self._bind or self.table.bind
375 def _set_bind(self, bind):
376 self._bind = bind
378 bind = property(bind, _set_bind)
380 @_generative
381 def returning(self, *cols):
382 r"""Add a :term:`RETURNING` or equivalent clause to this statement.
384 e.g.:
386 .. sourcecode:: pycon+sql
388 >>> stmt = (
389 ... table.update()
390 ... .where(table.c.data == "value")
391 ... .values(status="X")
392 ... .returning(table.c.server_flag, table.c.updated_timestamp)
393 ... )
394 >>> print(stmt)
395 UPDATE some_table SET status=:status
396 WHERE some_table.data = :data_1
397 RETURNING some_table.server_flag, some_table.updated_timestamp
399 The method may be invoked multiple times to add new entries to the
400 list of expressions to be returned.
402 .. versionadded:: 1.4.0b2 The method may be invoked multiple times to
403 add new entries to the list of expressions to be returned.
405 The given collection of column expressions should be derived from the
406 table that is the target of the INSERT, UPDATE, or DELETE. While
407 :class:`_schema.Column` objects are typical, the elements can also be
408 expressions:
410 .. sourcecode:: pycon+sql
412 >>> stmt = table.insert().returning(
413 ... (table.c.first_name + " " + table.c.last_name).label("fullname")
414 ... )
415 >>> print(stmt)
416 INSERT INTO some_table (first_name, last_name)
417 VALUES (:first_name, :last_name)
418 RETURNING some_table.first_name || :first_name_1 || some_table.last_name AS fullname
420 Upon compilation, a RETURNING clause, or database equivalent,
421 will be rendered within the statement. For INSERT and UPDATE,
422 the values are the newly inserted/updated values. For DELETE,
423 the values are those of the rows which were deleted.
425 Upon execution, the values of the columns to be returned are made
426 available via the result set and can be iterated using
427 :meth:`_engine.CursorResult.fetchone` and similar.
428 For DBAPIs which do not
429 natively support returning values (i.e. cx_oracle), SQLAlchemy will
430 approximate this behavior at the result level so that a reasonable
431 amount of behavioral neutrality is provided.
433 Note that not all databases/DBAPIs
434 support RETURNING. For those backends with no support,
435 an exception is raised upon compilation and/or execution.
436 For those who do support it, the functionality across backends
437 varies greatly, including restrictions on executemany()
438 and other statements which return multiple rows. Please
439 read the documentation notes for the database in use in
440 order to determine the availability of RETURNING.
442 .. seealso::
444 :meth:`.ValuesBase.return_defaults` - an alternative method tailored
445 towards efficient fetching of server-side defaults and triggers
446 for single-row INSERTs or UPDATEs.
448 :ref:`tutorial_insert_returning` - in the :ref:`unified_tutorial`
450 """ # noqa: E501
451 if self._return_defaults:
452 raise exc.InvalidRequestError(
453 "return_defaults() is already configured on this statement"
454 )
455 self._returning += tuple(
456 coercions.expect(roles.ColumnsClauseRole, c) for c in cols
457 )
459 @property
460 def _all_selected_columns(self):
461 return self._returning
463 @property
464 def exported_columns(self):
465 """Return the RETURNING columns as a column collection for this
466 statement.
468 .. versionadded:: 1.4
470 """
471 # TODO: no coverage here
472 return ColumnCollection(
473 (c.key, c) for c in self._all_selected_columns
474 ).as_immutable()
476 @_generative
477 def with_hint(self, text, selectable=None, dialect_name="*"):
478 """Add a table hint for a single table to this
479 INSERT/UPDATE/DELETE statement.
481 .. note::
483 :meth:`.UpdateBase.with_hint` currently applies only to
484 Microsoft SQL Server. For MySQL INSERT/UPDATE/DELETE hints, use
485 :meth:`.UpdateBase.prefix_with`.
487 The text of the hint is rendered in the appropriate
488 location for the database backend in use, relative
489 to the :class:`_schema.Table` that is the subject of this
490 statement, or optionally to that of the given
491 :class:`_schema.Table` passed as the ``selectable`` argument.
493 The ``dialect_name`` option will limit the rendering of a particular
494 hint to a particular backend. Such as, to add a hint
495 that only takes effect for SQL Server::
497 mytable.insert().with_hint("WITH (PAGLOCK)", dialect_name="mssql")
499 :param text: Text of the hint.
500 :param selectable: optional :class:`_schema.Table` that specifies
501 an element of the FROM clause within an UPDATE or DELETE
502 to be the subject of the hint - applies only to certain backends.
503 :param dialect_name: defaults to ``*``, if specified as the name
504 of a particular dialect, will apply these hints only when
505 that dialect is in use.
506 """
507 if selectable is None:
508 selectable = self.table
510 self._hints = self._hints.union({(selectable, dialect_name): text})
512 @property
513 def entity_description(self):
514 """Return a :term:`plugin-enabled` description of the table and/or
515 entity which this DML construct is operating against.
517 This attribute is generally useful when using the ORM, as an
518 extended structure which includes information about mapped
519 entities is returned. The section :ref:`queryguide_inspection`
520 contains more background.
522 For a Core statement, the structure returned by this accessor
523 is derived from the :attr:`.UpdateBase.table` attribute, and
524 refers to the :class:`.Table` being inserted, updated, or deleted::
526 >>> stmt = insert(user_table)
527 >>> stmt.entity_description
528 {
529 "name": "user_table",
530 "table": Table("user_table", ...)
531 }
533 .. versionadded:: 1.4.33
535 .. seealso::
537 :attr:`.UpdateBase.returning_column_descriptions`
539 :attr:`.Select.column_descriptions` - entity information for
540 a :func:`.select` construct
542 :ref:`queryguide_inspection` - ORM background
544 """
545 meth = DMLState.get_plugin_class(self).get_entity_description
546 return meth(self)
548 @property
549 def returning_column_descriptions(self):
550 """Return a :term:`plugin-enabled` description of the columns
551 which this DML construct is RETURNING against, in other words
552 the expressions established as part of :meth:`.UpdateBase.returning`.
554 This attribute is generally useful when using the ORM, as an
555 extended structure which includes information about mapped
556 entities is returned. The section :ref:`queryguide_inspection`
557 contains more background.
559 For a Core statement, the structure returned by this accessor is
560 derived from the same objects that are returned by the
561 :attr:`.UpdateBase.exported_columns` accessor::
563 >>> stmt = insert(user_table).returning(user_table.c.id, user_table.c.name)
564 >>> stmt.entity_description
565 [
566 {
567 "name": "id",
568 "type": Integer,
569 "expr": Column("id", Integer(), table=<user>, ...)
570 },
571 {
572 "name": "name",
573 "type": String(),
574 "expr": Column("name", String(), table=<user>, ...)
575 },
576 ]
578 .. versionadded:: 1.4.33
580 .. seealso::
582 :attr:`.UpdateBase.entity_description`
584 :attr:`.Select.column_descriptions` - entity information for
585 a :func:`.select` construct
587 :ref:`queryguide_inspection` - ORM background
589 """ # noqa: E501
590 meth = DMLState.get_plugin_class(
591 self
592 ).get_returning_column_descriptions
593 return meth(self)
596class ValuesBase(UpdateBase):
597 """Supplies support for :meth:`.ValuesBase.values` to
598 INSERT and UPDATE constructs."""
600 __visit_name__ = "values_base"
602 _supports_multi_parameters = False
603 _preserve_parameter_order = False
604 select = None
605 _post_values_clause = None
607 _values = None
608 _multi_values = ()
609 _ordered_values = None
610 _select_names = None
612 _returning = ()
614 def __init__(self, table, values, prefixes):
615 self.table = coercions.expect(
616 roles.DMLTableRole, table, apply_propagate_attrs=self
617 )
618 if values is not None:
619 self.values.non_generative(self, values)
620 if prefixes:
621 self._setup_prefixes(prefixes)
623 @_generative
624 @_exclusive_against(
625 "_select_names",
626 "_ordered_values",
627 msgs={
628 "_select_names": "This construct already inserts from a SELECT",
629 "_ordered_values": "This statement already has ordered "
630 "values present",
631 },
632 )
633 def values(self, *args, **kwargs):
634 r"""Specify a fixed VALUES clause for an INSERT statement, or the SET
635 clause for an UPDATE.
637 Note that the :class:`_expression.Insert` and
638 :class:`_expression.Update`
639 constructs support
640 per-execution time formatting of the VALUES and/or SET clauses,
641 based on the arguments passed to :meth:`_engine.Connection.execute`.
642 However, the :meth:`.ValuesBase.values` method can be used to "fix" a
643 particular set of parameters into the statement.
645 Multiple calls to :meth:`.ValuesBase.values` will produce a new
646 construct, each one with the parameter list modified to include
647 the new parameters sent. In the typical case of a single
648 dictionary of parameters, the newly passed keys will replace
649 the same keys in the previous construct. In the case of a list-based
650 "multiple values" construct, each new list of values is extended
651 onto the existing list of values.
653 :param \**kwargs: key value pairs representing the string key
654 of a :class:`_schema.Column`
655 mapped to the value to be rendered into the
656 VALUES or SET clause::
658 users.insert().values(name="some name")
660 users.update().where(users.c.id==5).values(name="some name")
662 :param \*args: As an alternative to passing key/value parameters,
663 a dictionary, tuple, or list of dictionaries or tuples can be passed
664 as a single positional argument in order to form the VALUES or
665 SET clause of the statement. The forms that are accepted vary
666 based on whether this is an :class:`_expression.Insert` or an
667 :class:`_expression.Update` construct.
669 For either an :class:`_expression.Insert` or
670 :class:`_expression.Update`
671 construct, a single dictionary can be passed, which works the same as
672 that of the kwargs form::
674 users.insert().values({"name": "some name"})
676 users.update().values({"name": "some new name"})
678 Also for either form but more typically for the
679 :class:`_expression.Insert` construct, a tuple that contains an
680 entry for every column in the table is also accepted::
682 users.insert().values((5, "some name"))
684 The :class:`_expression.Insert` construct also supports being
685 passed a list of dictionaries or full-table-tuples, which on the
686 server will render the less common SQL syntax of "multiple values" -
687 this syntax is supported on backends such as SQLite, PostgreSQL,
688 MySQL, but not necessarily others::
690 users.insert().values([
691 {"name": "some name"},
692 {"name": "some other name"},
693 {"name": "yet another name"},
694 ])
696 The above form would render a multiple VALUES statement similar to::
698 INSERT INTO users (name) VALUES
699 (:name_1),
700 (:name_2),
701 (:name_3)
703 It is essential to note that **passing multiple values is
704 NOT the same as using traditional executemany() form**. The above
705 syntax is a **special** syntax not typically used. To emit an
706 INSERT statement against multiple rows, the normal method is
707 to pass a multiple values list to the
708 :meth:`_engine.Connection.execute`
709 method, which is supported by all database backends and is generally
710 more efficient for a very large number of parameters.
712 .. seealso::
714 :ref:`tutorial_multiple_parameters` - an introduction to
715 the traditional Core method of multiple parameter set
716 invocation for INSERTs and other statements.
718 .. versionchanged:: 1.0.0 an INSERT that uses a multiple-VALUES
719 clause, even a list of length one,
720 implies that the :paramref:`_expression.Insert.inline`
721 flag is set to
722 True, indicating that the statement will not attempt to fetch
723 the "last inserted primary key" or other defaults. The
724 statement deals with an arbitrary number of rows, so the
725 :attr:`_engine.CursorResult.inserted_primary_key`
726 accessor does not
727 apply.
729 .. versionchanged:: 1.0.0 A multiple-VALUES INSERT now supports
730 columns with Python side default values and callables in the
731 same way as that of an "executemany" style of invocation; the
732 callable is invoked for each row. See :ref:`bug_3288`
733 for other details.
735 The UPDATE construct also supports rendering the SET parameters
736 in a specific order. For this feature refer to the
737 :meth:`_expression.Update.ordered_values` method.
739 .. seealso::
741 :meth:`_expression.Update.ordered_values`
744 """
745 if args:
746 # positional case. this is currently expensive. we don't
747 # yet have positional-only args so we have to check the length.
748 # then we need to check multiparams vs. single dictionary.
749 # since the parameter format is needed in order to determine
750 # a cache key, we need to determine this up front.
751 arg = args[0]
753 if kwargs:
754 raise exc.ArgumentError(
755 "Can't pass positional and kwargs to values() "
756 "simultaneously"
757 )
758 elif len(args) > 1:
759 raise exc.ArgumentError(
760 "Only a single dictionary/tuple or list of "
761 "dictionaries/tuples is accepted positionally."
762 )
764 elif not self._preserve_parameter_order and isinstance(
765 arg, collections_abc.Sequence
766 ):
768 if arg and isinstance(arg[0], (list, dict, tuple)):
769 self._multi_values += (arg,)
770 return
772 # tuple values
773 arg = {c.key: value for c, value in zip(self.table.c, arg)}
774 elif self._preserve_parameter_order and not isinstance(
775 arg, collections_abc.Sequence
776 ):
777 raise ValueError(
778 "When preserve_parameter_order is True, "
779 "values() only accepts a list of 2-tuples"
780 )
782 else:
783 # kwarg path. this is the most common path for non-multi-params
784 # so this is fairly quick.
785 arg = kwargs
786 if args:
787 raise exc.ArgumentError(
788 "Only a single dictionary/tuple or list of "
789 "dictionaries/tuples is accepted positionally."
790 )
792 # for top level values(), convert literals to anonymous bound
793 # parameters at statement construction time, so that these values can
794 # participate in the cache key process like any other ClauseElement.
795 # crud.py now intercepts bound parameters with unique=True from here
796 # and ensures they get the "crud"-style name when rendered.
798 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs
800 if self._preserve_parameter_order:
801 self._ordered_values = kv_generator(self, arg)
802 else:
803 arg = {k: v for k, v in kv_generator(self, arg.items())}
804 if self._values:
805 self._values = self._values.union(arg)
806 else:
807 self._values = util.immutabledict(arg)
809 @_generative
810 @_exclusive_against(
811 "_returning",
812 msgs={
813 "_returning": "RETURNING is already configured on this statement"
814 },
815 defaults={"_returning": _returning},
816 )
817 def return_defaults(self, *cols):
818 """Make use of a :term:`RETURNING` clause for the purpose
819 of fetching server-side expressions and defaults.
821 E.g.::
823 stmt = table.insert().values(data='newdata').return_defaults()
825 result = connection.execute(stmt)
827 server_created_at = result.returned_defaults['created_at']
829 When used against a backend that supports RETURNING, all column
830 values generated by SQL expression or server-side-default will be
831 added to any existing RETURNING clause, provided that
832 :meth:`.UpdateBase.returning` is not used simultaneously. The column
833 values will then be available on the result using the
834 :attr:`_engine.CursorResult.returned_defaults` accessor as
835 a dictionary,
836 referring to values keyed to the :class:`_schema.Column`
837 object as well as
838 its ``.key``.
840 This method differs from :meth:`.UpdateBase.returning` in these ways:
842 1. :meth:`.ValuesBase.return_defaults` is only intended for use with an
843 INSERT or an UPDATE statement that matches exactly one row per
844 parameter set. While the RETURNING construct in the general sense
845 supports multiple rows for a multi-row UPDATE or DELETE statement,
846 or for special cases of INSERT that return multiple rows (e.g.
847 INSERT from SELECT, multi-valued VALUES clause),
848 :meth:`.ValuesBase.return_defaults` is intended only for an
849 "ORM-style" single-row INSERT/UPDATE statement. The row
850 returned by the statement is also consumed implicitly when
851 :meth:`.ValuesBase.return_defaults` is used. By contrast,
852 :meth:`.UpdateBase.returning` leaves the RETURNING result-set intact
853 with a collection of any number of rows.
855 2. It is compatible with the existing logic to fetch auto-generated
856 primary key values, also known as "implicit returning". Backends
857 that support RETURNING will automatically make use of RETURNING in
858 order to fetch the value of newly generated primary keys; while the
859 :meth:`.UpdateBase.returning` method circumvents this behavior,
860 :meth:`.ValuesBase.return_defaults` leaves it intact.
862 3. It can be called against any backend. Backends that don't support
863 RETURNING will skip the usage of the feature, rather than raising
864 an exception. The return value of
865 :attr:`_engine.CursorResult.returned_defaults` will be ``None``
867 4. An INSERT statement invoked with executemany() is supported if the
868 backend database driver supports the
869 ``insert_executemany_returning`` feature, currently this includes
870 PostgreSQL with psycopg2. When executemany is used, the
871 :attr:`_engine.CursorResult.returned_defaults_rows` and
872 :attr:`_engine.CursorResult.inserted_primary_key_rows` accessors
873 will return the inserted defaults and primary keys.
875 .. versionadded:: 1.4
877 :meth:`.ValuesBase.return_defaults` is used by the ORM to provide
878 an efficient implementation for the ``eager_defaults`` feature of
879 :func:`.mapper`.
881 :param cols: optional list of column key names or
882 :class:`_schema.Column`
883 objects. If omitted, all column expressions evaluated on the server
884 are added to the returning list.
886 .. versionadded:: 0.9.0
888 .. seealso::
890 :meth:`.UpdateBase.returning`
892 :attr:`_engine.CursorResult.returned_defaults`
894 :attr:`_engine.CursorResult.returned_defaults_rows`
896 :attr:`_engine.CursorResult.inserted_primary_key`
898 :attr:`_engine.CursorResult.inserted_primary_key_rows`
900 """
901 self._return_defaults = True
902 self._return_defaults_columns = cols
905class Insert(ValuesBase):
906 """Represent an INSERT construct.
908 The :class:`_expression.Insert` object is created using the
909 :func:`_expression.insert()` function.
911 """
913 __visit_name__ = "insert"
915 _supports_multi_parameters = True
917 select = None
918 include_insert_from_select_defaults = False
920 is_insert = True
922 _traverse_internals = (
923 [
924 ("table", InternalTraversal.dp_clauseelement),
925 ("_inline", InternalTraversal.dp_boolean),
926 ("_select_names", InternalTraversal.dp_string_list),
927 ("_values", InternalTraversal.dp_dml_values),
928 ("_multi_values", InternalTraversal.dp_dml_multi_values),
929 ("select", InternalTraversal.dp_clauseelement),
930 ("_post_values_clause", InternalTraversal.dp_clauseelement),
931 ("_returning", InternalTraversal.dp_clauseelement_list),
932 ("_hints", InternalTraversal.dp_table_hint_list),
933 ("_return_defaults", InternalTraversal.dp_boolean),
934 (
935 "_return_defaults_columns",
936 InternalTraversal.dp_clauseelement_list,
937 ),
938 ]
939 + HasPrefixes._has_prefixes_traverse_internals
940 + DialectKWArgs._dialect_kwargs_traverse_internals
941 + Executable._executable_traverse_internals
942 + HasCTE._has_ctes_traverse_internals
943 )
945 @ValuesBase._constructor_20_deprecations(
946 "insert",
947 "Insert",
948 [
949 "values",
950 "inline",
951 "bind",
952 "prefixes",
953 "returning",
954 "return_defaults",
955 ],
956 )
957 def __init__(
958 self,
959 table,
960 values=None,
961 inline=False,
962 bind=None,
963 prefixes=None,
964 returning=None,
965 return_defaults=False,
966 **dialect_kw
967 ):
968 """Construct an :class:`_expression.Insert` object.
970 E.g.::
972 from sqlalchemy import insert
974 stmt = (
975 insert(user_table).
976 values(name='username', fullname='Full Username')
977 )
979 Similar functionality is available via the
980 :meth:`_expression.TableClause.insert` method on
981 :class:`_schema.Table`.
983 .. seealso::
985 :ref:`tutorial_core_insert` - in the :ref:`unified_tutorial`
988 :param table: :class:`_expression.TableClause`
989 which is the subject of the
990 insert.
992 :param values: collection of values to be inserted; see
993 :meth:`_expression.Insert.values`
994 for a description of allowed formats here.
995 Can be omitted entirely; a :class:`_expression.Insert` construct
996 will also dynamically render the VALUES clause at execution time
997 based on the parameters passed to :meth:`_engine.Connection.execute`.
999 :param inline: if True, no attempt will be made to retrieve the
1000 SQL-generated default values to be provided within the statement;
1001 in particular,
1002 this allows SQL expressions to be rendered 'inline' within the
1003 statement without the need to pre-execute them beforehand; for
1004 backends that support "returning", this turns off the "implicit
1005 returning" feature for the statement.
1007 If both :paramref:`_expression.Insert.values` and compile-time bind
1008 parameters are present, the compile-time bind parameters override the
1009 information specified within :paramref:`_expression.Insert.values` on a
1010 per-key basis.
1012 The keys within :paramref:`_expression.Insert.values` can be either
1013 :class:`~sqlalchemy.schema.Column` objects or their string
1014 identifiers. Each key may reference one of:
1016 * a literal data value (i.e. string, number, etc.);
1017 * a Column object;
1018 * a SELECT statement.
1020 If a ``SELECT`` statement is specified which references this
1021 ``INSERT`` statement's table, the statement will be correlated
1022 against the ``INSERT`` statement.
1024 .. seealso::
1026 :ref:`tutorial_core_insert` - in the :ref:`unified_tutorial`
1028 """
1029 super(Insert, self).__init__(table, values, prefixes)
1030 self._bind = bind
1031 self._inline = inline
1032 if returning:
1033 self._returning = returning
1034 if dialect_kw:
1035 self._validate_dialect_kwargs_deprecated(dialect_kw)
1037 if return_defaults:
1038 self._return_defaults = True
1039 if not isinstance(return_defaults, bool):
1040 self._return_defaults_columns = return_defaults
1042 @_generative
1043 def inline(self):
1044 """Make this :class:`_expression.Insert` construct "inline" .
1046 When set, no attempt will be made to retrieve the
1047 SQL-generated default values to be provided within the statement;
1048 in particular,
1049 this allows SQL expressions to be rendered 'inline' within the
1050 statement without the need to pre-execute them beforehand; for
1051 backends that support "returning", this turns off the "implicit
1052 returning" feature for the statement.
1055 .. versionchanged:: 1.4 the :paramref:`_expression.Insert.inline`
1056 parameter
1057 is now superseded by the :meth:`_expression.Insert.inline` method.
1059 """
1060 self._inline = True
1062 @_generative
1063 def from_select(self, names, select, include_defaults=True):
1064 """Return a new :class:`_expression.Insert` construct which represents
1065 an ``INSERT...FROM SELECT`` statement.
1067 e.g.::
1069 sel = select(table1.c.a, table1.c.b).where(table1.c.c > 5)
1070 ins = table2.insert().from_select(['a', 'b'], sel)
1072 :param names: a sequence of string column names or
1073 :class:`_schema.Column`
1074 objects representing the target columns.
1075 :param select: a :func:`_expression.select` construct,
1076 :class:`_expression.FromClause`
1077 or other construct which resolves into a
1078 :class:`_expression.FromClause`,
1079 such as an ORM :class:`_query.Query` object, etc. The order of
1080 columns returned from this FROM clause should correspond to the
1081 order of columns sent as the ``names`` parameter; while this
1082 is not checked before passing along to the database, the database
1083 would normally raise an exception if these column lists don't
1084 correspond.
1085 :param include_defaults: if True, non-server default values and
1086 SQL expressions as specified on :class:`_schema.Column` objects
1087 (as documented in :ref:`metadata_defaults_toplevel`) not
1088 otherwise specified in the list of names will be rendered
1089 into the INSERT and SELECT statements, so that these values are also
1090 included in the data to be inserted.
1092 .. note:: A Python-side default that uses a Python callable function
1093 will only be invoked **once** for the whole statement, and **not
1094 per row**.
1096 .. versionadded:: 1.0.0 - :meth:`_expression.Insert.from_select`
1097 now renders
1098 Python-side and SQL expression column defaults into the
1099 SELECT statement for columns otherwise not included in the
1100 list of column names.
1102 .. versionchanged:: 1.0.0 an INSERT that uses FROM SELECT
1103 implies that the :paramref:`_expression.insert.inline`
1104 flag is set to
1105 True, indicating that the statement will not attempt to fetch
1106 the "last inserted primary key" or other defaults. The statement
1107 deals with an arbitrary number of rows, so the
1108 :attr:`_engine.CursorResult.inserted_primary_key`
1109 accessor does not apply.
1111 """
1113 if self._values:
1114 raise exc.InvalidRequestError(
1115 "This construct already inserts value expressions"
1116 )
1118 self._select_names = names
1119 self._inline = True
1120 self.include_insert_from_select_defaults = include_defaults
1121 self.select = coercions.expect(roles.DMLSelectRole, select)
1124class DMLWhereBase(object):
1125 _where_criteria = ()
1127 @_generative
1128 def where(self, *whereclause):
1129 """Return a new construct with the given expression(s) added to
1130 its WHERE clause, joined to the existing clause via AND, if any.
1132 Both :meth:`_dml.Update.where` and :meth:`_dml.Delete.where`
1133 support multiple-table forms, including database-specific
1134 ``UPDATE...FROM`` as well as ``DELETE..USING``. For backends that
1135 don't have multiple-table support, a backend agnostic approach
1136 to using multiple tables is to make use of correlated subqueries.
1137 See the linked tutorial sections below for examples.
1139 .. seealso::
1141 :ref:`tutorial_correlated_updates`
1143 :ref:`tutorial_update_from`
1145 :ref:`tutorial_multi_table_deletes`
1147 """
1149 for criterion in whereclause:
1150 where_criteria = coercions.expect(roles.WhereHavingRole, criterion)
1151 self._where_criteria += (where_criteria,)
1153 def filter(self, *criteria):
1154 """A synonym for the :meth:`_dml.DMLWhereBase.where` method.
1156 .. versionadded:: 1.4
1158 """
1160 return self.where(*criteria)
1162 def _filter_by_zero(self):
1163 return self.table
1165 def filter_by(self, **kwargs):
1166 r"""apply the given filtering criterion as a WHERE clause
1167 to this select.
1169 """
1170 from_entity = self._filter_by_zero()
1172 clauses = [
1173 _entity_namespace_key(from_entity, key) == value
1174 for key, value in kwargs.items()
1175 ]
1176 return self.filter(*clauses)
1178 @property
1179 def whereclause(self):
1180 """Return the completed WHERE clause for this :class:`.DMLWhereBase`
1181 statement.
1183 This assembles the current collection of WHERE criteria
1184 into a single :class:`_expression.BooleanClauseList` construct.
1187 .. versionadded:: 1.4
1189 """
1191 return BooleanClauseList._construct_for_whereclause(
1192 self._where_criteria
1193 )
1196class Update(DMLWhereBase, ValuesBase):
1197 """Represent an Update construct.
1199 The :class:`_expression.Update` object is created using the
1200 :func:`_expression.update()` function.
1202 """
1204 __visit_name__ = "update"
1206 is_update = True
1208 _traverse_internals = (
1209 [
1210 ("table", InternalTraversal.dp_clauseelement),
1211 ("_where_criteria", InternalTraversal.dp_clauseelement_list),
1212 ("_inline", InternalTraversal.dp_boolean),
1213 ("_ordered_values", InternalTraversal.dp_dml_ordered_values),
1214 ("_values", InternalTraversal.dp_dml_values),
1215 ("_returning", InternalTraversal.dp_clauseelement_list),
1216 ("_hints", InternalTraversal.dp_table_hint_list),
1217 ("_return_defaults", InternalTraversal.dp_boolean),
1218 (
1219 "_return_defaults_columns",
1220 InternalTraversal.dp_clauseelement_list,
1221 ),
1222 ]
1223 + HasPrefixes._has_prefixes_traverse_internals
1224 + DialectKWArgs._dialect_kwargs_traverse_internals
1225 + Executable._executable_traverse_internals
1226 + HasCTE._has_ctes_traverse_internals
1227 )
1229 @ValuesBase._constructor_20_deprecations(
1230 "update",
1231 "Update",
1232 [
1233 "whereclause",
1234 "values",
1235 "inline",
1236 "bind",
1237 "prefixes",
1238 "returning",
1239 "return_defaults",
1240 "preserve_parameter_order",
1241 ],
1242 )
1243 def __init__(
1244 self,
1245 table,
1246 whereclause=None,
1247 values=None,
1248 inline=False,
1249 bind=None,
1250 prefixes=None,
1251 returning=None,
1252 return_defaults=False,
1253 preserve_parameter_order=False,
1254 **dialect_kw
1255 ):
1256 r"""Construct an :class:`_expression.Update` object.
1258 E.g.::
1260 from sqlalchemy import update
1262 stmt = (
1263 update(user_table).
1264 where(user_table.c.id == 5).
1265 values(name='user #5')
1266 )
1268 Similar functionality is available via the
1269 :meth:`_expression.TableClause.update` method on
1270 :class:`_schema.Table`.
1272 :param table: A :class:`_schema.Table`
1273 object representing the database
1274 table to be updated.
1276 :param whereclause: Optional SQL expression describing the ``WHERE``
1277 condition of the ``UPDATE`` statement; is equivalent to using the
1278 more modern :meth:`~Update.where()` method to specify the ``WHERE``
1279 clause.
1281 :param values:
1282 Optional dictionary which specifies the ``SET`` conditions of the
1283 ``UPDATE``. If left as ``None``, the ``SET``
1284 conditions are determined from those parameters passed to the
1285 statement during the execution and/or compilation of the
1286 statement. When compiled standalone without any parameters,
1287 the ``SET`` clause generates for all columns.
1289 Modern applications may prefer to use the generative
1290 :meth:`_expression.Update.values` method to set the values of the
1291 UPDATE statement.
1293 :param inline:
1294 if True, SQL defaults present on :class:`_schema.Column` objects via
1295 the ``default`` keyword will be compiled 'inline' into the statement
1296 and not pre-executed. This means that their values will not
1297 be available in the dictionary returned from
1298 :meth:`_engine.CursorResult.last_updated_params`.
1300 :param preserve_parameter_order: if True, the update statement is
1301 expected to receive parameters **only** via the
1302 :meth:`_expression.Update.values` method,
1303 and they must be passed as a Python
1304 ``list`` of 2-tuples. The rendered UPDATE statement will emit the SET
1305 clause for each referenced column maintaining this order.
1307 .. versionadded:: 1.0.10
1309 .. seealso::
1311 :ref:`updates_order_parameters` - illustrates the
1312 :meth:`_expression.Update.ordered_values` method.
1314 If both ``values`` and compile-time bind parameters are present, the
1315 compile-time bind parameters override the information specified
1316 within ``values`` on a per-key basis.
1318 The keys within ``values`` can be either :class:`_schema.Column`
1319 objects or their string identifiers (specifically the "key" of the
1320 :class:`_schema.Column`, normally but not necessarily equivalent to
1321 its "name"). Normally, the
1322 :class:`_schema.Column` objects used here are expected to be
1323 part of the target :class:`_schema.Table` that is the table
1324 to be updated. However when using MySQL, a multiple-table
1325 UPDATE statement can refer to columns from any of
1326 the tables referred to in the WHERE clause.
1328 The values referred to in ``values`` are typically:
1330 * a literal data value (i.e. string, number, etc.)
1331 * a SQL expression, such as a related :class:`_schema.Column`,
1332 a scalar-returning :func:`_expression.select` construct,
1333 etc.
1335 When combining :func:`_expression.select` constructs within the
1336 values clause of an :func:`_expression.update`
1337 construct, the subquery represented
1338 by the :func:`_expression.select` should be *correlated* to the
1339 parent table, that is, providing criterion which links the table inside
1340 the subquery to the outer table being updated::
1342 users.update().values(
1343 name=select(addresses.c.email_address).\
1344 where(addresses.c.user_id==users.c.id).\
1345 scalar_subquery()
1346 )
1348 .. seealso::
1350 :ref:`inserts_and_updates` - SQL Expression
1351 Language Tutorial
1354 """
1355 self._preserve_parameter_order = preserve_parameter_order
1356 super(Update, self).__init__(table, values, prefixes)
1357 self._bind = bind
1358 if returning:
1359 self._returning = returning
1360 if whereclause is not None:
1361 self._where_criteria += (
1362 coercions.expect(roles.WhereHavingRole, whereclause),
1363 )
1364 self._inline = inline
1365 if dialect_kw:
1366 self._validate_dialect_kwargs_deprecated(dialect_kw)
1367 self._return_defaults = return_defaults
1369 @_generative
1370 def ordered_values(self, *args):
1371 """Specify the VALUES clause of this UPDATE statement with an explicit
1372 parameter ordering that will be maintained in the SET clause of the
1373 resulting UPDATE statement.
1375 E.g.::
1377 stmt = table.update().ordered_values(
1378 ("name", "ed"), ("ident": "foo")
1379 )
1381 .. seealso::
1383 :ref:`tutorial_parameter_ordered_updates` - full example of the
1384 :meth:`_expression.Update.ordered_values` method.
1386 .. versionchanged:: 1.4 The :meth:`_expression.Update.ordered_values`
1387 method
1388 supersedes the
1389 :paramref:`_expression.update.preserve_parameter_order`
1390 parameter, which will be removed in SQLAlchemy 2.0.
1392 """
1393 if self._values:
1394 raise exc.ArgumentError(
1395 "This statement already has values present"
1396 )
1397 elif self._ordered_values:
1398 raise exc.ArgumentError(
1399 "This statement already has ordered values present"
1400 )
1402 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs
1403 self._ordered_values = kv_generator(self, args)
1405 @_generative
1406 def inline(self):
1407 """Make this :class:`_expression.Update` construct "inline" .
1409 When set, SQL defaults present on :class:`_schema.Column`
1410 objects via the
1411 ``default`` keyword will be compiled 'inline' into the statement and
1412 not pre-executed. This means that their values will not be available
1413 in the dictionary returned from
1414 :meth:`_engine.CursorResult.last_updated_params`.
1416 .. versionchanged:: 1.4 the :paramref:`_expression.update.inline`
1417 parameter
1418 is now superseded by the :meth:`_expression.Update.inline` method.
1420 """
1421 self._inline = True
1424class Delete(DMLWhereBase, UpdateBase):
1425 """Represent a DELETE construct.
1427 The :class:`_expression.Delete` object is created using the
1428 :func:`_expression.delete()` function.
1430 """
1432 __visit_name__ = "delete"
1434 is_delete = True
1436 _traverse_internals = (
1437 [
1438 ("table", InternalTraversal.dp_clauseelement),
1439 ("_where_criteria", InternalTraversal.dp_clauseelement_list),
1440 ("_returning", InternalTraversal.dp_clauseelement_list),
1441 ("_hints", InternalTraversal.dp_table_hint_list),
1442 ]
1443 + HasPrefixes._has_prefixes_traverse_internals
1444 + DialectKWArgs._dialect_kwargs_traverse_internals
1445 + Executable._executable_traverse_internals
1446 + HasCTE._has_ctes_traverse_internals
1447 )
1449 @ValuesBase._constructor_20_deprecations(
1450 "delete",
1451 "Delete",
1452 ["whereclause", "values", "bind", "prefixes", "returning"],
1453 )
1454 def __init__(
1455 self,
1456 table,
1457 whereclause=None,
1458 bind=None,
1459 returning=None,
1460 prefixes=None,
1461 **dialect_kw
1462 ):
1463 r"""Construct :class:`_expression.Delete` object.
1465 E.g.::
1467 from sqlalchemy import delete
1469 stmt = (
1470 delete(user_table).
1471 where(user_table.c.id == 5)
1472 )
1474 Similar functionality is available via the
1475 :meth:`_expression.TableClause.delete` method on
1476 :class:`_schema.Table`.
1478 .. seealso::
1480 :ref:`inserts_and_updates` - in the
1481 :ref:`1.x tutorial <sqlexpression_toplevel>`
1483 :ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
1486 :param table: The table to delete rows from.
1488 :param whereclause: Optional SQL expression describing the ``WHERE``
1489 condition of the ``DELETE`` statement; is equivalent to using the
1490 more modern :meth:`~Delete.where()` method to specify the ``WHERE``
1491 clause.
1493 .. seealso::
1495 :ref:`deletes` - SQL Expression Tutorial
1497 """
1498 self._bind = bind
1499 self.table = coercions.expect(
1500 roles.DMLTableRole, table, apply_propagate_attrs=self
1501 )
1502 if returning:
1503 self._returning = returning
1505 if prefixes:
1506 self._setup_prefixes(prefixes)
1508 if whereclause is not None:
1509 self._where_criteria += (
1510 coercions.expect(roles.WhereHavingRole, whereclause),
1511 )
1513 if dialect_kw:
1514 self._validate_dialect_kwargs_deprecated(dialect_kw)