Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/sql/crud.py: 11%

329 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1# sql/crud.py 

2# Copyright (C) 2005-2022 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

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 elif compile_state._ordered_values: 

81 spd = compile_state._dict_parameters 

82 stmt_parameter_tuples = compile_state._ordered_values 

83 elif compile_state._dict_parameters: 

84 spd = compile_state._dict_parameters 

85 stmt_parameter_tuples = list(spd.items()) 

86 else: 

87 stmt_parameter_tuples = spd = None 

88 

89 # if we have statement parameters - set defaults in the 

90 # compiled params 

91 if compiler.column_keys is None: 

92 parameters = {} 

93 elif stmt_parameter_tuples: 

94 parameters = dict( 

95 (_column_as_key(key), REQUIRED) 

96 for key in compiler.column_keys 

97 if key not in spd 

98 ) 

99 else: 

100 parameters = dict( 

101 (_column_as_key(key), REQUIRED) for key in compiler.column_keys 

102 ) 

103 

104 # create a list of column assignment clauses as tuples 

105 values = [] 

106 

107 if stmt_parameter_tuples is not None: 

108 _get_stmt_parameter_tuples_params( 

109 compiler, 

110 compile_state, 

111 parameters, 

112 stmt_parameter_tuples, 

113 _column_as_key, 

114 values, 

115 kw, 

116 ) 

117 

118 check_columns = {} 

119 

120 # special logic that only occurs for multi-table UPDATE 

121 # statements 

122 if compile_state.isupdate and compile_state.is_multitable: 

123 _get_update_multitable_params( 

124 compiler, 

125 stmt, 

126 compile_state, 

127 stmt_parameter_tuples, 

128 check_columns, 

129 _col_bind_name, 

130 _getattr_col_key, 

131 values, 

132 kw, 

133 ) 

134 

135 if compile_state.isinsert and stmt._select_names: 

136 _scan_insert_from_select_cols( 

137 compiler, 

138 stmt, 

139 compile_state, 

140 parameters, 

141 _getattr_col_key, 

142 _column_as_key, 

143 _col_bind_name, 

144 check_columns, 

145 values, 

146 kw, 

147 ) 

148 else: 

149 _scan_cols( 

150 compiler, 

151 stmt, 

152 compile_state, 

153 parameters, 

154 _getattr_col_key, 

155 _column_as_key, 

156 _col_bind_name, 

157 check_columns, 

158 values, 

159 kw, 

160 ) 

161 

162 if parameters and stmt_parameter_tuples: 

163 check = ( 

164 set(parameters) 

165 .intersection(_column_as_key(k) for k, v in stmt_parameter_tuples) 

166 .difference(check_columns) 

167 ) 

168 if check: 

169 raise exc.CompileError( 

170 "Unconsumed column names: %s" 

171 % (", ".join("%s" % (c,) for c in check)) 

172 ) 

173 

174 if compile_state._has_multi_parameters: 

175 values = _extend_values_for_multiparams( 

176 compiler, 

177 stmt, 

178 compile_state, 

179 values, 

180 _column_as_key, 

181 kw, 

182 ) 

183 elif ( 

184 not values 

185 and compiler.for_executemany 

186 and compiler.dialect.supports_default_metavalue 

187 ): 

188 # convert an "INSERT DEFAULT VALUES" 

189 # into INSERT (firstcol) VALUES (DEFAULT) which can be turned 

190 # into an in-place multi values. This supports 

191 # insert_executemany_returning mode :) 

192 values = [ 

193 ( 

194 stmt.table.columns[0], 

195 compiler.preparer.format_column(stmt.table.columns[0]), 

196 "DEFAULT", 

197 ) 

198 ] 

199 

200 return values 

201 

202 

203def _create_bind_param( 

204 compiler, col, value, process=True, required=False, name=None, **kw 

205): 

206 if name is None: 

207 name = col.key 

208 bindparam = elements.BindParameter( 

209 name, value, type_=col.type, required=required 

210 ) 

211 bindparam._is_crud = True 

212 if process: 

