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