1# sql/crud.py
2# Copyright (C) 2005-2021 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
8"""Functions used by compiler.py to determine the parameters rendered
9within INSERT and UPDATE statements.
10
11"""
12import functools
13import operator
14
15from . import coercions
16from . import dml
17from . import elements
18from . import roles
19from .. import exc
20from .. import util
21
22REQUIRED = util.symbol(
23    "REQUIRED",
24    """
25Placeholder for the value within a :class:`.BindParameter`
26which is required to be present when the statement is passed
27to :meth:`_engine.Connection.execute`.
28
29This symbol is typically used when a :func:`_expression.insert`
30or :func:`_expression.update` statement is compiled without parameter
31values present.
32
33""",
34)
35
36
37def _get_crud_params(compiler, stmt, compile_state, **kw):
38    """create a set of tuples representing column/string pairs for use
39    in an INSERT or UPDATE statement.
40
41    Also generates the Compiled object's postfetch, prefetch, and
42    returning column collections, used for default handling and ultimately
43    populating the CursorResult's prefetch_cols() and postfetch_cols()
44    collections.
45
46    """
47
48    compiler.postfetch = []
49    compiler.insert_prefetch = []
50    compiler.update_prefetch = []
51    compiler.returning = []
52
53    # getters - these are normally just column.key,
54    # but in the case of mysql multi-table update, the rules for
55    # .key must conditionally take tablename into account
56    (
57        _column_as_key,
58        _getattr_col_key,
59        _col_bind_name,
60    ) = getters = _key_getters_for_crud_column(compiler, stmt, compile_state)
61
62    compiler._key_getters_for_crud_column = getters
63
64    # no parameters in the statement, no parameters in the
65    # compiled params - return binds for all columns
66    if compiler.column_keys is None and compile_state._no_parameters:
67        return [
68            (
69                c,
70                compiler.preparer.format_column(c),
71                _create_bind_param(compiler, c, None, required=True),
72            )
73            for c in stmt.table.columns
74        ]
75
76    if compile_state._has_multi_parameters:
77        spd = compile_state._multi_parameters[0]
78        stmt_parameter_tuples = list(spd.items())
79    elif compile_state._ordered_values:
80        spd = compile_state._dict_parameters
81        stmt_parameter_tuples = compile_state._ordered_values
82    elif compile_state._dict_parameters:
83        spd = compile_state._dict_parameters
84        stmt_parameter_tuples = list(spd.items())
85    else:
86        stmt_parameter_tuples = spd = None
87
88    # if we have statement parameters - set defaults in the
89    # compiled params
90    if compiler.column_keys is None:
91        parameters = {}
92    elif stmt_parameter_tuples:
93        parameters = dict(
94            (_column_as_key(key), REQUIRED)
95            for key in compiler.column_keys
96            if key not in spd
97        )
98    else:
99        parameters = dict(
100            (_column_as_key(key), REQUIRED) for key in compiler.column_keys
101        )
102
103    # create a list of column assignment clauses as tuples
104    values = []
105
106    if stmt_parameter_tuples is not None:
107        _get_stmt_parameter_tuples_params(
108            compiler,
109            compile_state,
110            parameters,
111            stmt_parameter_tuples,
112            _column_as_key,
113            values,
114            kw,
115        )
116
117    check_columns = {}
118
119    # special logic that only occurs for multi-table UPDATE
120    # statements
121    if compile_state.isupdate and compile_state.is_multitable:
122        _get_update_multitable_params(
123            compiler,
124            stmt,
125            compile_state,
126            stmt_parameter_tuples,
127            check_columns,
128            _col_bind_name,
129            _getattr_col_key,
130            values,
131            kw,
132        )
133
134    if compile_state.isinsert and stmt._select_names:
135        _scan_insert_from_select_cols(
136            compiler,
137            stmt,
138            compile_state,
139            parameters,
140            _getattr_col_key,
141            _column_as_key,
142            _col_bind_name,
143            check_columns,
144            values,
145            kw,
146        )
147    else:
148        _scan_cols(
149            compiler,
150            stmt,
151            compile_state,
152            parameters,
153            _getattr_col_key,
154            _column_as_key,
155            _col_bind_name,
156            check_columns,
157            values,
158            kw,
159        )
160
161    if parameters and stmt_parameter_tuples:
162        check = (
163            set(parameters)
164            .intersection(_column_as_key(k) for k, v in stmt_parameter_tuples)
165            .difference(check_columns)
166        )
167        if check:
168            raise exc.CompileError(
169                "Unconsumed column names: %s"
170                % (", ".join("%s" % (c,) for c in check))
171            )
172
173    if compile_state._has_multi_parameters:
174        values = _extend_values_for_multiparams(
175            compiler,
176            stmt,
177            compile_state,
178            values,
179            _column_as_key,
180            kw,
181        )
182    elif (
183        not values
184        and compiler.for_executemany
185        and compiler.dialect.supports_default_metavalue
186    ):
187        # convert an "INSERT DEFAULT VALUES"
188        # into INSERT (firstcol) VALUES (DEFAULT) which can be turned
189        # into an in-place multi values.  This supports
190        # insert_executemany_returning mode :)
191        values = [
192            (
193                stmt.table.columns[0],
194                compiler.preparer.format_column(stmt.table.columns[0]),
195                "DEFAULT",
196            )
197        ]
198
199    return values
200
201
202def _create_bind_param(
203    compiler, col, value, process=True, required=False, name=None, **kw
204):
205    if name is None:
206        name = col.key
207    bindparam = elements.BindParameter(
208        name, value, type_=col.type, required=required
209    )
210    bindparam._is_crud = True
211    if process:
212        bindparam = bindparam._compiler_dispatch(compiler, **kw)
213    return bindparam
214
215
216def _handle_values_anonymous_param(compiler, col, value, name, **kw):
217    # the insert() and update() constructs as of 1.4 will now produce anonymous
218    # bindparam() objects in the values() collections up front when given plain
219    # literal values.  This is so that cache key behaviors, which need to
220    # produce bound parameters in deterministic order without invoking any
221    # compilation here, can be applied to these constructs when they include
222    # values() (but not yet multi-values, which are not included in caching
223    # right now).
224    #
225    # in order to produce the desired "crud" style name for these parameters,
226    # which will also be targetable in engine/default.py through the usual
227    # conventions, apply our desired name to these unique parameters by
228    # populating the compiler truncated names cache with the desired name,
229    # rather than having
230    # compiler.visit_bindparam()->compiler._truncated_identifier make up a
231    # name.  Saves on call counts also.
232
233    # for INSERT/UPDATE that's a CTE, we don't need names to match to
234    # external parameters and these would also conflict in the case where
235    # multiple insert/update are combined together using CTEs
236    is_cte = "visiting_cte" in kw
237
238    if (
239        not is_cte
240        and value.unique
241        and isinstance(value.key, elements._truncated_label)
242    ):
243        compiler.truncated_names[("bindparam", value.key)] = name
244
245    if value.type._isnull:
246        # either unique parameter, or other bound parameters that were
247        # passed in directly
248        # set type to that of the column unconditionally
249        value = value._with_binary_element_type(col.type)
250
251    return value._compiler_dispatch(compiler, **kw)
252
253
254def _key_getters_for_crud_column(compiler, stmt, compile_state):
255    if compile_state.isupdate and compile_state._extra_froms:
256        # when extra tables are present, refer to the columns
257        # in those extra tables as table-qualified, including in
258        # dictionaries and when rendering bind param names.
259        # the "main" table of the statement remains unqualified,
260        # allowing the most compatibility with a non-multi-table
261        # statement.
262        _et = set(compile_state._extra_froms)
263
264        c_key_role = functools.partial(
265            coercions.expect_as_key, roles.DMLColumnRole
266        )
267
268        def _column_as_key(key):
269            str_key = c_key_role(key)
270            if hasattr(key, "table") and key.table in _et:
271                return (key.table.name, str_key)
272            else:
273                return str_key
274
275        def _getattr_col_key(col):
276            if col.table in _et:
277                return (col.table.name, col.key)
278            else:
279                return col.key
280
281        def _col_bind_name(col):
282            if col.table in _et:
283                return "%s_%s" % (col.table.name, col.key)
284            else:
285                return col.key
286
287    else:
288        _column_as_key = functools.partial(
289            coercions.expect_as_key, roles.DMLColumnRole
290        )
291        _getattr_col_key = _col_bind_name = operator.attrgetter("key")
292
293    return _column_as_key, _getattr_col_key, _col_bind_name
294
295
296def _scan_insert_from_select_cols(
297    compiler,
298    stmt,
299    compile_state,
300    parameters,
301    _getattr_col_key,
302    _column_as_key,
303    _col_bind_name,
304    check_columns,
305    values,
306    kw,
307):
308
309    (
310        need_pks,
311        implicit_returning,
312        implicit_return_defaults,
313        postfetch_lastrowid,
314    ) = _get_returning_modifiers(compiler, stmt, compile_state)
315
316    cols = [stmt.table.c[_column_as_key(name)] for name in stmt._select_names]
317
318    assert compiler.stack[-1]["selectable"] is stmt
319
320    compiler.stack[-1]["insert_from_select"] = stmt.select
321
322    add_select_cols = []
323    if stmt.include_insert_from_select_defaults:
324        col_set = set(cols)
325        for col in stmt.table.columns:
326            if col not in col_set and col.default:
327                cols.append(col)
328
329    for c in cols:
330        col_key = _getattr_col_key(c)
331        if col_key in parameters and col_key not in check_columns:
332            parameters.pop(col_key)
333            values.append((c, compiler.preparer.format_column(c), None))
334        else:
335            _append_param_insert_select_hasdefault(
336                compiler, stmt, c, add_select_cols, kw
337            )
338
339    if add_select_cols:
340        values.extend(add_select_cols)
341        ins_from_select = compiler.stack[-1]["insert_from_select"]
342        ins_from_select = ins_from_select._generate()
343        ins_from_select._raw_columns = tuple(
344            ins_from_select._raw_columns
345        ) + tuple(expr for col, col_expr, expr in add_select_cols)
346        compiler.stack[-1]["insert_from_select"] = ins_from_select
347
348
349def _scan_cols(
350    compiler,
351    stmt,
352    compile_state,
353    parameters,
354    _getattr_col_key,
355    _column_as_key,
356    _col_bind_name,
357    check_columns,
358    values,
359    kw,
360):
361    (
362        need_pks,
363        implicit_returning,
364        implicit_return_defaults,
365        postfetch_lastrowid,
366    ) = _get_returning_modifiers(compiler, stmt, compile_state)
367
368    if compile_state._parameter_ordering:
369        parameter_ordering = [
370            _column_as_key(key) for key in compile_state._parameter_ordering
371        ]
372        ordered_keys = set(parameter_ordering)
373        cols = [
374            stmt.table.c[key]
375            for key in parameter_ordering
376            if isinstance(key, util.string_types) and key in stmt.table.c
377        ] + [c for c in stmt.table.c if c.key not in ordered_keys]
378
379    else:
380        cols = stmt.table.columns
381
382    for c in cols:
383        # scan through every column in the target table
384
385        col_key = _getattr_col_key(c)
386
387        if col_key in parameters and col_key not in check_columns:
388            # parameter is present for the column.  use that.
389
390            _append_param_parameter(
391                compiler,
392                stmt,
393                compile_state,
394                c,
395                col_key,
396                parameters,
397                _col_bind_name,
398                implicit_returning,
399                implicit_return_defaults,
400                values,
401                kw,
402            )
403
404        elif compile_state.isinsert:
405            # no parameter is present and it's an insert.
406
407            if c.primary_key and need_pks:
408                # it's a primary key column, it will need to be generated by a
409                # default generator of some kind, and the statement expects
410                # inserted_primary_key to be available.
411
412                if implicit_returning:
413                    # we can use RETURNING, find out how to invoke this
414                    # column and get the value where RETURNING is an option.
415                    # we can inline server-side functions in this case.
416
417                    _append_param_insert_pk_returning(
418                        compiler, stmt, c, values, kw
419                    )
420                else:
421                    # otherwise, find out how to invoke this column
422                    # and get its value where RETURNING is not an option.
423                    # if we have to invoke a server-side function, we need
424                    # to pre-execute it.   or if this is a straight
425                    # autoincrement column and the dialect supports it
426                    # we can use cursor.lastrowid.
427
428                    _append_param_insert_pk_no_returning(
429                        compiler, stmt, c, values, kw
430                    )
431
432            elif c.default is not None:
433                # column has a default, but it's not a pk column, or it is but
434                # we don't need to get the pk back.
435                _append_param_insert_hasdefault(
436                    compiler, stmt, c, implicit_return_defaults, values, kw
437                )
438
439            elif c.server_default is not None:
440                # column has a DDL-level default, and is either not a pk
441                # column or we don't need the pk.
442                if implicit_return_defaults and c in implicit_return_defaults:
443                    compiler.returning.append(c)
444                elif not c.primary_key:
445                    compiler.postfetch.append(c)
446            elif implicit_return_defaults and c in implicit_return_defaults:
447                compiler.returning.append(c)
448            elif (
449                c.primary_key
450                and c is not stmt.table._autoincrement_column
451                and not c.nullable
452            ):
453                _warn_pk_with_no_anticipated_value(c)
454
455        elif compile_state.isupdate:
456            # no parameter is present and it's an insert.
457
458            _append_param_update(
459                compiler,
460                compile_state,
461                stmt,
462                c,
463                implicit_return_defaults,
464                values,
465                kw,
466            )
467
468
469def _append_param_parameter(
470    compiler,
471    stmt,
472    compile_state,
473    c,
474    col_key,
475    parameters,
476    _col_bind_name,
477    implicit_returning,
478    implicit_return_defaults,
479    values,
480    kw,
481):
482    value = parameters.pop(col_key)
483
484    col_value = compiler.preparer.format_column(
485        c, use_table=compile_state.include_table_with_column_exprs
486    )
487
488    if coercions._is_literal(value):
489        value = _create_bind_param(
490            compiler,
491            c,
492            value,
493            required=value is REQUIRED,
494            name=_col_bind_name(c)
495            if not compile_state._has_multi_parameters
496            else "%s_m0" % _col_bind_name(c),
497            **kw
498        )
499    elif value._is_bind_parameter:
500        value = _handle_values_anonymous_param(
501            compiler,
502            c,
503            value,
504            name=_col_bind_name(c)
505            if not compile_state._has_multi_parameters
506            else "%s_m0" % _col_bind_name(c),
507            **kw
508        )
509    else:
510        # value is a SQL expression
511        value = compiler.process(value.self_group(), **kw)
512
513        if compile_state.isupdate:
514            if implicit_return_defaults and c in implicit_return_defaults:
515                compiler.returning.append(c)
516
517            else:
518                compiler.postfetch.append(c)
519        else:
520            if c.primary_key:
521
522                if implicit_returning:
523                    compiler.returning.append(c)
524                elif compiler.dialect.postfetch_lastrowid:
525                    compiler.postfetch_lastrowid = True
526
527            elif implicit_return_defaults and c in implicit_return_defaults:
528                compiler.returning.append(c)
529
530            else:
531                # postfetch specifically means, "we can SELECT the row we just
532                # inserted by primary key to get back the server generated
533                # defaults". so by definition this can't be used to get the
534                # primary key value back, because we need to have it ahead of
535                # time.
536
537                compiler.postfetch.append(c)
538
539    values.append((c, col_value, value))
540
541
542def _append_param_insert_pk_returning(compiler, stmt, c, values, kw):
543    """Create a primary key expression in the INSERT statement where
544    we want to populate result.inserted_primary_key and RETURNING
545    is available.
546
547    """
548    if c.default is not None:
549        if c.default.is_sequence:
550            if compiler.dialect.supports_sequences and (
551                not c.default.optional
552                or not compiler.dialect.sequences_optional
553            ):
554                values.append(
555                    (
556                        c,
557                        compiler.preparer.format_column(c),
558                        compiler.process(c.default, **kw),
559                    )
560                )
561            compiler.returning.append(c)
562        elif c.default.is_clause_element:
563            values.append(
564                (
565                    c,
566                    compiler.preparer.format_column(c),
567                    compiler.process(c.default.arg.self_group(), **kw),
568                )
569            )
570            compiler.returning.append(c)
571        else:
572            # client side default.  OK we can't use RETURNING, need to
573            # do a "prefetch", which in fact fetches the default value
574            # on the Python side
575            values.append(
576                (
577                    c,
578                    compiler.preparer.format_column(c),
579                    _create_insert_prefetch_bind_param(compiler, c, **kw),
580                )
581            )
582    elif c is stmt.table._autoincrement_column or c.server_default is not None:
583        compiler.returning.append(c)
584    elif not c.nullable:
585        # no .default, no .server_default, not autoincrement, we have
586        # no indication this primary key column will have any value
587        _warn_pk_with_no_anticipated_value(c)
588
589
590def _append_param_insert_pk_no_returning(compiler, stmt, c, values, kw):
591    """Create a primary key expression in the INSERT statement where
592    we want to populate result.inserted_primary_key and we cannot use
593    RETURNING.
594
595    Depending on the kind of default here we may create a bound parameter
596    in the INSERT statement and pre-execute a default generation function,
597    or we may use cursor.lastrowid if supported by the dialect.
598
599
600    """
601
602    if (
603        # column has a Python-side default
604        c.default is not None
605        and (
606            # and it either is not a sequence, or it is and we support
607            # sequences and want to invoke it
608            not c.default.is_sequence
609            or (
610                compiler.dialect.supports_sequences
611                and (
612                    not c.default.optional
613                    or not compiler.dialect.sequences_optional
614                )
615            )
616        )
617    ) or (
618        # column is the "autoincrement column"
619        c is stmt.table._autoincrement_column
620        and (
621            # dialect can't use cursor.lastrowid
622            not compiler.dialect.postfetch_lastrowid
623            and (
624                # column has a Sequence and we support those
625                (
626                    c.default is not None
627                    and c.default.is_sequence
628                    and compiler.dialect.supports_sequences
629                )
630                or
631                # column has no default on it, but dialect can run the
632                # "autoincrement" mechanism explicitly, e.g. PostgreSQL
633                # SERIAL we know the sequence name
634                (
635                    c.default is None
636                    and compiler.dialect.preexecute_autoincrement_sequences
637                )
638            )
639        )
640    ):
641        # do a pre-execute of the default
642        values.append(
643            (
644                c,
645                compiler.preparer.format_column(c),
646                _create_insert_prefetch_bind_param(compiler, c, **kw),
647            )
648        )
649    elif (
650        c.default is None
651        and c.server_default is None
652        and not c.nullable
653        and c is not stmt.table._autoincrement_column
654    ):
655        # no .default, no .server_default, not autoincrement, we have
656        # no indication this primary key column will have any value
657        _warn_pk_with_no_anticipated_value(c)
658    elif compiler.dialect.postfetch_lastrowid:
659        # finally, where it seems like there will be a generated primary key
660        # value and we haven't set up any other way to fetch it, and the
661        # dialect supports cursor.lastrowid, switch on the lastrowid flag so
662        # that the DefaultExecutionContext calls upon cursor.lastrowid
663        compiler.postfetch_lastrowid = True
664
665
666def _append_param_insert_hasdefault(
667    compiler, stmt, c, implicit_return_defaults, values, kw
668):
669    if c.default.is_sequence:
670        if compiler.dialect.supports_sequences and (
671            not c.default.optional or not compiler.dialect.sequences_optional
672        ):
673            values.append(
674                (
675                    c,
676                    compiler.preparer.format_column(c),
677                    compiler.process(c.default, **kw),
678                )
679            )
680            if implicit_return_defaults and c in implicit_return_defaults:
681                compiler.returning.append(c)
682            elif not c.primary_key:
683                compiler.postfetch.append(c)
684    elif c.default.is_clause_element:
685        values.append(
686            (
687                c,
688                compiler.preparer.format_column(c),
689                compiler.process(c.default.arg.self_group(), **kw),
690            )
691        )
692
693        if implicit_return_defaults and c in implicit_return_defaults:
694            compiler.returning.append(c)
695        elif not c.primary_key:
696            # don't add primary key column to postfetch
697            compiler.postfetch.append(c)
698    else:
699        values.append(
700            (
701                c,
702                compiler.preparer.format_column(c),
703                _create_insert_prefetch_bind_param(compiler, c, **kw),
704            )
705        )
706
707
708def _append_param_insert_select_hasdefault(compiler, stmt, c, values, kw):
709
710    if c.default.is_sequence:
711        if compiler.dialect.supports_sequences and (
712            not c.default.optional or not compiler.dialect.sequences_optional
713        ):
714            values.append(
715                (c, compiler.preparer.format_column(c), c.default.next_value())
716            )
717    elif c.default.is_clause_element:
718        values.append(
719            (c, compiler.preparer.format_column(c), c.default.arg.self_group())
720        )
721    else:
722        values.append(
723            (
724                c,
725                compiler.preparer.format_column(c),
726                _create_insert_prefetch_bind_param(
727                    compiler, c, process=False, **kw
728                ),
729            )
730        )
731
732
733def _append_param_update(
734    compiler, compile_state, stmt, c, implicit_return_defaults, values, kw
735):
736
737    include_table = compile_state.include_table_with_column_exprs
738    if c.onupdate is not None and not c.onupdate.is_sequence:
739        if c.onupdate.is_clause_element:
740            values.append(
741                (
742                    c,
743                    compiler.preparer.format_column(
744                        c,
745                        use_table=include_table,
746                    ),
747                    compiler.process(c.onupdate.arg.self_group(), **kw),
748                )
749            )
750            if implicit_return_defaults and c in implicit_return_defaults:
751                compiler.returning.append(c)
752            else:
753                compiler.postfetch.append(c)
754        else:
755            values.append(
756                (
757                    c,
758                    compiler.preparer.format_column(
759                        c,
760                        use_table=include_table,
761                    ),
762                    _create_update_prefetch_bind_param(compiler, c, **kw),
763                )
764            )
765    elif c.server_onupdate is not None:
766        if implicit_return_defaults and c in implicit_return_defaults:
767            compiler.returning.append(c)
768        else:
769            compiler.postfetch.append(c)
770    elif (
771        implicit_return_defaults
772        and (stmt._return_defaults_columns or not stmt._return_defaults)
773        and c in implicit_return_defaults
774    ):
775        compiler.returning.append(c)
776
777
778def _create_insert_prefetch_bind_param(
779    compiler, c, process=True, name=None, **kw
780):
781
782    param = _create_bind_param(
783        compiler, c, None, process=process, name=name, **kw
784    )
785    compiler.insert_prefetch.append(c)
786    return param
787
788
789def _create_update_prefetch_bind_param(
790    compiler, c, process=True, name=None, **kw
791):
792    param = _create_bind_param(
793        compiler, c, None, process=process, name=name, **kw
794    )
795    compiler.update_prefetch.append(c)
796    return param
797
798
799class _multiparam_column(elements.ColumnElement):
800    _is_multiparam_column = True
801
802    def __init__(self, original, index):
803        self.index = index
804        self.key = "%s_m%d" % (original.key, index + 1)
805        self.original = original
806        self.default = original.default
807        self.type = original.type
808
809    def compare(self, other, **kw):
810        raise NotImplementedError()
811
812    def _copy_internals(self, other, **kw):
813        raise NotImplementedError()
814
815    def __eq__(self, other):
816        return (
817            isinstance(other, _multiparam_column)
818            and other.key == self.key
819            and other.original == self.original
820        )
821
822
823def _process_multiparam_default_bind(compiler, stmt, c, index, kw):
824    if not c.default:
825        raise exc.CompileError(
826            "INSERT value for column %s is explicitly rendered as a bound"
827            "parameter in the VALUES clause; "
828            "a Python-side value or SQL expression is required" % c
829        )
830    elif c.default.is_clause_element:
831        return compiler.process(c.default.arg.self_group(), **kw)
832    elif c.default.is_sequence:
833        # these conditions would have been established
834        # by append_param_insert_(?:hasdefault|pk_returning|pk_no_returning)
835        # in order for us to be here, so these don't need to be
836        # checked
837        # assert compiler.dialect.supports_sequences and (
838        #    not c.default.optional
839        #    or not compiler.dialect.sequences_optional
840        # )
841        return compiler.process(c.default, **kw)
842    else:
843        col = _multiparam_column(c, index)
844        if isinstance(stmt, dml.Insert):
845            return _create_insert_prefetch_bind_param(compiler, col, **kw)
846        else:
847            return _create_update_prefetch_bind_param(compiler, col, **kw)
848
849
850def _get_update_multitable_params(
851    compiler,
852    stmt,
853    compile_state,
854    stmt_parameter_tuples,
855    check_columns,
856    _col_bind_name,
857    _getattr_col_key,
858    values,
859    kw,
860):
861    normalized_params = dict(
862        (coercions.expect(roles.DMLColumnRole, c), param)
863        for c, param in stmt_parameter_tuples
864    )
865
866    include_table = compile_state.include_table_with_column_exprs
867
868    affected_tables = set()
869    for t in compile_state._extra_froms:
870        for c in t.c:
871            if c in normalized_params:
872                affected_tables.add(t)
873                check_columns[_getattr_col_key(c)] = c
874                value = normalized_params[c]
875
876                col_value = compiler.process(c, include_table=include_table)
877                if coercions._is_literal(value):
878                    value = _create_bind_param(
879                        compiler,
880                        c,
881                        value,
882                        required=value is REQUIRED,
883                        name=_col_bind_name(c),
884                        **kw  # TODO: no test coverage for literal binds here
885                    )
886                elif value._is_bind_parameter:
887                    value = _handle_values_anonymous_param(
888                        compiler, c, value, name=_col_bind_name(c), **kw
889                    )
890                else:
891                    compiler.postfetch.append(c)
892                    value = compiler.process(value.self_group(), **kw)
893                values.append((c, col_value, value))
894    # determine tables which are actually to be updated - process onupdate
895    # and server_onupdate for these
896    for t in affected_tables:
897        for c in t.c:
898            if c in normalized_params:
899                continue
900            elif c.onupdate is not None and not c.onupdate.is_sequence:
901                if c.onupdate.is_clause_element:
902                    values.append(
903                        (
904                            c,
905                            compiler.process(c, include_table=include_table),
906                            compiler.process(
907                                c.onupdate.arg.self_group(), **kw
908                            ),
909                        )
910                    )
911                    compiler.postfetch.append(c)
912                else:
913                    values.append(
914                        (
915                            c,
916                            compiler.process(c, include_table=include_table),
917                            _create_update_prefetch_bind_param(
918                                compiler, c, name=_col_bind_name(c), **kw
919                            ),
920                        )
921                    )
922            elif c.server_onupdate is not None:
923                compiler.postfetch.append(c)
924
925
926def _extend_values_for_multiparams(
927    compiler,
928    stmt,
929    compile_state,
930    values,
931    _column_as_key,
932    kw,
933):
934    values_0 = values
935    values = [values]
936
937    for i, row in enumerate(compile_state._multi_parameters[1:]):
938        extension = []
939
940        row = {_column_as_key(key): v for key, v in row.items()}
941
942        for (col, col_expr, param) in values_0:
943            if col.key in row:
944                key = col.key
945
946                if coercions._is_literal(row[key]):
947                    new_param = _create_bind_param(
948                        compiler,
949                        col,
950                        row[key],
951                        name="%s_m%d" % (col.key, i + 1),
952                        **kw
953                    )
954                else:
955                    new_param = compiler.process(row[key].self_group(), **kw)
956            else:
957                new_param = _process_multiparam_default_bind(
958                    compiler, stmt, col, i, kw
959                )
960
961            extension.append((col, col_expr, new_param))
962
963        values.append(extension)
964
965    return values
966
967
968def _get_stmt_parameter_tuples_params(
969    compiler,
970    compile_state,
971    parameters,
972    stmt_parameter_tuples,
973    _column_as_key,
974    values,
975    kw,
976):
977
978    for k, v in stmt_parameter_tuples:
979        colkey = _column_as_key(k)
980        if colkey is not None:
981            parameters.setdefault(colkey, v)
982        else:
983            # a non-Column expression on the left side;
984            # add it to values() in an "as-is" state,
985            # coercing right side to bound param
986
987            # note one of the main use cases for this is array slice
988            # updates on PostgreSQL, as the left side is also an expression.
989
990            col_expr = compiler.process(
991                k, include_table=compile_state.include_table_with_column_exprs
992            )
993
994            if coercions._is_literal(v):
995                v = compiler.process(
996                    elements.BindParameter(None, v, type_=k.type), **kw
997                )
998            else:
999                if v._is_bind_parameter and v.type._isnull:
1000                    # either unique parameter, or other bound parameters that
1001                    # were passed in directly
1002                    # set type to that of the column unconditionally
1003                    v = v._with_binary_element_type(k.type)
1004
1005                v = compiler.process(v.self_group(), **kw)
1006
1007            values.append((k, col_expr, v))
1008
1009
1010def _get_returning_modifiers(compiler, stmt, compile_state):
1011
1012    need_pks = (
1013        compile_state.isinsert
1014        and not stmt._inline
1015        and (
1016            not compiler.for_executemany
1017            or (
1018                compiler.dialect.insert_executemany_returning
1019                and stmt._return_defaults
1020            )
1021        )
1022        and not stmt._returning
1023        and not compile_state._has_multi_parameters
1024    )
1025
1026    implicit_returning = (
1027        need_pks
1028        and compiler.dialect.implicit_returning
1029        and stmt.table.implicit_returning
1030    )
1031
1032    if compile_state.isinsert:
1033        implicit_return_defaults = implicit_returning and stmt._return_defaults
1034    elif compile_state.isupdate:
1035        implicit_return_defaults = (
1036            compiler.dialect.implicit_returning
1037            and stmt.table.implicit_returning
1038            and stmt._return_defaults
1039        )
1040    else:
1041        # this line is unused, currently we are always
1042        # isinsert or isupdate
1043        implicit_return_defaults = False  # pragma: no cover
1044
1045    if implicit_return_defaults:
1046        if not stmt._return_defaults_columns:
1047            implicit_return_defaults = set(stmt.table.c)
1048        else:
1049            implicit_return_defaults = set(stmt._return_defaults_columns)
1050
1051    postfetch_lastrowid = need_pks and compiler.dialect.postfetch_lastrowid
1052
1053    return (
1054        need_pks,
1055        implicit_returning,
1056        implicit_return_defaults,
1057        postfetch_lastrowid,
1058    )
1059
1060
1061def _warn_pk_with_no_anticipated_value(c):
1062    msg = (
1063        "Column '%s.%s' is marked as a member of the "
1064        "primary key for table '%s', "
1065        "but has no Python-side or server-side default generator indicated, "
1066        "nor does it indicate 'autoincrement=True' or 'nullable=True', "
1067        "and no explicit value is passed.  "
1068        "Primary key columns typically may not store NULL."
1069        % (c.table.fullname, c.name, c.table.fullname)
1070    )
1071    if len(c.table.primary_key) > 1:
1072        msg += (
1073            " Note that as of SQLAlchemy 1.1, 'autoincrement=True' must be "
1074            "indicated explicitly for composite (e.g. multicolumn) primary "
1075            "keys if AUTO_INCREMENT/SERIAL/IDENTITY "
1076            "behavior is expected for one of the columns in the primary key. "
1077            "CREATE TABLE statements are impacted by this change as well on "
1078            "most backends."
1079        )
1080    util.warn(msg)
1081