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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

479 statements  

1# sql/dml.py 

2# Copyright (C) 2009-2026 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""" 

8Provide :class:`_expression.Insert`, :class:`_expression.Update` and 

9:class:`_expression.Delete`. 

10 

11""" 

12 

13from __future__ import annotations 

14 

15import collections.abc as collections_abc 

16import operator 

17from typing import Any 

18from typing import cast 

19from typing import Dict 

20from typing import Iterable 

21from typing import List 

22from typing import MutableMapping 

23from typing import NoReturn 

24from typing import Optional 

25from typing import overload 

26from typing import Sequence 

27from typing import Set 

28from typing import Tuple 

29from typing import Type 

30from typing import TYPE_CHECKING 

31from typing import TypeVar 

32from typing import Union 

33 

34from . import coercions 

35from . import roles 

36from . import util as sql_util 

37from ._typing import _TP 

38from ._typing import _unexpected_kw 

39from ._typing import is_column_element 

40from ._typing import is_named_from_clause 

41from .base import _entity_namespace_key 

42from .base import _exclusive_against 

43from .base import _from_objects 

44from .base import _generative 

45from .base import _select_iterables 

46from .base import ColumnCollection 

47from .base import ColumnSet 

48from .base import CompileState 

49from .base import DialectKWArgs 

50from .base import Executable 

51from .base import Generative 

52from .base import HasCompileState 

53from .elements import BooleanClauseList 

54from .elements import ClauseElement 

55from .elements import ColumnClause 

56from .elements import ColumnElement 

57from .elements import Null 

58from .selectable import Alias 

59from .selectable import ExecutableReturnsRows 

60from .selectable import FromClause 

61from .selectable import HasCTE 

62from .selectable import HasPrefixes 

63from .selectable import Join 

64from .selectable import SelectLabelStyle 

65from .selectable import TableClause 

66from .selectable import TypedReturnsRows 

67from .sqltypes import NullType 

68from .visitors import InternalTraversal 

69from .. import exc 

70from .. import util 

71from ..util.typing import Self 

72from ..util.typing import TypeGuard 

73 

74if TYPE_CHECKING: 

75 from ._typing import _ColumnExpressionArgument 

76 from ._typing import _ColumnsClauseArgument 

77 from ._typing import _DMLColumnArgument 

78 from ._typing import _DMLColumnKeyMapping 

79 from ._typing import _DMLTableArgument 

80 from ._typing import _T0 # noqa 

81 from ._typing import _T1 # noqa 

82 from ._typing import _T2 # noqa 

83 from ._typing import _T3 # noqa 

84 from ._typing import _T4 # noqa 

85 from ._typing import _T5 # noqa 

86 from ._typing import _T6 # noqa 

87 from ._typing import _T7 # noqa 

88 from ._typing import _TypedColumnClauseArgument as _TCCA # noqa 

89 from .base import ReadOnlyColumnCollection 

90 from .compiler import SQLCompiler 

91 from .elements import KeyedColumnElement 

92 from .selectable import _ColumnsClauseElement 

93 from .selectable import _SelectIterable 

94 from .selectable import Select 

95 from .selectable import Selectable 

96 

97 def isupdate(dml: DMLState) -> TypeGuard[UpdateDMLState]: ... 

98 

99 def isdelete(dml: DMLState) -> TypeGuard[DeleteDMLState]: ... 

100 

101 def isinsert(dml: DMLState) -> TypeGuard[InsertDMLState]: ... 

102 

103else: 

104 isupdate = operator.attrgetter("isupdate") 

105 isdelete = operator.attrgetter("isdelete") 

106 isinsert = operator.attrgetter("isinsert") 

107 

108 

109_T = TypeVar("_T", bound=Any) 

110 

111_DMLColumnElement = Union[str, ColumnClause[Any]] 

112_DMLTableElement = Union[TableClause, Alias, Join] 

113 

114 

115class DMLState(CompileState): 

116 _no_parameters = True 

117 _dict_parameters: Optional[MutableMapping[_DMLColumnElement, Any]] = None 

118 _multi_parameters: Optional[ 

119 List[MutableMapping[_DMLColumnElement, Any]] 

120 ] = None 

121 _ordered_values: Optional[List[Tuple[_DMLColumnElement, Any]]] = None 

122 _parameter_ordering: Optional[List[_DMLColumnElement]] = None 

123 _primary_table: FromClause 

124 _supports_implicit_returning = True 

125 

126 isupdate = False 

127 isdelete = False 

128 isinsert = False 

129 

130 statement: UpdateBase 

131 

132 def __init__( 

133 self, statement: UpdateBase, compiler: SQLCompiler, **kw: Any 

134 ): 

135 raise NotImplementedError() 

136 

137 @classmethod 

138 def get_entity_description(cls, statement: UpdateBase) -> Dict[str, Any]: 

139 return { 

140 "name": ( 

141 statement.table.name 

142 if is_named_from_clause(statement.table) 

143 else None 

144 ), 

145 "table": statement.table, 

146 } 

147 

148 @classmethod 

149 def get_returning_column_descriptions( 

150 cls, statement: UpdateBase 

151 ) -> List[Dict[str, Any]]: 

152 return [ 

153 { 

154 "name": c.key, 

155 "type": c.type, 

156 "expr": c, 

157 } 

158 for c in statement._all_selected_columns 

159 ] 

160 

161 @property 

162 def dml_table(self) -> _DMLTableElement: 

163 return self.statement.table 

164 

165 if TYPE_CHECKING: 

166 

167 @classmethod 

168 def get_plugin_class(cls, statement: Executable) -> Type[DMLState]: ... 

169 

170 @classmethod 

171 def _get_multi_crud_kv_pairs( 

172 cls, 

173 statement: UpdateBase, 

174 multi_kv_iterator: Iterable[Dict[_DMLColumnArgument, Any]], 

175 ) -> List[Dict[_DMLColumnElement, Any]]: 

176 return [ 

177 { 

178 coercions.expect(roles.DMLColumnRole, k): v 

179 for k, v in mapping.items() 

180 } 

181 for mapping in multi_kv_iterator 

182 ] 

183 

184 @classmethod 

185 def _get_crud_kv_pairs( 

186 cls, 

187 statement: UpdateBase, 

188 kv_iterator: Iterable[Tuple[_DMLColumnArgument, Any]], 

189 needs_to_be_cacheable: bool, 

190 ) -> List[Tuple[_DMLColumnElement, Any]]: 

191 return [ 

192 ( 

193 coercions.expect(roles.DMLColumnRole, k), 

194 ( 

195 v 

196 if not needs_to_be_cacheable 

197 else coercions.expect( 

198 roles.ExpressionElementRole, 

199 v, 

200 type_=NullType(), 

201 is_crud=True, 

202 ) 

203 ), 

204 ) 

205 for k, v in kv_iterator 

206 ] 

207 

208 def _make_extra_froms( 

209 self, statement: DMLWhereBase 

210 ) -> Tuple[FromClause, List[FromClause]]: 

211 froms: List[FromClause] = [] 

212 

213 all_tables = list(sql_util.tables_from_leftmost(statement.table)) 

214 primary_table = all_tables[0] 

215 seen = {primary_table} 

216 

217 consider = statement._where_criteria 

218 if self._dict_parameters: 

219 consider += tuple(self._dict_parameters.values()) 

220 

221 for crit in consider: 

222 for item in _from_objects(crit): 

223 if not seen.intersection(item._cloned_set): 

224 froms.append(item) 

225 seen.update(item._cloned_set) 

226 

227 froms.extend(all_tables[1:]) 

228 return primary_table, froms 

229 

230 def _process_values(self, statement: ValuesBase) -> None: 

231 if self._no_parameters: 

232 self._dict_parameters = statement._values 

233 self._no_parameters = False 

234 

235 def _process_select_values(self, statement: ValuesBase) -> None: 

236 assert statement._select_names is not None 

237 parameters: MutableMapping[_DMLColumnElement, Any] = { 

238 name: Null() for name in statement._select_names 

239 } 

240 

241 if self._no_parameters: 

242 self._no_parameters = False 

243 self._dict_parameters = parameters 

244 else: 

245 # this condition normally not reachable as the Insert 

246 # does not allow this construction to occur 

247 assert False, "This statement already has parameters" 

248 

249 def _no_multi_values_supported(self, statement: ValuesBase) -> NoReturn: 

250 raise exc.InvalidRequestError( 

251 "%s construct does not support " 

252 "multiple parameter sets." % statement.__visit_name__.upper() 

253 ) 

254 

255 def _cant_mix_formats_error(self) -> NoReturn: 

256 raise exc.InvalidRequestError( 

257 "Can't mix single and multiple VALUES " 

258 "formats in one INSERT statement; one style appends to a " 

259 "list while the other replaces values, so the intent is " 

260 "ambiguous." 

261 ) 

262 

263 

264@CompileState.plugin_for("default", "insert") 

265class InsertDMLState(DMLState): 

266 isinsert = True 

267 

268 include_table_with_column_exprs = False 

269 

270 _has_multi_parameters = False 

271 

272 def __init__( 

273 self, 

274 statement: Insert, 

275 compiler: SQLCompiler, 

276 disable_implicit_returning: bool = False, 

277 **kw: Any, 

278 ): 

279 self.statement = statement 

280 self._primary_table = statement.table 

281 

282 if disable_implicit_returning: 

283 self._supports_implicit_returning = False 

284 

285 self.isinsert = True 

286 if statement._select_names: 

287 self._process_select_values(statement) 

288 if statement._values is not None: 

289 self._process_values(statement) 

290 if statement._multi_values: 

291 self._process_multi_values(statement) 

292 

293 @util.memoized_property 

294 def _insert_col_keys(self) -> List[str]: 

295 # this is also done in crud.py -> _key_getters_for_crud_column 

296 return [ 

297 coercions.expect(roles.DMLColumnRole, col, as_key=True) 

298 for col in self._dict_parameters or () 

299 ] 

300 

301 def _process_values(self, statement: ValuesBase) -> None: 

302 if self._no_parameters: 

303 self._has_multi_parameters = False 

304 self._dict_parameters = statement._values 

305 self._no_parameters = False 

306 elif self._has_multi_parameters: 

307 self._cant_mix_formats_error() 

308 

309 def _process_multi_values(self, statement: ValuesBase) -> None: 

310 for parameters in statement._multi_values: 

311 multi_parameters: List[MutableMapping[_DMLColumnElement, Any]] = [ 

312 ( 

313 { 

314 c.key: value 

315 for c, value in zip(statement.table.c, parameter_set) 

316 } 

317 if isinstance(parameter_set, collections_abc.Sequence) 

318 else parameter_set 

319 ) 

320 for parameter_set in parameters 

321 ] 

322 

323 if self._no_parameters: 

324 self._no_parameters = False 

325 self._has_multi_parameters = True 

326 self._multi_parameters = multi_parameters 

327 self._dict_parameters = self._multi_parameters[0] 

328 elif not self._has_multi_parameters: 

329 self._cant_mix_formats_error() 

330 else: 

331 assert self._multi_parameters 

332 self._multi_parameters.extend(multi_parameters) 

333 

334 

335@CompileState.plugin_for("default", "update") 

336class UpdateDMLState(DMLState): 

337 isupdate = True 

338 

339 include_table_with_column_exprs = False 

340 

341 def __init__(self, statement: Update, compiler: SQLCompiler, **kw: Any): 

342 self.statement = statement 

343 

344 self.isupdate = True 

345 if statement._ordered_values is not None: 

346 self._process_ordered_values(statement) 

347 elif statement._values is not None: 

348 self._process_values(statement) 

349 elif statement._multi_values: 

350 self._no_multi_values_supported(statement) 

351 t, ef = self._make_extra_froms(statement) 

352 self._primary_table = t 

353 self._extra_froms = ef 

354 

355 self.is_multitable = mt = ef 

356 self.include_table_with_column_exprs = bool( 

357 mt and compiler.render_table_with_column_in_update_from 

358 ) 

359 

360 def _process_ordered_values(self, statement: ValuesBase) -> None: 

361 parameters = statement._ordered_values 

362 

363 if self._no_parameters: 

364 self._no_parameters = False 

365 assert parameters is not None 

366 self._dict_parameters = dict(parameters) 

367 self._ordered_values = parameters 

368 self._parameter_ordering = [key for key, value in parameters] 

369 else: 

370 raise exc.InvalidRequestError( 

371 "Can only invoke ordered_values() once, and not mixed " 

372 "with any other values() call" 

373 ) 

374 

375 

376@CompileState.plugin_for("default", "delete") 

377class DeleteDMLState(DMLState): 

378 isdelete = True 

379 

380 def __init__(self, statement: Delete, compiler: SQLCompiler, **kw: Any): 

381 self.statement = statement 

382 

383 self.isdelete = True 

384 t, ef = self._make_extra_froms(statement) 

385 self._primary_table = t 

386 self._extra_froms = ef 

387 self.is_multitable = ef 

388 

389 

390class UpdateBase( 

391 roles.DMLRole, 

392 HasCTE, 

393 HasCompileState, 

394 DialectKWArgs, 

395 HasPrefixes, 

396 Generative, 

397 ExecutableReturnsRows, 

398 ClauseElement, 

399): 

400 """Form the base for ``INSERT``, ``UPDATE``, and ``DELETE`` statements.""" 

401 

402 __visit_name__ = "update_base" 

403 

404 _hints: util.immutabledict[Tuple[_DMLTableElement, str], str] = ( 

405 util.EMPTY_DICT 

406 ) 

407 named_with_column = False 

408 

409 _label_style: SelectLabelStyle = ( 

410 SelectLabelStyle.LABEL_STYLE_DISAMBIGUATE_ONLY 

411 ) 

412 table: _DMLTableElement 

413 

414 _return_defaults = False 

415 _return_defaults_columns: Optional[Tuple[_ColumnsClauseElement, ...]] = ( 

416 None 

417 ) 

418 _supplemental_returning: Optional[Tuple[_ColumnsClauseElement, ...]] = None 

419 _returning: Tuple[_ColumnsClauseElement, ...] = () 

420 

421 is_dml = True 

422 

423 def _generate_fromclause_column_proxies( 

424 self, 

425 fromclause: FromClause, 

426 columns: ColumnCollection[str, KeyedColumnElement[Any]], 

427 primary_key: ColumnSet, 

428 foreign_keys: Set[KeyedColumnElement[Any]], 

429 ) -> None: 

430 prox = [ 

431 c._make_proxy( 

432 fromclause, 

433 key=proxy_key, 

434 name=required_label_name, 

435 name_is_truncatable=True, 

436 primary_key=primary_key, 

437 foreign_keys=foreign_keys, 

438 ) 

439 for ( 

440 required_label_name, 

441 proxy_key, 

442 fallback_label_name, 

443 c, 

444 repeated, 

445 ) in (self._generate_columns_plus_names(False)) 

446 if is_column_element(c) 

447 ] 

448 

449 columns._populate_separate_keys(prox) 

450 

451 def params(self, *arg: Any, **kw: Any) -> NoReturn: 

452 """Set the parameters for the statement. 