213 bindparam = bindparam._compiler_dispatch(compiler, **kw) 

214 return bindparam 

215 

216 

217def _handle_values_anonymous_param(compiler, col, value, name, **kw): 

218 # the insert() and update() constructs as of 1.4 will now produce anonymous 

219 # bindparam() objects in the values() collections up front when given plain 

220 # literal values. This is so that cache key behaviors, which need to 

221 # produce bound parameters in deterministic order without invoking any 

222 # compilation here, can be applied to these constructs when they include 

223 # values() (but not yet multi-values, which are not included in caching 

224 # right now). 

225 # 

226 # in order to produce the desired "crud" style name for these parameters, 

227 # which will also be targetable in engine/default.py through the usual 

228 # conventions, apply our desired name to these unique parameters by 

229 # populating the compiler truncated names cache with the desired name, 

230 # rather than having 

231 # compiler.visit_bindparam()->compiler._truncated_identifier make up a 

232 # name. Saves on call counts also. 

233 

234 # for INSERT/UPDATE that's a CTE, we don't need names to match to 

235 # external parameters and these would also conflict in the case where 

236 # multiple insert/update are combined together using CTEs 

237 is_cte = "visiting_cte" in kw 

238 

239 if ( 

240 not is_cte 

241 and value.unique 

242 and isinstance(value.key, elements._truncated_label) 

243 ): 

244 compiler.truncated_names[("bindparam", value.key)] = name 

245 

246 if value.type._isnull: 

247 # either unique parameter, or other bound parameters that were 

248 # passed in directly 

249 # set type to that of the column unconditionally 

250 value = value._with_binary_element_type(col.type) 

251 

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

253 

254 

255def _key_getters_for_crud_column(compiler, stmt, compile_state): 

256 if compile_state.isupdate and compile_state._extra_froms: 

257 # when extra tables are present, refer to the columns 

258 # in those extra tables as table-qualified, including in 

259 # dictionaries and when rendering bind param names. 

260 # the "main" table of the statement remains unqualified, 

261 # allowing the most compatibility with a non-multi-table 

262 # statement. 

263 _et = set(compile_state._extra_froms) 

264 

265 c_key_role = functools.partial( 

266 coercions.expect_as_key, roles.DMLColumnRole 

267 ) 

268 

269 def _column_as_key(key): 

270 str_key = c_key_role(key) 

271 if hasattr(key, "table") and key.table in _et: 

272 return (key.table.name, str_key) 

273 else: 

274 return str_key 

275 

276 def _getattr_col_key(col): 

277 if col.table in _et: 

278 return (col.table.name, col.key) 

279 else: 

280 return col.key 

281 

282 def _col_bind_name(col): 

283 if col.table in _et: 

284 return "%s_%s" % (col.table.name, col.key) 

285 else: 

286 return col.key 

287 

288 else: 

289 _column_as_key = functools.partial( 

290 coercions.expect_as_key, roles.DMLColumnRole 

291 ) 

292 _getattr_col_key = _col_bind_name = operator.attrgetter("key") 

293 

294 return _column_as_key, _getattr_col_key, _col_bind_name 

295 

296 

297def _scan_insert_from_select_cols( 

298 compiler, 

299 stmt, 

300 compile_state, 

301 parameters, 

302 _getattr_col_key, 

303 _column_as_key, 

304 _col_bind_name, 

305 check_columns, 

306 values, 

307 kw, 

308): 

309 

310 ( 

311 need_pks, 

312 implicit_returning, 

313 implicit_return_defaults, 

314 postfetch_lastrowid, 

315 ) = _get_returning_modifiers(compiler, stmt, compile_state) 

316 

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

318 

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

320 

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

322 

323 add_select_cols = [] 

324 if stmt.include_insert_from_select_defaults: 

325 col_set = set(cols) 

326 for col in stmt.table.columns: 

327 if col not in col_set and col.default: 

328 cols.append(col) 

329 

330 for c in cols: 

331 col_key = _getattr_col_key(c) 

332 if col_key in parameters and col_key not in check_columns: 

