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