453 

454 This method raises ``NotImplementedError`` on the base class, 

455 and is overridden by :class:`.ValuesBase` to provide the 

456 SET/VALUES clause of UPDATE and INSERT. 

457 

458 """ 

459 raise NotImplementedError( 

460 "params() is not supported for INSERT/UPDATE/DELETE statements." 

461 " To set the values for an INSERT or UPDATE statement, use" 

462 " stmt.values(**parameters)." 

463 ) 

464 

465 @_generative 

466 def with_dialect_options(self, **opt: Any) -> Self: 

467 """Add dialect options to this INSERT/UPDATE/DELETE object. 

468 

469 e.g.:: 

470 

471 upd = table.update().dialect_options(mysql_limit=10) 

472 

473 .. versionadded: 1.4 - this method supersedes the dialect options 

474 associated with the constructor. 

475 

476 

477 """ 

478 self._validate_dialect_kwargs(opt) 

479 return self 

480 

481 @_generative 

482 def return_defaults( 

483 self, 

484 *cols: _DMLColumnArgument, 

485 supplemental_cols: Optional[Iterable[_DMLColumnArgument]] = None, 

486 sort_by_parameter_order: bool = False, 

487 ) -> Self: 

488 """Make use of a :term:`RETURNING` clause for the purpose 

489 of fetching server-side expressions and defaults, for supporting 

490 backends only. 

491 

492 .. deepalchemy:: 

493 

494 The :meth:`.UpdateBase.return_defaults` method is used by the ORM 

495 for its internal work in fetching newly generated primary key 

496 and server default values, in particular to provide the underlying 

497 implementation of the :paramref:`_orm.Mapper.eager_defaults` 

498 ORM feature as well as to allow RETURNING support with bulk 

499 ORM inserts. Its behavior is fairly idiosyncratic 

500 and is not really intended for general use. End users should 

501 stick with using :meth:`.UpdateBase.returning` in order to 

502 add RETURNING clauses to their INSERT, UPDATE and DELETE 

503 statements. 

504 

505 Normally, a single row INSERT statement will automatically populate the 

506 :attr:`.CursorResult.inserted_primary_key` attribute when executed, 

507 which stores the primary key of the row that was just inserted in the 