333 parameters.pop(col_key) 

334 values.append((c, compiler.preparer.format_column(c), None)) 

335 else: 

336 _append_param_insert_select_hasdefault( 

337 compiler, stmt, c, add_select_cols, kw 

338 ) 

339 

340 if add_select_cols: 

341 values.extend(add_select_cols) 

342 ins_from_select = compiler.stack[-1]["insert_from_select"] 

343 if not isinstance(ins_from_select, Select): 

344 raise exc.CompileError( 

345 "Can't extend statement for INSERT..FROM SELECT to include " 

346 "additional default-holding column(s) " 

347 "%s. Convert the selectable to a subquery() first, or pass " 

348 "include_defaults=False to Insert.from_select() to skip these " 

349 "columns." 

350 % (", ".join(repr(key) for _, key, _ in add_select_cols),) 

351 ) 

352 ins_from_select = ins_from_select._generate() 

353 # copy raw_columns 

354 ins_from_select._raw_columns = list(ins_from_select._raw_columns) + [ 

355 expr for col, col_expr, expr in add_select_cols 

356 ] 

357 compiler.stack[-1]["insert_from_select"] = ins_from_select 

358 

359 

360def _scan_cols( 

361 compiler, 

362 stmt, 

363 compile_state, 

364 parameters, 

365 _getattr_col_key, 

366 _column_as_key, 

367 _col_bind_name, 

368 check_columns, 

369 values, 

370 kw, 

371): 

372 ( 

373 need_pks, 

374 implicit_returning, 

375 implicit_return_defaults, 

376 postfetch_lastrowid, 

377 ) = _get_returning_modifiers(compiler, stmt, compile_state) 

378 

379 if compile_state._parameter_ordering: 

380 parameter_ordering = [ 

381 _column_as_key(key) for key in compile_state._parameter_ordering 

382 ] 

383 ordered_keys = set(parameter_ordering) 

384 cols = [ 

385 stmt.table.c[key] 

386 for key in parameter_ordering 

387 if isinstance(key, util.string_types) and key in stmt.table.c 

388 ] + [c for c in stmt.table.c if c.key not in ordered_keys] 

389 

390 else: 

391 cols = stmt.table.columns 

392 

393 for c in cols: 

394 # scan through every column in the target table 

395 

396 col_key = _getattr_col_key(c) 

397 

398 if col_key in parameters and col_key not in check_columns: 

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

400 

401 _append_param_parameter( 

402 compiler, 

403 stmt, 

404 compile_state, 

405 c, 

406 col_key, 

407 parameters, 

408 _col_bind_name, 

409 implicit_returning, 

410 implicit_return_defaults, 

411 values, 

412 kw, 

413 ) 

414 

415 elif compile_state.isinsert: 

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

417 

418 if c.primary_key and need_pks: 

419 # it's a primary key column, it will need to be generated by a 

420 # default generator of some kind, and the statement expects 

421 # inserted_primary_key to be available. 

422 

423 if implicit_returning: 

424 # we can use RETURNING, find out how to invoke this 

425 # column and get the value where RETURNING is an option. 

426 # we can inline server-side functions in this case. 

427 

428 _append_param_insert_pk_returning( 

429 compiler, stmt, c, values, kw 

430 ) 

431 else: 

432 # otherwise, find out how to invoke this column 

433 # and get its value where RETURNING is not an option. 

434 # if we have to invoke a server-side function, we need 

435 # to pre-execute it. or if this is a straight 

436 # autoincrement column and the dialect supports it 

437 # we can use cursor.lastrowid. 

438 

439 _append_param_insert_pk_no_returning( 

440 compiler, stmt, c, values, kw 

441 ) 

442 

443 elif c.default is not None: 

444 # column has a default, but it's not a pk column, or it is but 

445 # we don't need to get the pk back. 

446 _append_param_insert_hasdefault( 

447 compiler, stmt, c, implicit_return_defaults, values, kw 

448 ) 

449 

450 elif c.server_default is not None: 

451 # column has a DDL-level default, and is either not a pk 

