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