508 form of a :class:`.Row` object with column names as named tuple keys 

509 (and the :attr:`.Row._mapping` view fully populated as well). The 

510 dialect in use chooses the strategy to use in order to populate this 

511 data; if it was generated using server-side defaults and / or SQL 

512 expressions, dialect-specific approaches such as ``cursor.lastrowid`` 

513 or ``RETURNING`` are typically used to acquire the new primary key 

514 value. 

515 

516 However, when the statement is modified by calling 

517 :meth:`.UpdateBase.return_defaults` before executing the statement, 

518 additional behaviors take place **only** for backends that support 

519 RETURNING and for :class:`.Table` objects that maintain the 

520 :paramref:`.Table.implicit_returning` parameter at its default value of 

521 ``True``. In these cases, when the :class:`.CursorResult` is returned 

522 from the statement's execution, not only will 

523 :attr:`.CursorResult.inserted_primary_key` be populated as always, the 

524 :attr:`.CursorResult.returned_defaults` attribute will also be 

525 populated with a :class:`.Row` named-tuple representing the full range 

526 of server generated 

527 values from that single row, including values for any columns that 

528 specify :paramref:`_schema.Column.server_default` or which make use of 

529 :paramref:`_schema.Column.default` using a SQL expression. 

530 

531 When invoking INSERT statements with multiple rows using 

532 :ref:`insertmanyvalues <engine_insertmanyvalues>`, the 

533 :meth:`.UpdateBase.return_defaults` modifier will have the effect of 

534 the :attr:`_engine.CursorResult.inserted_primary_key_rows` and 

535 :attr:`_engine.CursorResult.returned_defaults_rows` attributes being 

536 fully populated with lists of :class:`.Row` objects representing newly 

537 inserted primary key values as well as newly inserted server generated 

538 values for each row inserted. The 

539 :attr:`.CursorResult.inserted_primary_key` and 

540 :attr:`.CursorResult.returned_defaults` attributes will also continue 

541 to be populated with the first row of these two collections. 

542 

543 If the backend does not support RETURNING or the :class:`.Table` in use 

544 has disabled :paramref:`.Table.implicit_returning`, then no RETURNING 

545 clause is added and no additional data is fetched, however the 

546 INSERT, UPDATE or DELETE statement proceeds normally. 

547 

548 E.g.:: 

549 

550 stmt = table.insert().values(data="newdata").return_defaults() 

551 

552 result = connection.execute(stmt) 

553 

554 server_created_at = result.returned_defaults["created_at"] 

555 

556 When used against an UPDATE statement 

557 :meth:`.UpdateBase.return_defaults` instead looks for columns that 

558 include :paramref:`_schema.Column.onupdate` or 

559 :paramref:`_schema.Column.server_onupdate` parameters assigned, when 

560 constructing the columns that will be included in the RETURNING clause 

561 by default if explicit columns were not specified. When used against a 

562 DELETE statement, no columns are included in RETURNING by default, they 

563 instead must be specified explicitly as there are no columns that 

564 normally change values when a DELETE statement proceeds. 

565 

566 .. versionadded:: 2.0 :meth:`.UpdateBase.return_defaults` is supported 

567 for DELETE statements also and has been moved from 

568 :class:`.ValuesBase` to :class:`.UpdateBase`. 

569 

570 The :meth:`.UpdateBase.return_defaults` method is mutually exclusive 

571 against the :meth:`.UpdateBase.returning` method and errors will be 

572 raised during the SQL compilation process if both are used at the same 

573 time on one statement. The RETURNING clause of the INSERT, UPDATE or 

574 DELETE statement is therefore controlled by only one of these methods 

575 at a time. 

576 

577 The :meth:`.UpdateBase.return_defaults` method differs from 

578 :meth:`.UpdateBase.returning` in these ways: 

579 

580 1. :meth:`.UpdateBase.return_defaults` method causes the 

581 :attr:`.CursorResult.returned_defaults` collection to be populated 

582 with the first row from the RETURNING result. This attribute is not 

583 populated when using :meth:`.UpdateBase.returning`. 

584 

585 2. :meth:`.UpdateBase.return_defaults` is compatible with existing 

586 logic used to fetch auto-generated primary key values that are then 

587 populated into the :attr:`.CursorResult.inserted_primary_key` 

588 attribute. By contrast, using :meth:`.UpdateBase.returning` will 

589 have the effect of the :attr:`.CursorResult.inserted_primary_key` 

590 attribute being left unpopulated. 

591 

592 3. :meth:`.UpdateBase.return_defaults` can be called against any 

593 backend. Backends that don't support RETURNING will skip the usage 

594 of the feature, rather than raising an exception, *unless* 

595 ``supplemental_cols`` is passed. The return value 

596 of :attr:`_engine.CursorResult.returned_defaults` will be ``None`` 

597 for backends that don't support RETURNING or for which the target 

598 :class:`.Table` sets :paramref:`.Table.implicit_returning` to 

599 ``False``. 

600 

601 4. An INSERT statement invoked with executemany() is supported if the 

602 backend database driver supports the 

603 :ref:`insertmanyvalues <engine_insertmanyvalues>` 

604 feature which is now supported by most SQLAlchemy-included backends. 

605 When executemany is used, the 

606 :attr:`_engine.CursorResult.returned_defaults_rows` and 

607 :attr:`_engine.CursorResult.inserted_primary_key_rows` accessors 

608 will return the inserted defaults and primary keys. 

609 

610 .. versionadded:: 1.4 Added 

611 :attr:`_engine.CursorResult.returned_defaults_rows` and 

612 :attr:`_engine.CursorResult.inserted_primary_key_rows` accessors. 

613 In version 2.0, the underlying implementation which fetches and 

614 populates the data for these attributes was generalized to be 

615 supported by most backends, whereas in 1.4 they were only 

616 supported by the ``psycopg2`` driver. 

617 

618 

619 :param cols: optional list of column key names or 

620 :class:`_schema.Column` that acts as a filter for those columns that 

621 will be fetched. 

622 :param supplemental_cols: optional list of RETURNING expressions, 

623 in the same form as one would pass to the 

624 :meth:`.UpdateBase.returning` method. When present, the additional 

625 columns will be included in the RETURNING clause, and the 

626 :class:`.CursorResult` object will be "rewound" when returned, so 

627 that methods like :meth:`.CursorResult.all` will return new rows 

628 mostly as though the statement used :meth:`.UpdateBase.returning` 

629 directly. However, unlike when using :meth:`.UpdateBase.returning` 

630 directly, the **order of the columns is undefined**, so can only be 

631 targeted using names or :attr:`.Row._mapping` keys; they cannot 

632 reliably be targeted positionally. 

633 

634 .. versionadded:: 2.0 

635 

636 :param sort_by_parameter_order: for a batch INSERT that is being 

637 executed against multiple parameter sets, organize the results of 

638 RETURNING so that the returned rows correspond to the order of 

639 parameter sets passed in. This applies only to an :term:`executemany` 

640 execution for supporting dialects and typically makes use of the 

641 :term:`insertmanyvalues` feature. 

642 

643 .. versionadded:: 2.0.10 

644 

645 .. seealso:: 

646 

647 :ref:`engine_insertmanyvalues_returning_order` - background on 

648 sorting of RETURNING rows for bulk INSERT 

649 

650 .. seealso:: 

651 

652 :meth:`.UpdateBase.returning` 

653 

654 :attr:`_engine.CursorResult.returned_defaults` 

655 

656 :attr:`_engine.CursorResult.returned_defaults_rows` 

657 

658 :attr:`_engine.CursorResult.inserted_primary_key` 

659 

660 :attr:`_engine.CursorResult.inserted_primary_key_rows` 

661 

662 """ 

663 

664 if self._return_defaults: 

665 # note _return_defaults_columns = () means return all columns, 

666 # so if we have been here before, only update collection if there 

667 # are columns in the collection 

668 if self._return_defaults_columns and cols: 

669 self._return_defaults_columns = tuple( 

670 util.OrderedSet(self._return_defaults_columns).union( 

671 coercions.expect(roles.ColumnsClauseRole, c) 

672 for c in cols 

673 ) 

674 ) 

675 else: 

676 # set for all columns 

677 self._return_defaults_columns = () 

678 else: 

679 self._return_defaults_columns = tuple( 

680 coercions.expect(roles.ColumnsClauseRole, c) for c in cols 

681 ) 

682 self._return_defaults = True 

683 if sort_by_parameter_order: 

684 if not self.is_insert: 

685 raise exc.ArgumentError( 

686 "The 'sort_by_parameter_order' argument to " 

687 "return_defaults() only applies to INSERT statements" 

688 ) 

689 self._sort_by_parameter_order = True 

690 if supplemental_cols: 

691 # uniquifying while also maintaining order (the maintain of order 

692 # is for test suites but also for vertical splicing 

693 supplemental_col_tup = ( 

694 coercions.expect(roles.ColumnsClauseRole, c) 

695 for c in supplemental_cols 

696 ) 

697 

698 if self._supplemental_returning is None: 

699 self._supplemental_returning = tuple( 

700 util.unique_list(supplemental_col_tup) 

701 ) 

702 else: 

703 self._supplemental_returning = tuple( 

704 util.unique_list( 

705 self._supplemental_returning 

706 + tuple(supplemental_col_tup) 

707 ) 

708 ) 

709 

710 return self 

711 

712 def is_derived_from(self, fromclause: Optional[FromClause]) -> bool: 

713 """Return ``True`` if this :class:`.ReturnsRows` is 