452 # column or we don't need the pk. 

453 if implicit_return_defaults and c in implicit_return_defaults: 

454 compiler.returning.append(c) 

455 elif not c.primary_key: 

456 compiler.postfetch.append(c) 

457 elif implicit_return_defaults and c in implicit_return_defaults: 

458 compiler.returning.append(c) 

459 elif ( 

460 c.primary_key 

461 and c is not stmt.table._autoincrement_column 

462 and not c.nullable 

463 ): 

464 _warn_pk_with_no_anticipated_value(c) 

465 

466 elif compile_state.isupdate: 

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

468 

469 _append_param_update( 

470 compiler, 

471 compile_state, 

472 stmt, 

473 c, 

474 implicit_return_defaults, 

475 values, 

476 kw, 

477 ) 

478 

479 

480def _append_param_parameter( 

481 compiler, 

482 stmt, 

483 compile_state, 

484 c, 

485 col_key, 

486 parameters, 

487 _col_bind_name, 

488 implicit_returning, 

489 implicit_return_defaults, 

490 values, 

491 kw, 

492): 

493 value = parameters.pop(col_key) 

494 

495 col_value = compiler.preparer.format_column( 

496 c, use_table=compile_state.include_table_with_column_exprs 

497 ) 

498 

499 if coercions._is_literal(value): 

500 value = _create_bind_param( 

501 compiler, 

502 c, 

503 value, 

504 required=value is REQUIRED, 

505 name=_col_bind_name(c) 

506 if not compile_state._has_multi_parameters 

507 else "%s_m0" % _col_bind_name(c), 

508 **kw 

509 ) 

510 elif value._is_bind_parameter: 

511 value = _handle_values_anonymous_param( 

512 compiler, 

513 c, 

514 value, 

515 name=_col_bind_name(c) 

516 if not compile_state._has_multi_parameters 

517 else "%s_m0" % _col_bind_name(c), 

518 **kw 

519 ) 

520 else: 

521 # value is a SQL expression 

522 value = compiler.process(value.self_group(), **kw) 

523 

524 if compile_state.isupdate: 

525 if implicit_return_defaults and c in implicit_return_defaults: 

526 compiler.returning.append(c) 

527 

528 else: 

529 compiler.postfetch.append(c) 

530 else: 

531 if c.primary_key: 

532 

533 if implicit_returning: 

534 compiler.returning.append(c) 

535 elif compiler.dialect.postfetch_lastrowid: 

536 compiler.postfetch_lastrowid = True 

537 

538 elif implicit_return_defaults and c in implicit_return_defaults: 

539 compiler.returning.append(c) 

540 

541 else: 

542 # postfetch specifically means, "we can SELECT the row we just 

543 # inserted by primary key to get back the server generated 

544 # defaults". so by definition this can't be used to get the 

545 # primary key value back, because we need to have it ahead of 

546 # time. 

547 

548 compiler.postfetch.append(c) 

549 

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

551 

552 

553def _append_param_insert_pk_returning(compiler, stmt, c, values, kw): 

554 """Create a primary key expression in the INSERT statement where 

555 we want to populate result.inserted_primary_key and RETURNING 

556 is available. 

557 

558 """ 

559 if c.default is not None: 

560 if c.default.is_sequence: 

561 if compiler.dialect.supports_sequences and ( 

562 not c.default.optional 

563 or not compiler.dialect.sequences_optional 

564 ): 

565 values.append( 

566 ( 

567 c, 

568 compiler.preparer.format_column(c), 

569 compiler.process(c.default, **kw), 

570 ) 

571 ) 

572 compiler.returning.append(c) 

573 elif c.default.is_clause_element: 

574 values.append( 

575 ( 

576 c, 

577 compiler.preparer.format_column(c), 

578 compiler.process(c.default.arg.self_group(), **kw), 

579 ) 

580 ) 

581 compiler.returning.append(c) 

582 else: 

583 # client side default. OK we can't use RETURNING, need to 

584 # do a "prefetch", which in fact fetches the default value 

585 # on the Python side 

