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

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 

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 .selectable import Select 

20from .. import exc 

21from .. import util 

22 

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`. 

29 

30This symbol is typically used when a :func:`_expression.insert` 

31or :func:`_expression.update` statement is compiled without parameter 

32values present. 

33 

34""", 

35) 

36 

37 

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. 

41 

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. 

46 

47 """ 

48 

49 compiler.postfetch = [] 

50 compiler.insert_prefetch = [] 

51 compiler.update_prefetch = [] 

52 compiler.returning = [] 

53 

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) 

62 

63 compiler._key_getters_for_crud_column = getters 

64 

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 ] 

76 

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 

91 

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 ) 

106 

107 # create a list of column assignment clauses as tuples 

108 values = [] 

109 

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 ) 

120 

121 check_columns = {} 

122 

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 ) 

137 

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 ) 

164 

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 ) 

176 

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 ] 

202 

203 return values 

204 

205 

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 

218 

219 

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. 

236 

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 

241 

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 

248 

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) 

254 

255 return value._compiler_dispatch(compiler, **kw) 

256 

257 

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) 

267 

268 c_key_role = functools.partial( 

269 coercions.expect_as_key, roles.DMLColumnRole 

270 ) 

271 

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 

278 

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 

284 

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 

290 

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") 

296 

297 return _column_as_key, _getattr_col_key, _col_bind_name 

298 

299 

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): 

312 

313 ( 

314 need_pks, 

315 implicit_returning, 

316 implicit_return_defaults, 

317 postfetch_lastrowid, 

318 ) = _get_returning_modifiers(compiler, stmt, compile_state) 

319 

320 cols = [stmt.table.c[_column_as_key(name)] for name in stmt._select_names] 

321 

322 assert compiler.stack[-1]["selectable"] is stmt 

323 

324 compiler.stack[-1]["insert_from_select"] = stmt.select 

325 

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) 

332 

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 ) 

342 

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 

361 

362 

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) 

381 

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] 

392 

393 else: 

394 cols = stmt.table.columns 

395 

396 for c in cols: 

397 # scan through every column in the target table 

398 

399 col_key = _getattr_col_key(c) 

400 

401 if col_key in parameters and col_key not in check_columns: 

402 # parameter is present for the column. use that. 

403 

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 ) 

417 

418 elif compile_state.isinsert: 

419 # no parameter is present and it's an insert. 

420 

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. 

425 

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. 

430 

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. 

441 

442 _append_param_insert_pk_no_returning( 

443 compiler, stmt, c, values, kw 

444 ) 

445 

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 ) 

452 

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) 

468 

469 elif compile_state.isupdate: 

470 # no parameter is present and it's an insert. 

471 

472 _append_param_update( 

473 compiler, 

474 compile_state, 

475 stmt, 

476 c, 

477 implicit_return_defaults, 

478 values, 

479 kw, 

480 ) 

481 

482 

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) 

497 

498 col_value = compiler.preparer.format_column( 

499 c, use_table=compile_state.include_table_with_column_exprs 

500 ) 

501 

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) 

526 

527 if compile_state.isupdate: 

528 if implicit_return_defaults and c in implicit_return_defaults: 

529 compiler.returning.append(c) 

530 

531 else: 

532 compiler.postfetch.append(c) 

533 else: 

534 if c.primary_key: 

535 

536 if implicit_returning: 

537 compiler.returning.append(c) 

538 elif compiler.dialect.postfetch_lastrowid: 

539 compiler.postfetch_lastrowid = True 

540 

541 elif implicit_return_defaults and c in implicit_return_defaults: 

542 compiler.returning.append(c) 

543 

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. 

550 

551 compiler.postfetch.append(c) 

552 

553 values.append((c, col_value, value)) 

554 

555 

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. 

560 

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) 

602 

603 

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. 

608 

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. 

612 

613 

614 """ 

615 

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 

678 

679 

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 ) 

706 

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 ) 

720 

721 

722def _append_param_insert_select_hasdefault(compiler, stmt, c, values, kw): 

723 

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 ) 

745 

746 

747def _append_param_update( 

748 compiler, compile_state, stmt, c, implicit_return_defaults, values, kw 

749): 

750 

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) 

790 

791 

792def _create_insert_prefetch_bind_param( 

793 compiler, c, process=True, name=None, **kw 

794): 

795 

796 param = _create_bind_param( 

797 compiler, c, None, process=process, name=name, **kw 

798 ) 

799 compiler.insert_prefetch.append(c) 

800 return param 

801 

802 

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 

811 

812 

813class _multiparam_column(elements.ColumnElement): 

814 _is_multiparam_column = True 

815 

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 

822 

823 def compare(self, other, **kw): 

824 raise NotImplementedError() 

825 

826 def _copy_internals(self, other, **kw): 

827 raise NotImplementedError() 

828 

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 ) 

835 

836 

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) 

862 

863 

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 ) 

879 

880 include_table = compile_state.include_table_with_column_exprs 

881 

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] 

889 

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) 

938 

939 

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] 

950 

951 for i, row in enumerate(compile_state._multi_parameters[1:]): 

952 extension = [] 

953 

954 row = {_column_as_key(key): v for key, v in row.items()} 

955 

956 for (col, col_expr, param) in values_0: 

957 if col.key in row: 

958 key = col.key 

959 

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 ) 

974 

975 extension.append((col, col_expr, new_param)) 

976 

977 values.append(extension) 

978 

979 return values 

980 

981 

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): 

991 

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 

1000 

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. 

1003 

1004 col_expr = compiler.process( 

1005 k, include_table=compile_state.include_table_with_column_exprs 

1006 ) 

1007 

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) 

1018 

1019 v = compiler.process(v.self_group(), **kw) 

1020 

1021 values.append((k, col_expr, v)) 

1022 

1023 

1024def _get_returning_modifiers(compiler, stmt, compile_state): 

1025 

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 ) 

1039 

1040 implicit_returning = ( 

1041 need_pks 

1042 and compiler.dialect.implicit_returning 

1043 and stmt.table.implicit_returning 

1044 ) 

1045 

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 

1058 

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) 

1064 

1065 postfetch_lastrowid = need_pks and compiler.dialect.postfetch_lastrowid 

1066 

1067 return ( 

1068 need_pks, 

1069 implicit_returning, 

1070 implicit_return_defaults, 

1071 postfetch_lastrowid, 

1072 ) 

1073 

1074 

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)