714 'derived' from the given :class:`.FromClause`. 

715 

716 Since these are DMLs, we dont want such statements ever being adapted 

717 so we return False for derives. 

718 

719 """ 

720 return False 

721 

722 @_generative 

723 def returning( 

724 self, 

725 *cols: _ColumnsClauseArgument[Any], 

726 sort_by_parameter_order: bool = False, 

727 **__kw: Any, 

728 ) -> UpdateBase: 

729 r"""Add a :term:`RETURNING` or equivalent clause to this statement. 

730 

731 e.g.: 

732 

733 .. sourcecode:: pycon+sql 

734 

735 >>> stmt = ( 

736 ... table.update() 

737 ... .where(table.c.data == "value") 

738 ... .values(status="X") 

739 ... .returning(table.c.server_flag, table.c.updated_timestamp) 

740 ... ) 

741 >>> print(stmt) 

742 {printsql}UPDATE some_table SET status=:status 

743 WHERE some_table.data = :data_1 

744 RETURNING some_table.server_flag, some_table.updated_timestamp 

745 

746 The method may be invoked multiple times to add new entries to the 

747 list of expressions to be returned. 

748 

749 .. versionadded:: 1.4.0b2 The method may be invoked multiple times to 

750 add new entries to the list of expressions to be returned. 

751 

752 The given collection of column expressions should be derived from the 

753 table that is the target of the INSERT, UPDATE, or DELETE. While 

754 :class:`_schema.Column` objects are typical, the elements can also be 

755 expressions: 

756 

757 .. sourcecode:: pycon+sql 

758 

759 >>> stmt = table.insert().returning( 

760 ... (table.c.first_name + " " + table.c.last_name).label("fullname") 

761 ... ) 

762 >>> print(stmt) 

763 {printsql}INSERT INTO some_table (first_name, last_name) 

764 VALUES (:first_name, :last_name) 

765 RETURNING some_table.first_name || :first_name_1 || some_table.last_name AS fullname 

766 

767 Upon compilation, a RETURNING clause, or database equivalent, 

768 will be rendered within the statement. For INSERT and UPDATE, 

769 the values are the newly inserted/updated values. For DELETE, 

770 the values are those of the rows which were deleted. 

771 

772 Upon execution, the values of the columns to be returned are made 

773 available via the result set and can be iterated using 

774 :meth:`_engine.CursorResult.fetchone` and similar. 

775 For DBAPIs which do not 

776 natively support returning values (i.e. cx_oracle), SQLAlchemy will 

777 approximate this behavior at the result level so that a reasonable 

778 amount of behavioral neutrality is provided. 

779 

780 Note that not all databases/DBAPIs 

781 support RETURNING. For those backends with no support, 

782 an exception is raised upon compilation and/or execution. 

783 For those who do support it, the functionality across backends 

784 varies greatly, including restrictions on executemany() 

785 and other statements which return multiple rows. Please 

786 read the documentation notes for the database in use in 

787 order to determine the availability of RETURNING. 

788 

789 :param \*cols: series of columns, SQL expressions, or whole tables 

790 entities to be returned. 

791 :param sort_by_parameter_order: for a batch INSERT that is being 

792 executed against multiple parameter sets, organize the results of 

793 RETURNING so that the returned rows correspond to the order of 

794 parameter sets passed in. This applies only to an :term:`executemany` 

795 execution for supporting dialects and typically makes use of the 

796 :term:`insertmanyvalues` feature. 

797 

798 .. versionadded:: 2.0.10 

799 

800 .. seealso:: 

801 

802 :ref:`engine_insertmanyvalues_returning_order` - background on 

803 sorting of RETURNING rows for bulk INSERT (Core level discussion) 

804 

805 :ref:`orm_queryguide_bulk_insert_returning_ordered` - example of 

806 use with :ref:`orm_queryguide_bulk_insert` (ORM level discussion) 

807 

808 .. seealso:: 

809 

810 :meth:`.UpdateBase.return_defaults` - an alternative method tailored 

811 towards efficient fetching of server-side defaults and triggers 

812 for single-row INSERTs or UPDATEs. 

813 

814 :ref:`tutorial_insert_returning` - in the :ref:`unified_tutorial` 

815 

816 """ # noqa: E501 

817 if __kw: 

818 raise _unexpected_kw("UpdateBase.returning()", __kw) 

819 if self._return_defaults: 

820 raise exc.InvalidRequestError( 

821 "return_defaults() is already configured on this statement" 

822 ) 

823 self._returning += tuple( 

824 coercions.expect(roles.ColumnsClauseRole, c) for c in cols 

825 ) 

826 if sort_by_parameter_order: 

827 if not self.is_insert: 

828 raise exc.ArgumentError( 

829 "The 'sort_by_parameter_order' argument to returning() " 

830 "only applies to INSERT statements" 

831 ) 

832 self._sort_by_parameter_order = True 

833 return self 

834 

835 def corresponding_column( 

836 self, column: KeyedColumnElement[Any], require_embedded: bool = False 

837 ) -> Optional[ColumnElement[Any]]: 

838 return self.exported_columns.corresponding_column( 

839 column, require_embedded=require_embedded 

840 ) 

841 

842 @util.ro_memoized_property 

843 def _all_selected_columns(self) -> _SelectIterable: 

844 return [c for c in _select_iterables(self._returning)] 

845 

846 @util.ro_memoized_property 

847 def exported_columns( 

848 self, 

849 ) -> ReadOnlyColumnCollection[Optional[str], ColumnElement[Any]]: 

850 """Return the RETURNING columns as a column collection for this 

851 statement. 

852 

853 .. versionadded:: 1.4 

854 

855 """ 

856 return ColumnCollection( 

857 (c.key, c) 

858 for c in self._all_selected_columns 

859 if is_column_element(c) 

860 ).as_readonly() 

861 

862 @_generative 

863 def with_hint( 

864 self, 

865 text: str, 

866 selectable: Optional[_DMLTableArgument] = None, 

867 dialect_name: str = "*", 

868 ) -> Self: 

869 """Add a table hint for a single table to this 

870 INSERT/UPDATE/DELETE statement. 

871 

872 .. note:: 

873 

874 :meth:`.UpdateBase.with_hint` currently applies only to 

875 Microsoft SQL Server. For MySQL INSERT/UPDATE/DELETE hints, use 

876 :meth:`.UpdateBase.prefix_with`. 

877 

878 The text of the hint is rendered in the appropriate 

879 location for the database backend in use, relative 

880 to the :class:`_schema.Table` that is the subject of this 

881 statement, or optionally to that of the given 

882 :class:`_schema.Table` passed as the ``selectable`` argument. 

883 

884 The ``dialect_name`` option will limit the rendering of a particular 

885 hint to a particular backend. Such as, to add a hint 

886 that only takes effect for SQL Server:: 

887 

888 mytable.insert().with_hint("WITH (PAGLOCK)", dialect_name="mssql") 

889 

890 :param text: Text of the hint. 

891 :param selectable: optional :class:`_schema.Table` that specifies 

892 an element of the FROM clause within an UPDATE or DELETE 

893 to be the subject of the hint - applies only to certain backends. 

894 :param dialect_name: defaults to ``*``, if specified as the name 

895 of a particular dialect, will apply these hints only when 

896 that dialect is in use. 

897 """ 

898 if selectable is None: 

899 selectable = self.table 

900 else: 

901 selectable = coercions.expect(roles.DMLTableRole, selectable) 

902 self._hints = self._hints.union({(selectable, dialect_name): text}) 

903 return self 

904 

905 @property 

906 def entity_description(self) -> Dict[str, Any]: 

907 """Return a :term:`plugin-enabled` description of the table and/or 

908 entity which this DML construct is operating against. 

909 

910 This attribute is generally useful when using the ORM, as an 

911 extended structure which includes information about mapped 

912 entities is returned. The section :ref:`queryguide_inspection` 

913 contains more background. 

914 