586 values.append( 

587 ( 

588 c, 

589 compiler.preparer.format_column(c), 

590 _create_insert_prefetch_bind_param(compiler, c, **kw), 

591 ) 

592 ) 

593 elif c is stmt.table._autoincrement_column or c.server_default is not None: 

594 compiler.returning.append(c) 

595 elif not c.nullable: 

596 # no .default, no .server_default, not autoincrement, we have 

597 # no indication this primary key column will have any value 

598 _warn_pk_with_no_anticipated_value(c) 

599 

600 

601def _append_param_insert_pk_no_returning(compiler, stmt, c, values, kw): 

602 """Create a primary key expression in the INSERT statement where 

603 we want to populate result.inserted_primary_key and we cannot use 

604 RETURNING. 

605 

606 Depending on the kind of default here we may create a bound parameter 

607 in the INSERT statement and pre-execute a default generation function, 

608 or we may use cursor.lastrowid if supported by the dialect. 

609 

610 

611 """ 

612 

613 if ( 

614 # column has a Python-side default 

615 c.default is not None 

616 and ( 

617 # and it either is not a sequence, or it is and we support 

618 # sequences and want to invoke it 

619 not c.default.is_sequence 

620 or ( 

621 compiler.dialect.supports_sequences 

622 and ( 

623 not c.default.optional 

624 or not compiler.dialect.sequences_optional 

625 ) 

626 ) 

627 ) 

628 ) or ( 

629 # column is the "autoincrement column" 

630 c is stmt.table._autoincrement_column 

631 and ( 

632 # dialect can't use cursor.lastrowid 

633 not compiler.dialect.postfetch_lastrowid 

634 and ( 

635 # column has a Sequence and we support those 

636 ( 

637 c.default is not None 

638 and c.default.is_sequence 

639 and compiler.dialect.supports_sequences 

640 ) 

641 or 

642 # column has no default on it, but dialect can run the 

643 # "autoincrement" mechanism explicitly, e.g. PostgreSQL 

644 # SERIAL we know the sequence name 

645 ( 

646 c.default is None 

647 and compiler.dialect.preexecute_autoincrement_sequences 

648 ) 

649 ) 

650 ) 

651 ): 

652 # do a pre-execute of the default 

653 values.append( 

654 ( 

655 c, 

656 compiler.preparer.format_column(c), 

657 _create_insert_prefetch_bind_param(compiler, c, **kw), 

658 ) 

659 ) 

660 elif ( 

661 c.default is None 

662 and c.server_default is None 

663 and not c.nullable 

664 and c is not stmt.table._autoincrement_column 

665 ): 

666 # no .default, no .server_default, not autoincrement, we have 

667 # no indication this primary key column will have any value 

668 _warn_pk_with_no_anticipated_value(c) 

669 elif compiler.dialect.postfetch_lastrowid: 

670 # finally, where it seems like there will be a generated primary key 

671 # value and we haven't set up any other way to fetch it, and the 

672 # dialect supports cursor.lastrowid, switch on the lastrowid flag so 

673 # that the DefaultExecutionContext calls upon cursor.lastrowid 

674 compiler.postfetch_lastrowid = True 

675 

676 

677def _append_param_insert_hasdefault( 

678 compiler, stmt, c, implicit_return_defaults, values, kw 

679): 

680 if c.default.is_sequence: 

681 if compiler.dialect.supports_sequences and ( 

682 not c.default.optional or not compiler.dialect.sequences_optional 

683 ): 

684 values.append( 

685 ( 

686 c, 

687 compiler.preparer.format_column(c), 

688 compiler.process(c.default, **kw), 

689 ) 

690 ) 

691 if implicit_return_defaults and c in implicit_return_defaults: 

692 compiler.returning.append(c) 

693 elif not c.primary_key: 

694 compiler.postfetch.append(c) 

695 elif c.default.is_clause_element: 

696 values.append( 

697 ( 

698 c, 

699 compiler.preparer.format_column(c), 

700 compiler.process(c.default.arg.self_group(), **kw), 

701 ) 

702 ) 

703 

704 if implicit_return_defaults and c in implicit_return_defaults: 

705 compiler.returning.append(c) 

706 elif not c.primary_key: 

707 # don't add primary key column to postfetch 

708 compiler.postfetch.append(c) 

709 else: 

710 values.append( 

711 ( 

712 c, 

713 compiler.preparer.format_column(c), 

714 _create_insert_prefetch_bind_param(compiler, c, **kw), 

715 ) 

716 ) 

717 

718 

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

720 

721 if c.default.is_sequence: 

722 if compiler.dialect.supports_sequences and ( 

723 not c.default.optional or not compiler.dialect.sequences_optional 

724 ): 

725 values.append( 

726 (c, compiler.preparer.format_column(c), c.default.next_value()) 

727 ) 

728 elif c.default.is_clause_element: 

729 values.append( 

730 (c, compiler.preparer.format_column(c), c.default.arg.self_group()) 

731 ) 

732 else: 

733 values.append( 

734 ( 

735 c, 

736 compiler.preparer.format_column(c), 

737 _create_insert_prefetch_bind_param( 

738 compiler, c, process=False, **kw 

739 ), 

740 ) 

741 ) 

742 

743 

744def _append_param_update( 

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

746): 

747 

748 include_table = compile_state.include_table_with_column_exprs 

749 if c.onupdate is not None and not c.onupdate.is_sequence: 

750 if c.onupdate.is_clause_element: 

751 values.append( 

752 ( 

753 c, 

754 compiler.preparer.format_column( 

755 c, 

756 use_table=include_table, 

757 ), 

758 compiler.process(c.onupdate.arg.self_group(), **kw), 

759 ) 

760 ) 

761 if implicit_return_defaults and c in implicit_return_defaults: 

762 compiler.returning.append(c) 

763 else: 

764 compiler.postfetch.append(c) 

765 else: 

766 values.append( 

767 ( 

768 c, 

769 compiler.preparer.format_column( 

770 c, 

771 use_table=include_table, 

772 ), 

773 _create_update_prefetch_bind_param(compiler, c, **kw), 

774 ) 

775 ) 

776 elif c.server_onupdate is not None: 

777 if implicit_return_defaults and c in implicit_return_defaults: 

778 compiler.returning.append(c) 

779 else: 

780 compiler.postfetch.append(c) 

781 elif ( 

782 implicit_return_defaults 

783 and (stmt._return_defaults_columns or not stmt._return_defaults) 

784 and c in implicit_return_defaults 

785 ): 

786 compiler.returning.append(c) 

787 

788 

789def _create_insert_prefetch_bind_param( 

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

791): 

792 

793 param = _create_bind_param( 

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

795 ) 

796 compiler.insert_prefetch.append(c) 

797 return param 

798 

799 

800def _create_update_prefetch_bind_param( 

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

802): 

803 param = _create_bind_param( 

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

805 ) 

806 compiler.update_prefetch.append(c) 

807 return param 

808 

809 

810class _multiparam_column(elements.ColumnElement): 

811 _is_multiparam_column = True 

812 

813 def __init__(self, original, index): 

814 self.index = index 

815 self.key = "%s_m%d" % (original.key, index + 1) 

816 self.original = original 

817 self.default = original.default 

818 self.type = original.type 

819 

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

821 raise NotImplementedError() 

822 

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

824 raise NotImplementedError() 

825 

826 def __eq__(self, other): 

827 return ( 

828 isinstance(other, _multiparam_column) 

829 and other.key == self.key 

830 and other.original == self.original 

831 ) 

832 

833 

834def _process_multiparam_default_bind(compiler, stmt, c, index, kw): 

835 if not c.default: 

836 raise exc.CompileError( 

837 "INSERT value for column %s is explicitly rendered as a bound" 

838 "parameter in the VALUES clause; " 

839 "a Python-side value or SQL expression is required" % c 

840 ) 

841 elif c.default.is_clause_element: 

842 return compiler.process(c.default.arg.self_group(), **kw) 

843 elif c.default.is_sequence: 