915 For a Core statement, the structure returned by this accessor 

916 is derived from the :attr:`.UpdateBase.table` attribute, and 

917 refers to the :class:`.Table` being inserted, updated, or deleted:: 

918 

919 >>> stmt = insert(user_table) 

920 >>> stmt.entity_description 

921 { 

922 "name": "user_table", 

923 "table": Table("user_table", ...) 

924 } 

925 

926 .. versionadded:: 1.4.33 

927 

928 .. seealso:: 

929 

930 :attr:`.UpdateBase.returning_column_descriptions` 

931 

932 :attr:`.Select.column_descriptions` - entity information for 

933 a :func:`.select` construct 

934 

935 :ref:`queryguide_inspection` - ORM background 

936 

937 """ 

938 meth = DMLState.get_plugin_class(self).get_entity_description 

939 return meth(self) 

940 

941 @property 

942 def returning_column_descriptions(self) -> List[Dict[str, Any]]: 

943 """Return a :term:`plugin-enabled` description of the columns 

944 which this DML construct is RETURNING against, in other words 

945 the expressions established as part of :meth:`.UpdateBase.returning`. 

946 

947 This attribute is generally useful when using the ORM, as an 

948 extended structure which includes information about mapped 

949 entities is returned. The section :ref:`queryguide_inspection` 

950 contains more background. 

951 

952 For a Core statement, the structure returned by this accessor is 

953 derived from the same objects that are returned by the 

954 :attr:`.UpdateBase.exported_columns` accessor:: 

955 

956 >>> stmt = insert(user_table).returning(user_table.c.id, user_table.c.name) 

957 >>> stmt.entity_description 

958 [ 

959 { 

960 "name": "id", 

961 "type": Integer, 

962 "expr": Column("id", Integer(), table=<user>, ...) 

963 }, 

964 { 

965 "name": "name", 

966 "type": String(), 

967 "expr": Column("name", String(), table=<user>, ...) 

968 }, 

969 ] 

970 

971 .. versionadded:: 1.4.33 

972 

973 .. seealso:: 

974 

975 :attr:`.UpdateBase.entity_description` 

976 

977 :attr:`.Select.column_descriptions` - entity information for 

978 a :func:`.select` construct 

979 

980 :ref:`queryguide_inspection` - ORM background 

981 

982 """ # noqa: E501 

983 meth = DMLState.get_plugin_class( 

984 self 

985 ).get_returning_column_descriptions 

986 return meth(self) 

987 

988 

989class ValuesBase(UpdateBase): 

990 """Supplies support for :meth:`.ValuesBase.values` to 

991 INSERT and UPDATE constructs.""" 

992 

993 __visit_name__ = "values_base" 

994 

995 _supports_multi_parameters = False 

996 

997 select: Optional[Select[Any]] = None 

998 """SELECT statement for INSERT .. FROM SELECT""" 

999 

1000 _post_values_clause: Optional[ClauseElement] = None 

1001 """used by extensions to Insert etc. to add additional syntacitcal 

1002 constructs, e.g. ON CONFLICT etc.""" 

1003 

1004 _values: Optional[util.immutabledict[_DMLColumnElement, Any]] = None 

1005 _multi_values: Tuple[ 

1006 Union[ 

1007 Sequence[Dict[_DMLColumnElement, Any]], 

1008 Sequence[Sequence[Any]], 

1009 ], 

1010 ..., 

1011 ] = () 

1012 

1013 _ordered_values: Optional[List[Tuple[_DMLColumnElement, Any]]] = None 

1014 

1015 _select_names: Optional[List[str]] = None 

1016 _inline: bool = False 

1017 

1018 def __init__(self, table: _DMLTableArgument): 

1019 self.table = coercions.expect( 

1020 roles.DMLTableRole, table, apply_propagate_attrs=self 

1021 ) 

1022 

1023 @_generative 

1024 @_exclusive_against( 

1025 "_select_names", 

1026 "_ordered_values", 

1027 msgs={ 

1028 "_select_names": "This construct already inserts from a SELECT", 

1029 "_ordered_values": "This statement already has ordered " 

1030 "values present", 

1031 }, 

1032 ) 

1033 def values( 

1034 self, 

1035 *args: Union[ 

1036 _DMLColumnKeyMapping[Any], 

1037 Sequence[Any], 

1038 ], 

1039 **kwargs: Any, 

1040 ) -> Self: 

1041 r"""Specify a fixed VALUES clause for an INSERT statement, or the SET 

1042 clause for an UPDATE. 

1043 

1044 Note that the :class:`_expression.Insert` and 

1045 :class:`_expression.Update` 

1046 constructs support 

1047 per-execution time formatting of the VALUES and/or SET clauses, 

1048 based on the arguments passed to :meth:`_engine.Connection.execute`. 

1049 However, the :meth:`.ValuesBase.values` method can be used to "fix" a 

1050 particular set of parameters into the statement. 

1051 

1052 Multiple calls to :meth:`.ValuesBase.values` will produce a new 

1053 construct, each one with the parameter list modified to include 

1054 the new parameters sent. In the typical case of a single 

1055 dictionary of parameters, the newly passed keys will replace 

1056 the same keys in the previous construct. In the case of a list-based 

1057 "multiple values" construct, each new list of values is extended 

1058 onto the existing list of values. 

1059 

1060 :param \**kwargs: key value pairs representing the string key 

1061 of a :class:`_schema.Column` 

1062 mapped to the value to be rendered into the 

1063 VALUES or SET clause:: 

1064 

1065 users.insert().values(name="some name") 

1066 

1067 users.update().where(users.c.id == 5).values(name="some name") 

1068 

1069 :param \*args: As an alternative to passing key/value parameters, 

1070 a dictionary, tuple, or list of dictionaries or tuples can be passed 

1071 as a single positional argument in order to form the VALUES or 

1072 SET clause of the statement. The forms that are accepted vary 

1073 based on whether this is an :class:`_expression.Insert` or an 

1074 :class:`_expression.Update` construct. 

1075 

1076 For either an :class:`_expression.Insert` or 

1077 :class:`_expression.Update` 

1078 construct, a single dictionary can be passed, which works the same as 

1079 that of the kwargs form:: 

1080 

1081 users.insert().values({"name": "some name"}) 

1082 

1083 users.update().values({"name": "some new name"}) 

1084 

1085 Also for either form but more typically for the 

1086 :class:`_expression.Insert` construct, a tuple that contains an 

1087 entry for every column in the table is also accepted:: 

1088 

1089 users.insert().values((5, "some name")) 

1090 

1091 The :class:`_expression.Insert` construct also supports being 

1092 passed a list of dictionaries or full-table-tuples, which on the 

1093 server will render the less common SQL syntax of "multiple values" - 

1094 this syntax is supported on backends such as SQLite, PostgreSQL, 

1095 MySQL, but not necessarily others:: 

1096 

1097 users.insert().values( 

1098 [ 

1099 {"name": "some name"}, 

1100 {"name": "some other name"}, 

1101 {"name": "yet another name"}, 

1102 ] 

1103 ) 

1104 

1105 The above form would render a multiple VALUES statement similar to: 

1106 

1107 .. sourcecode:: sql 

1108 

1109 INSERT INTO users (name) VALUES 

1110 (:name_1), 

1111 (:name_2), 

1112 (:name_3) 

1113 

1114 It is essential to note that **passing multiple values is 

1115 NOT the same as using traditional executemany() form**. The above 

1116 syntax is a **special** syntax not typically used. To emit an 

1117 INSERT statement against multiple rows, the normal method is 

1118 to pass a multiple values list to the 

1119 :meth:`_engine.Connection.execute` 

1120 method, which is supported by all database backends and is generally 

1121 more efficient for a very large number of parameters. 

1122 

1123 .. seealso:: 

1124 

1125 :ref:`tutorial_multiple_parameters` - an introduction to 

1126 the traditional Core method of multiple parameter set 

1127 invocation for INSERTs and other statements. 

1128 

1129 :ref:`tutorial_core_insert_values_clause` - Insert tutorial 

1130 detailing alternatives to the multiple values syntax. 

1131 

1132 The UPDATE construct also supports rendering the SET parameters 

1133 in a specific order. For this feature refer to the 

1134 :meth:`_expression.Update.ordered_values` method. 

1135 

1136 .. seealso:: 

1137 

1138 :meth:`_expression.Update.ordered_values` 

1139 

1140 