844 # these conditions would have been established 

845 # by append_param_insert_(?:hasdefault|pk_returning|pk_no_returning) 

846 # in order for us to be here, so these don't need to be 

847 # checked 

848 # assert compiler.dialect.supports_sequences and ( 

849 # not c.default.optional 

850 # or not compiler.dialect.sequences_optional 

851 # ) 

852 return compiler.process(c.default, **kw) 

853 else: 

854 col = _multiparam_column(c, index) 

855 if isinstance(stmt, dml.Insert): 

856 return _create_insert_prefetch_bind_param(compiler, col, **kw) 

857 else: 

858 return _create_update_prefetch_bind_param(compiler, col, **kw) 

859 

860 

861def _get_update_multitable_params( 

862 compiler, 

863 stmt, 

864 compile_state, 

865 stmt_parameter_tuples, 

866 check_columns, 

867 _col_bind_name, 

868 _getattr_col_key, 

869 values, 

870 kw, 

871): 

872 normalized_params = dict( 

873 (coercions.expect(roles.DMLColumnRole, c), param) 

874 for c, param in stmt_parameter_tuples 

875 ) 

876 

877 include_table = compile_state.include_table_with_column_exprs 

878 

879 affected_tables = set() 

880 for t in compile_state._extra_froms: 

881 for c in t.c: 

882 if c in normalized_params: 

883 affected_tables.add(t) 

884 check_columns[_getattr_col_key(c)] = c 

885 value = normalized_params[c] 

886 

887 col_value = compiler.process(c, include_table=include_table) 

888 if coercions._is_literal(value): 

889 value = _create_bind_param( 

890 compiler, 

891 c, 

892 value, 

893 required=value is REQUIRED, 

894 name=_col_bind_name(c), 

895 **kw # TODO: no test coverage for literal binds here 

896 ) 

897 elif value._is_bind_parameter: 

898 value = _handle_values_anonymous_param( 

899 compiler, c, value, name=_col_bind_name(c), **kw 

900 ) 

901 else: 

902 compiler.postfetch.append(c) 

903 value = compiler.process(value.self_group(), **kw) 

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

905 # determine tables which are actually to be updated - process onupdate 

906 # and server_onupdate for these 

907 for t in affected_tables: 

908 for c in t.c: 

909 if c in normalized_params: 

910 continue 

911 elif c.onupdate is not None and not c.onupdate.is_sequence: 

912 if c.onupdate.is_clause_element: 

913 values.append( 

914 ( 

915 c, 

916 compiler.process(c, include_table=include_table), 

917 compiler.process( 

918 c.onupdate.arg.self_group(), **kw 

919 ), 

920 ) 

921 ) 

922 compiler.postfetch.append(c) 

923 else: 

924 values.append( 

925 ( 

926 c, 

927 compiler.process(c, include_table=include_table), 

928 _create_update_prefetch_bind_param( 

929 compiler, c, name=_col_bind_name(c), **kw 

930 ), 

931 ) 

932 ) 

933 elif c.server_onupdate is not None: 

934 compiler.postfetch.append(c) 

935 

936 

937def _extend_values_for_multiparams( 

938 compiler, 

939 stmt, 

940 compile_state, 

941 values, 

942 _column_as_key, 

943 kw, 

944): 

945 values_0 = values 

946 values = [values] 

947 

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

949 extension = [] 

950 

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

952 

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

954 if col.key in row: 

955 key = col.key 

956 

957 if coercions._is_literal(row[key]): 

958 new_param = _create_bind_param( 

959 compiler, 

960 col, 

961 row[key], 

962 name="%s_m%d" % (col.key, i + 1), 

963 **kw 

964 ) 

965 else: 

966 new_param = compiler.process(row[key].self_group(), **kw) 

967 else: 

968 new_param = _process_multiparam_default_bind( 

969 compiler, stmt, col, i, kw 

970 ) 

971 

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

973 

974 values.append(extension) 

975 

976 return values 

977 

978 

979def _get_stmt_parameter_tuples_params( 

980 compiler, 

981 compile_state, 

982 parameters, 

983 stmt_parameter_tuples, 

984 _column_as_key, 

985 values, 

986 kw, 

987): 

988 

989 for k, v in stmt_parameter_tuples: 

990 colkey = _column_as_key(k) 

991 if colkey is not None: 

992 parameters.setdefault(colkey, v) 

993 else: 

994 # a non-Column expression on the left side; 

995 # add it to values() in an "as-is" state, 

996 # coercing right side to bound param 

997 

998 # note one of the main use cases for this is array slice 

999 # updates on PostgreSQL, as the left side is also an expression. 

1000 

1001 col_expr = compiler.process( 

1002 k, include_table=compile_state.include_table_with_column_exprs 

1003 ) 

1004 

1005 if coercions._is_literal(v): 

1006 v = compiler.process( 

1007 elements.BindParameter(None, v, type_=k.type), **kw 

1008 ) 

1009 else: 

1010 if v._is_bind_parameter and v.type._isnull: 

1011 # either unique parameter, or other bound parameters that 

1012 # were passed in directly 

1013 # set type to that of the column unconditionally 

1014 v = v._with_binary_element_type(k.type) 

1015 

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

1017 

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

1019 

1020 

1021def _get_returning_modifiers(compiler, stmt, compile_state): 

1022 

1023 need_pks = ( 

1024 compile_state.isinsert 

1025 and not stmt._inline 

1026 and ( 

1027 not compiler.for_executemany 

1028 or ( 

1029 compiler.dialect.insert_executemany_returning 

1030 and stmt._return_defaults 

1031 ) 

1032 ) 

1033 and not stmt._returning 

1034 and not compile_state._has_multi_parameters 

1035 ) 

1036 

1037 implicit_returning = ( 

1038 need_pks 

1039 and compiler.dialect.implicit_returning 

1040 and stmt.table.implicit_returning 

1041 ) 

1042 

1043 if compile_state.isinsert: 

1044 implicit_return_defaults = implicit_returning and stmt._return_defaults 

1045 elif compile_state.isupdate: 

1046 implicit_return_defaults = ( 

1047 compiler.dialect.implicit_returning 

1048 and stmt.table.implicit_returning 

1049 and stmt._return_defaults 

1050 ) 

1051 else: 

1052 # this line is unused, currently we are always 

1053 # isinsert or isupdate 

1054 implicit_return_defaults = False # pragma: no cover 

1055 

1056 if implicit_return_defaults: 

1057 if not stmt._return_defaults_columns: 

1058 implicit_return_defaults = set(stmt.table.c) 

1059 else: 

1060 implicit_return_defaults = set(stmt._return_defaults_columns) 

1061 

1062 postfetch_lastrowid = need_pks and compiler.dialect.postfetch_lastrowid 

1063 

1064 return ( 

1065 need_pks, 

1066 implicit_returning, 

1067 implicit_return_defaults, 

1068 postfetch_lastrowid, 

1069 ) 

1070 

1071 

1072def _warn_pk_with_no_anticipated_value(c): 

1073 msg = ( 

1074 "Column '%s.%s' is marked as a member of the " 

1075 "primary key for table '%s', " 

1076 "but has no Python-side or server-side default generator indicated, " 

1077 "nor does it indicate 'autoincrement=True' or 'nullable=True', " 

1078 "and no explicit value is passed. " 

1079 "Primary key columns typically may not store NULL." 

1080 % (c.table.fullname, c.name, c.table.fullname) 

1081 ) 

1082 if len(c.table.primary_key) > 1: 

1083 msg += ( 

1084 " Note that as of SQLAlchemy 1.1, 'autoincrement=True' must be " 

1085 "indicated explicitly for composite (e.g. multicolumn) primary " 

1086 "keys if AUTO_INCREMENT/SERIAL/IDENTITY " 

1087 "behavior is expected for one of the columns in the primary key. " 

1088 "CREATE TABLE statements are impacted by this change as well on " 

1089 "most backends." 

1090 ) 

1091 util.warn(msg)