1141 """ 

1142 if args: 

1143 # positional case. this is currently expensive. we don't 

1144 # yet have positional-only args so we have to check the length. 

1145 # then we need to check multiparams vs. single dictionary. 

1146 # since the parameter format is needed in order to determine 

1147 # a cache key, we need to determine this up front. 

1148 arg = args[0] 

1149 

1150 if kwargs: 

1151 raise exc.ArgumentError( 

1152 "Can't pass positional and kwargs to values() " 

1153 "simultaneously" 

1154 ) 

1155 elif len(args) > 1: 

1156 raise exc.ArgumentError( 

1157 "Only a single dictionary/tuple or list of " 

1158 "dictionaries/tuples is accepted positionally." 

1159 ) 

1160 

1161 elif isinstance(arg, collections_abc.Sequence): 

1162 if arg and isinstance(arg[0], dict): 

1163 multi_kv_generator = DMLState.get_plugin_class( 

1164 self 

1165 )._get_multi_crud_kv_pairs 

1166 self._multi_values += (multi_kv_generator(self, arg),) 

1167 return self 

1168 

1169 if arg and isinstance(arg[0], (list, tuple)): 

1170 self._multi_values += (arg,) 

1171 return self 

1172 

1173 if TYPE_CHECKING: 

1174 # crud.py raises during compilation if this is not the 

1175 # case 

1176 assert isinstance(self, Insert) 

1177 

1178 # tuple values 

1179 arg = {c.key: value for c, value in zip(self.table.c, arg)} 

1180 

1181 else: 

1182 # kwarg path. this is the most common path for non-multi-params 

1183 # so this is fairly quick. 

1184 arg = cast("Dict[_DMLColumnArgument, Any]", kwargs) 

1185 if args: 

1186 raise exc.ArgumentError( 

1187 "Only a single dictionary/tuple or list of " 

1188 "dictionaries/tuples is accepted positionally." 

1189 ) 

1190 

1191 # for top level values(), convert literals to anonymous bound 

1192 # parameters at statement construction time, so that these values can 

1193 # participate in the cache key process like any other ClauseElement. 

1194 # crud.py now intercepts bound parameters with unique=True from here 

1195 # and ensures they get the "crud"-style name when rendered. 

1196 

1197 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs 

1198 coerced_arg = dict(kv_generator(self, arg.items(), True)) 

1199 if self._values: 

1200 self._values = self._values.union(coerced_arg) 

1201 else: 

1202 self._values = util.immutabledict(coerced_arg) 

1203 return self 

1204 

1205 

1206class Insert(ValuesBase): 

1207 """Represent an INSERT construct. 

1208 

1209 The :class:`_expression.Insert` object is created using the 

1210 :func:`_expression.insert()` function. 

1211 

1212 """ 

1213 

1214 __visit_name__ = "insert" 

1215 

1216 _supports_multi_parameters = True 

1217 

1218 select = None 

1219 include_insert_from_select_defaults = False 

1220 

1221 _sort_by_parameter_order: bool = False 

1222 

1223 is_insert = True 

1224 

1225 table: TableClause 

1226 

1227 _traverse_internals = ( 

1228 [ 

1229 ("table", InternalTraversal.dp_clauseelement), 

1230 ("_inline", InternalTraversal.dp_boolean), 

1231 ("_select_names", InternalTraversal.dp_string_list), 

1232 ("_values", InternalTraversal.dp_dml_values), 

1233 ("_multi_values", InternalTraversal.dp_dml_multi_values), 

1234 ("select", InternalTraversal.dp_clauseelement), 

1235 ("_post_values_clause", InternalTraversal.dp_clauseelement), 

1236 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1237 ("_hints", InternalTraversal.dp_table_hint_list), 

1238 ("_return_defaults", InternalTraversal.dp_boolean), 

1239 ( 

1240 "_return_defaults_columns", 

1241 InternalTraversal.dp_clauseelement_tuple, 

1242 ), 

1243 ("_sort_by_parameter_order", InternalTraversal.dp_boolean), 

1244 ] 

1245 + HasPrefixes._has_prefixes_traverse_internals 

1246 + DialectKWArgs._dialect_kwargs_traverse_internals 

1247 + Executable._executable_traverse_internals 

1248 + HasCTE._has_ctes_traverse_internals 

1249 ) 

1250 

1251 def __init__(self, table: _DMLTableArgument): 

1252 super().__init__(table) 

1253 

1254 @_generative 

1255 def inline(self) -> Self: 

1256 """Make this :class:`_expression.Insert` construct "inline" . 

1257 

1258 When set, no attempt will be made to retrieve the 

1259 SQL-generated default values to be provided within the statement; 

1260 in particular, 

1261 this allows SQL expressions to be rendered 'inline' within the 

1262 statement without the need to pre-execute them beforehand; for 

1263 backends that support "returning", this turns off the "implicit 

1264 returning" feature for the statement. 

1265 

1266 

1267 .. versionchanged:: 1.4 the :paramref:`_expression.Insert.inline` 

1268 parameter 

1269 is now superseded by the :meth:`_expression.Insert.inline` method. 

1270 

1271 """ 

1272 self._inline = True 

1273 return self 

1274 

1275 @_generative 

1276 def from_select( 

1277 self, 

1278 names: Sequence[_DMLColumnArgument], 

1279 select: Selectable, 

1280 include_defaults: bool = True, 

1281 ) -> Self: 

1282 """Return a new :class:`_expression.Insert` construct which represents 

1283 an ``INSERT...FROM SELECT`` statement. 

1284 

1285 e.g.:: 

1286 

1287 sel = select(table1.c.a, table1.c.b).where(table1.c.c > 5) 

1288 ins = table2.insert().from_select(["a", "b"], sel) 

1289 

1290 :param names: a sequence of string column names or 

1291 :class:`_schema.Column` 

1292 objects representing the target columns. 

1293 :param select: a :func:`_expression.select` construct, 

1294 :class:`_expression.FromClause` 

1295 or other construct which resolves into a 

1296 :class:`_expression.FromClause`, 

1297 such as an ORM :class:`_query.Query` object, etc. The order of 

1298 columns returned from this FROM clause should correspond to the 

1299 order of columns sent as the ``names`` parameter; while this 

1300 is not checked before passing along to the database, the database 

1301 would normally raise an exception if these column lists don't 

1302 correspond. 

1303 :param include_defaults: if True, non-server default values and 

1304 SQL expressions as specified on :class:`_schema.Column` objects 

1305 (as documented in :ref:`metadata_defaults_toplevel`) not 

1306 otherwise specified in the list of names will be rendered 

1307 into the INSERT and SELECT statements, so that these values are also 

1308 included in the data to be inserted. 

1309 

1310 .. note:: A Python-side default that uses a Python callable function 

1311 will only be invoked **once** for the whole statement, and **not 

1312 per row**. 

1313 

1314 """ 

1315 

1316 if self._values: 

1317 raise exc.InvalidRequestError( 

1318 "This construct already inserts value expressions" 

1319 ) 

1320 

1321 self._select_names = [ 

1322 coercions.expect(roles.DMLColumnRole, name, as_key=True) 

1323 for name in names 

1324 ] 

1325 self._inline = True 

1326 self.include_insert_from_select_defaults = include_defaults 

1327 self.select = coercions.expect(roles.DMLSelectRole, select) 

1328 return self 

1329 

1330 if TYPE_CHECKING: 

1331 # START OVERLOADED FUNCTIONS self.returning ReturningInsert 1-8 ", *, sort_by_parameter_order: bool = False" # noqa: E501 

1332 

1333 # code within this block is **programmatically, 

1334 # statically generated** by tools/generate_tuple_map_overloads.py 

1335 

1336 @overload 

1337 def returning( 

1338 self, __ent0: _TCCA[_T0], *, sort_by_parameter_order: bool = False 

1339 ) -> ReturningInsert[Tuple[_T0]]: ... 

1340 

1341 @overload 

1342 def returning( 

1343 self, 

1344 __ent0: _TCCA[_T0], 

1345 __ent1: _TCCA[_T1], 

1346 *, 

1347 sort_by_parameter_order: bool = False, 

1348 ) -> ReturningInsert[Tuple[_T0, _T1]]: ... 

1349 

1350 @overload 

1351 def returning( 

1352 self, 

1353 __ent0: _TCCA[_T0], 

1354 __ent1: _TCCA[_T1], 

1355 __ent2: _TCCA[_T2], 

1356 *, 

1357 sort_by_parameter_order: bool = False, 

1358 ) -> ReturningInsert[Tuple[_T0, _T1, _T2]]: ... 

1359 

1360 @overload 

1361 def returning( 

1362 self, 

1363 __ent0: _TCCA[_T0], 

1364 __ent1: _TCCA[_T1], 

1365 __ent2: _TCCA[_T2], 

1366 __ent3: _TCCA[_T3], 

1367 *, 

1368 sort_by_parameter_order: bool = False, 

1369 ) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3]]: ... 

1370 

1371 @overload 

1372 def returning( 

1373 self, 

1374 __ent0: _TCCA[_T0], 

1375 __ent1: _TCCA[_T1], 

1376 __ent2: _TCCA[_T2], 

1377 __ent3: _TCCA[_T3], 

1378 __ent4: _TCCA[_T4], 

1379 *, 

1380 sort_by_parameter_order: bool = False, 

1381 ) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4]]: ... 

1382 

1383 @overload 

1384 def returning( 

1385 self, 

1386 __ent0: _TCCA[_T0], 

1387 __ent1: _TCCA[_T1], 

1388 __ent2: _TCCA[_T2], 

1389 __ent3: _TCCA[_T3], 

1390 __ent4: _TCCA[_T4], 

1391 __ent5: _TCCA[_T5], 

1392 *, 

1393 sort_by_parameter_order: bool = False, 

1394 ) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ... 

1395 

1396 @overload 

1397 def returning( 

1398 self, 

1399 __ent0: _TCCA[_T0], 

1400 __ent1: _TCCA[_T1], 

1401 __ent2: _TCCA[_T2], 

1402 __ent3: _TCCA[_T3], 

1403 __ent4: _TCCA[_T4], 

1404 __ent5: _TCCA[_T5], 

1405 __ent6: _TCCA[_T6], 

1406 *, 

1407 sort_by_parameter_order: bool = False, 

1408 ) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ... 

1409 

1410 @overload 

1411 def returning( 

1412 self, 

1413 __ent0: _TCCA[_T0], 

1414 __ent1: _TCCA[_T1], 

1415 __ent2: _TCCA[_T2], 

1416 __ent3: _TCCA[_T3], 

1417 __ent4: _TCCA[_T4], 

1418 __ent5: _TCCA[_T5], 

1419 __ent6: _TCCA[_T6], 

1420 __ent7: _TCCA[_T7], 

1421 *, 

1422 sort_by_parameter_order: bool = False, 

1423 ) -> ReturningInsert[ 

1424 Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7] 

1425 ]: ... 

1426 

1427 # END OVERLOADED FUNCTIONS self.returning 

1428 

1429 @overload 

1430 def returning( 

1431 self, 

1432 *cols: _ColumnsClauseArgument[Any], 

1433 sort_by_parameter_order: bool = False, 

1434 **__kw: Any, 

1435 ) -> ReturningInsert[Any]: ... 

1436 

1437 def returning( 

1438 self, 

1439 *cols: _ColumnsClauseArgument[Any], 

1440 sort_by_parameter_order: bool = False, 

1441 **__kw: Any, 

1442 ) -> ReturningInsert[Any]: ... 

1443 

1444 

1445class ReturningInsert(Insert, TypedReturnsRows[_TP]): 

1446 """Typing-only class that establishes a generic type form of 

1447 :class:`.Insert` which tracks returned column types. 

1448 

1449 This datatype is delivered when calling the 

1450 :meth:`.Insert.returning` method. 

1451 

1452 .. versionadded:: 2.0 

1453 

1454 """ 

1455 

1456 

1457class DMLWhereBase: 

1458 table: _DMLTableElement 

1459 _where_criteria: Tuple[ColumnElement[Any], ...] = () 

1460 

1461 @_generative 

1462 def where(self, *whereclause: _ColumnExpressionArgument[bool]) -> Self: 

1463 """Return a new construct with the given expression(s) added to 

1464 its WHERE clause, joined to the existing clause via AND, if any. 

1465 

1466 Both :meth:`_dml.Update.where` and :meth:`_dml.Delete.where` 

1467 support multiple-table forms, including database-specific 

1468 ``UPDATE...FROM`` as well as ``DELETE..USING``. For backends that 

1469 don't have multiple-table support, a backend agnostic approach 

1470 to using multiple tables is to make use of correlated subqueries. 

1471 See the linked tutorial sections below for examples. 

1472 

1473 .. seealso:: 

1474 

1475 :ref:`tutorial_correlated_updates` 

1476 

1477 :ref:`tutorial_update_from` 

1478 

1479 :ref:`tutorial_multi_table_deletes` 

1480 

1481 """ 

1482 

1483 for criterion in whereclause: 

1484 where_criteria: ColumnElement[Any] = coercions.expect( 

1485 roles.WhereHavingRole, criterion, apply_propagate_attrs=self 

1486 ) 

1487 self._where_criteria += (where_criteria,) 

1488 return self 

1489 

1490 def filter(self, *criteria: roles.ExpressionElementRole[Any]) -> Self: 

1491 """A synonym for the :meth:`_dml.DMLWhereBase.where` method. 

1492 

1493 .. versionadded:: 1.4 

1494 

1495 """ 

1496 

1497 return self.where(*criteria) 

1498 

1499 def _filter_by_zero(self) -> _DMLTableElement: 

1500 return self.table 

1501 

1502 def filter_by(self, **kwargs: Any) -> Self: 

1503 r"""apply the given filtering criterion as a WHERE clause 

1504 to this select. 

1505 

1506 """ 

1507 from_entity = self._filter_by_zero() 

1508 

1509 clauses = [ 

1510 _entity_namespace_key(from_entity, key) == value 

1511 for key, value in kwargs.items() 

1512 ] 

1513 return self.filter(*clauses) 

1514 

1515 @property 

1516 def whereclause(self) -> Optional[ColumnElement[Any]]: 

1517 """Return the completed WHERE clause for this :class:`.DMLWhereBase` 

1518 statement. 

1519 

1520 This assembles the current collection of WHERE criteria 

1521 into a single :class:`_expression.BooleanClauseList` construct. 

1522 

1523 

1524 .. versionadded:: 1.4 

1525 

1526 """ 

1527 

1528 return BooleanClauseList._construct_for_whereclause( 

1529 self._where_criteria 

1530 ) 

1531 

1532 

1533class Update(DMLWhereBase, ValuesBase): 

1534 """Represent an Update construct. 

1535 

1536 The :class:`_expression.Update` object is created using the 

1537 :func:`_expression.update()` function. 

1538 

1539 """ 

1540 

1541 __visit_name__ = "update" 

1542 

1543 is_update = True 

1544 

1545 _traverse_internals = ( 

1546 [ 

1547 ("table", InternalTraversal.dp_clauseelement), 

1548 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1549 ("_inline", InternalTraversal.dp_boolean), 

1550 ("_ordered_values", InternalTraversal.dp_dml_ordered_values), 

1551 ("_values", InternalTraversal.dp_dml_values), 

1552 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1553 ("_hints", InternalTraversal.dp_table_hint_list), 

1554 ("_return_defaults", InternalTraversal.dp_boolean), 

1555 ( 

1556 "_return_defaults_columns", 

1557 InternalTraversal.dp_clauseelement_tuple, 

1558 ), 

1559 ] 

1560 + HasPrefixes._has_prefixes_traverse_internals 

1561 + DialectKWArgs._dialect_kwargs_traverse_internals 

1562 + Executable._executable_traverse_internals 

1563 + HasCTE._has_ctes_traverse_internals 

1564 ) 

1565 

1566 def __init__(self, table: _DMLTableArgument): 

1567 super().__init__(table) 

1568 

1569 @_generative 

1570 def ordered_values(self, *args: Tuple[_DMLColumnArgument, Any]) -> Self: 

1571 """Specify the VALUES clause of this UPDATE statement with an explicit 

1572 parameter ordering that will be maintained in the SET clause of the 

1573 resulting UPDATE statement. 

1574 

1575 E.g.:: 

1576 

1577 stmt = table.update().ordered_values(("name", "ed"), ("ident", "foo")) 

1578 

1579 .. seealso:: 

1580 

1581 :ref:`tutorial_parameter_ordered_updates` - full example of the 

1582 :meth:`_expression.Update.ordered_values` method. 

1583 

1584 .. versionchanged:: 1.4 The :meth:`_expression.Update.ordered_values` 

1585 method 

1586 supersedes the 

1587 :paramref:`_expression.update.preserve_parameter_order` 

1588 parameter, which will be removed in SQLAlchemy 2.0. 

1589 

1590 """ # noqa: E501 

1591 if self._values: 

1592 raise exc.ArgumentError( 

1593 "This statement already has values present" 

1594 ) 

1595 elif self._ordered_values: 

1596 raise exc.ArgumentError( 

1597 "This statement already has ordered values present" 

1598 ) 

1599 

1600 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs 

1601 self._ordered_values = kv_generator(self, args, True) 

1602 return self 

1603 

1604 @_generative 

1605 def inline(self) -> Self: 

1606 """Make this :class:`_expression.Update` construct "inline" . 

1607 

1608 When set, SQL defaults present on :class:`_schema.Column` 

1609 objects via the 

1610 ``default`` keyword will be compiled 'inline' into the statement and 

1611 not pre-executed. This means that their values will not be available 

1612 in the dictionary returned from 

1613 :meth:`_engine.CursorResult.last_updated_params`. 

1614 

1615 .. versionchanged:: 1.4 the :paramref:`_expression.update.inline` 

1616 parameter 

1617 is now superseded by the :meth:`_expression.Update.inline` method. 

1618 

1619 """ 

1620 self._inline = True 

1621 return self 

1622 

1623 if TYPE_CHECKING: 

1624 # START OVERLOADED FUNCTIONS self.returning ReturningUpdate 1-8 

1625 

1626 # code within this block is **programmatically, 

1627 # statically generated** by tools/generate_tuple_map_overloads.py 

1628 

1629 @overload 

1630 def returning( 

1631 self, __ent0: _TCCA[_T0] 

1632 ) -> ReturningUpdate[Tuple[_T0]]: ... 

1633 

1634 @overload 

1635 def returning( 

1636 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1] 

1637 ) -> ReturningUpdate[Tuple[_T0, _T1]]: ... 

1638 

1639 @overload 

1640 def returning( 

1641 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2] 

1642 ) -> ReturningUpdate[Tuple[_T0, _T1, _T2]]: ... 

1643 

1644 @overload 

1645 def returning( 

1646 self, 

1647 __ent0: _TCCA[_T0], 

1648 __ent1: _TCCA[_T1], 

1649 __ent2: _TCCA[_T2], 

1650 __ent3: _TCCA[_T3], 

1651 ) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3]]: ... 

1652 

1653 @overload 

1654 def returning( 

1655 self, 

1656 __ent0: _TCCA[_T0], 

1657 __ent1: _TCCA[_T1], 

1658 __ent2: _TCCA[_T2], 

1659 __ent3: _TCCA[_T3], 

1660 __ent4: _TCCA[_T4], 

1661 ) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4]]: ... 

1662 

1663 @overload 

1664 def returning( 

1665 self, 

1666 __ent0: _TCCA[_T0], 

1667 __ent1: _TCCA[_T1], 

1668 __ent2: _TCCA[_T2], 

1669 __ent3: _TCCA[_T3], 

1670 __ent4: _TCCA[_T4], 

1671 __ent5: _TCCA[_T5], 

1672 ) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ... 

1673 

1674 @overload 

1675 def returning( 

1676 self, 

1677 __ent0: _TCCA[_T0], 

1678 __ent1: _TCCA[_T1], 

1679 __ent2: _TCCA[_T2], 

1680 __ent3: _TCCA[_T3], 

1681 __ent4: _TCCA[_T4], 

1682 __ent5: _TCCA[_T5], 

1683 __ent6: _TCCA[_T6], 

1684 ) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ... 

1685 

1686 @overload 

1687 def returning( 

1688 self, 

1689 __ent0: _TCCA[_T0], 

1690 __ent1: _TCCA[_T1], 

1691 __ent2: _TCCA[_T2], 

1692 __ent3: _TCCA[_T3], 

1693 __ent4: _TCCA[_T4], 

1694 __ent5: _TCCA[_T5], 

1695 __ent6: _TCCA[_T6], 

1696 __ent7: _TCCA[_T7], 

1697 ) -> ReturningUpdate[ 

1698 Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7] 

1699 ]: ... 

1700 

1701 # END OVERLOADED FUNCTIONS self.returning 

1702 

1703 @overload 

1704 def returning( 

1705 self, *cols: _ColumnsClauseArgument[Any], **__kw: Any 

1706 ) -> ReturningUpdate[Any]: ... 

1707 

1708 def returning( 

1709 self, *cols: _ColumnsClauseArgument[Any], **__kw: Any 

1710 ) -> ReturningUpdate[Any]: ... 

1711 

1712 

1713class ReturningUpdate(Update, TypedReturnsRows[_TP]): 

1714 """Typing-only class that establishes a generic type form of 

1715 :class:`.Update` which tracks returned column types. 

1716 

1717 This datatype is delivered when calling the 

1718 :meth:`.Update.returning` method. 

1719 

1720 .. versionadded:: 2.0 

1721 

1722 """ 

1723 

1724 

1725class Delete(DMLWhereBase, UpdateBase): 

1726 """Represent a DELETE construct. 

1727 

1728 The :class:`_expression.Delete` object is created using the 

1729 :func:`_expression.delete()` function. 

1730 

1731 """ 

1732 

1733 __visit_name__ = "delete" 

1734 

1735 is_delete = True 

1736 

1737 _traverse_internals = ( 

1738 [ 

1739 ("table", InternalTraversal.dp_clauseelement), 

1740 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1741 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1742 ("_hints", InternalTraversal.dp_table_hint_list), 

1743 ] 

1744 + HasPrefixes._has_prefixes_traverse_internals 

1745 + DialectKWArgs._dialect_kwargs_traverse_internals 

1746 + Executable._executable_traverse_internals 

1747 + HasCTE._has_ctes_traverse_internals 

1748 ) 

1749 

1750 def __init__(self, table: _DMLTableArgument): 

1751 self.table = coercions.expect( 

1752 roles.DMLTableRole, table, apply_propagate_attrs=self 

1753 ) 

1754 

1755 if TYPE_CHECKING: 

1756 # START OVERLOADED FUNCTIONS self.returning ReturningDelete 1-8 

1757 

1758 # code within this block is **programmatically, 

1759 # statically generated** by tools/generate_tuple_map_overloads.py 

1760 

1761 @overload 

1762 def returning( 

1763 self, __ent0: _TCCA[_T0] 

1764 ) -> ReturningDelete[Tuple[_T0]]: ... 

1765 

1766 @overload 

1767 def returning( 

1768 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1] 

1769 ) -> ReturningDelete[Tuple[_T0, _T1]]: ... 

1770 

1771 @overload 

1772 def returning( 

1773 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2] 

1774 ) -> ReturningDelete[Tuple[_T0, _T1, _T2]]: ... 

1775 

1776 @overload 

1777 def returning( 

1778 self, 

1779 __ent0: _TCCA[_T0], 

1780 __ent1: _TCCA[_T1], 

1781 __ent2: _TCCA[_T2], 

1782 __ent3: _TCCA[_T3], 

1783 ) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3]]: ... 

1784 

1785 @overload 

1786 def returning( 

1787 self, 

1788 __ent0: _TCCA[_T0], 

1789 __ent1: _TCCA[_T1], 

1790 __ent2: _TCCA[_T2], 

1791 __ent3: _TCCA[_T3], 

1792 __ent4: _TCCA[_T4], 

1793 ) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4]]: ... 

1794 

1795 @overload 

1796 def returning( 

1797 self, 

1798 __ent0: _TCCA[_T0], 

1799 __ent1: _TCCA[_T1], 

1800 __ent2: _TCCA[_T2], 

1801 __ent3: _TCCA[_T3], 

1802 __ent4: _TCCA[_T4], 

1803 __ent5: _TCCA[_T5], 

1804 ) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ... 

1805 

1806 @overload 

1807 def returning( 

1808 self, 

1809 __ent0: _TCCA[_T0], 

1810 __ent1: _TCCA[_T1], 

1811 __ent2: _TCCA[_T2], 

1812 __ent3: _TCCA[_T3], 

1813 __ent4: _TCCA[_T4], 

1814 __ent5: _TCCA[_T5], 

1815 __ent6: _TCCA[_T6], 

1816 ) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ... 

1817 

1818 @overload 

1819 def returning( 

1820 self, 

1821 __ent0: _TCCA[_T0], 

1822 __ent1: _TCCA[_T1], 

1823 __ent2: _TCCA[_T2], 

1824 __ent3: _TCCA[_T3], 

1825 __ent4: _TCCA[_T4], 

1826 __ent5: _TCCA[_T5], 

1827 __ent6: _TCCA[_T6], 

1828 __ent7: _TCCA[_T7], 

1829 ) -> ReturningDelete[ 

1830 Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7] 

1831 ]: ... 

1832 

1833 # END OVERLOADED FUNCTIONS self.returning 

1834 

1835 @overload 

1836 def returning( 

1837 self, *cols: _ColumnsClauseArgument[Any], **__kw: Any 

1838 ) -> ReturningDelete[Any]: ... 

1839 

1840 def returning( 

1841 self, *cols: _ColumnsClauseArgument[Any], **__kw: Any 

1842 ) -> ReturningDelete[Any]: ... 

1843 

1844 

1845class ReturningDelete(Update, TypedReturnsRows[_TP]): 

1846 """Typing-only class that establishes a generic type form of 

1847 :class:`.Delete` which tracks returned column types. 

1848 

1849 This datatype is delivered when calling the 

1850 :meth:`.Delete.returning` method. 

1851 

1852 .. versionadded:: 2.0 

1853 

1854 """