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

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

493 statements  

1# sql/dml.py 

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

12from __future__ import annotations 

13 

14import collections.abc as collections_abc 

15import operator 

16from typing import Any 

17from typing import cast 

18from typing import Dict 

19from typing import Iterable 

20from typing import List 

21from typing import Literal 

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 TypeGuard 

32from typing import TypeVar 

33from typing import Union 

34 

35from . import coercions 

36from . import roles 

37from . import util as sql_util 

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 .base import HasSyntaxExtensions 

54from .base import SyntaxExtension 

55from .elements import BooleanClauseList 

56from .elements import ClauseElement 

57from .elements import ColumnClause 

58from .elements import ColumnElement 

59from .elements import Null 

60from .selectable import Alias 

61from .selectable import ExecutableReturnsRows 

62from .selectable import FromClause 

63from .selectable import HasCTE 

64from .selectable import HasPrefixes 

65from .selectable import Join 

66from .selectable import SelectLabelStyle 

67from .selectable import TableClause 

68from .selectable import TypedReturnsRows 

69from .sqltypes import NullType 

70from .visitors import InternalTraversal 

71from .. import exc 

72from .. import util 

73from ..util.typing import Self 

74from ..util.typing import TupleAny 

75from ..util.typing import TypeVarTuple 

76from ..util.typing import Unpack 

77 

78 

79if TYPE_CHECKING: 

80 from ._typing import _ColumnExpressionArgument 

81 from ._typing import _ColumnsClauseArgument 

82 from ._typing import _DMLColumnArgument 

83 from ._typing import _DMLColumnKeyMapping 

84 from ._typing import _DMLTableArgument 

85 from ._typing import _T0 # noqa 

86 from ._typing import _T1 # noqa 

87 from ._typing import _T2 # noqa 

88 from ._typing import _T3 # noqa 

89 from ._typing import _T4 # noqa 

90 from ._typing import _T5 # noqa 

91 from ._typing import _T6 # noqa 

92 from ._typing import _T7 # noqa 

93 from ._typing import _TypedColumnClauseArgument as _TCCA # noqa 

94 from .base import ReadOnlyColumnCollection 

95 from .compiler import SQLCompiler 

96 from .elements import KeyedColumnElement 

97 from .selectable import _ColumnsClauseElement 

98 from .selectable import _SelectIterable 

99 from .selectable import Select 

100 from .selectable import Selectable 

101 

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

103 

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

105 

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

107 

108else: 

109 isupdate = operator.attrgetter("isupdate") 

110 isdelete = operator.attrgetter("isdelete") 

111 isinsert = operator.attrgetter("isinsert") 

112 

113 

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

115_Ts = TypeVarTuple("_Ts") 

116 

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

118_DMLTableElement = Union[TableClause, Alias, Join] 

119 

120 

121class DMLState(CompileState): 

122 _no_parameters = True 

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

124 _multi_parameters: Optional[ 

125 List[MutableMapping[_DMLColumnElement, Any]] 

126 ] = None 

127 _maintain_values_ordering: bool = False 

128 _primary_table: FromClause 

129 _supports_implicit_returning = True 

130 

131 isupdate = False 

132 isdelete = False 

133 isinsert = False 

134 

135 statement: UpdateBase 

136 

137 def __init__( 

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

139 ): 

140 raise NotImplementedError() 

141 

142 @classmethod 

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

144 return { 

145 "name": ( 

146 statement.table.name 

147 if is_named_from_clause(statement.table) 

148 else None 

149 ), 

150 "table": statement.table, 

151 } 

152 

153 @classmethod 

154 def get_returning_column_descriptions( 

155 cls, statement: UpdateBase 

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

157 return [ 

158 { 

159 "name": c.key, 

160 "type": c.type, 

161 "expr": c, 

162 } 

163 for c in statement._all_selected_columns 

164 ] 

165 

166 @property 

167 def dml_table(self) -> _DMLTableElement: 

168 return self.statement.table 

169 

170 if TYPE_CHECKING: 

171 

172 @classmethod 

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

174 

175 @classmethod 

176 def _get_multi_crud_kv_pairs( 

177 cls, 

178 statement: UpdateBase, 

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

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

181 return [ 

182 { 

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

184 for k, v in mapping.items() 

185 } 

186 for mapping in multi_kv_iterator 

187 ] 

188 

189 @classmethod 

190 def _get_crud_kv_pairs( 

191 cls, 

192 statement: UpdateBase, 

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

194 needs_to_be_cacheable: bool, 

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

196 return [ 

197 ( 

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

199 ( 

200 v 

201 if not needs_to_be_cacheable 

202 else coercions.expect( 

203 roles.ExpressionElementRole, 

204 v, 

205 type_=NullType(), 

206 is_crud=True, 

207 ) 

208 ), 

209 ) 

210 for k, v in kv_iterator 

211 ] 

212 

213 def _make_extra_froms( 

214 self, statement: DMLWhereBase 

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

216 froms: List[FromClause] = [] 

217 

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

219 primary_table = all_tables[0] 

220 seen = {primary_table} 

221 

222 consider = statement._where_criteria 

223 if self._dict_parameters: 

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

225 

226 for crit in consider: 

227 for item in _from_objects(crit): 

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

229 froms.append(item) 

230 seen.update(item._cloned_set) 

231 

232 froms.extend(all_tables[1:]) 

233 return primary_table, froms 

234 

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

236 if self._no_parameters: 

237 self._dict_parameters = statement._values 

238 self._no_parameters = False 

239 

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

241 assert statement._select_names is not None 

242 parameters: MutableMapping[_DMLColumnElement, Any] = { 

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

244 } 

245 

246 if self._no_parameters: 

247 self._no_parameters = False 

248 self._dict_parameters = parameters 

249 else: 

250 # this condition normally not reachable as the Insert 

251 # does not allow this construction to occur 

252 assert False, "This statement already has parameters" 

253 

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

255 raise exc.InvalidRequestError( 

256 "%s construct does not support " 

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

258 ) 

259 

260 def _cant_mix_formats_error(self) -> NoReturn: 

261 raise exc.InvalidRequestError( 

262 "Can't mix single and multiple VALUES " 

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

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

265 "ambiguous." 

266 ) 

267 

268 

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

270class InsertDMLState(DMLState): 

271 isinsert = True 

272 

273 include_table_with_column_exprs = False 

274 

275 _has_multi_parameters = False 

276 

277 def __init__( 

278 self, 

279 statement: Insert, 

280 compiler: SQLCompiler, 

281 disable_implicit_returning: bool = False, 

282 **kw: Any, 

283 ): 

284 self.statement = statement 

285 self._primary_table = statement.table 

286 

287 if disable_implicit_returning: 

288 self._supports_implicit_returning = False 

289 

290 self.isinsert = True 

291 if statement._select_names: 

292 self._process_select_values(statement) 

293 if statement._values is not None: 

294 self._process_values(statement) 

295 if statement._multi_values: 

296 self._process_multi_values(statement) 

297 

298 @util.memoized_property 

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

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

301 return [ 

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

303 for col in self._dict_parameters or () 

304 ] 

305 

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

307 if self._no_parameters: 

308 self._has_multi_parameters = False 

309 self._dict_parameters = statement._values 

310 self._no_parameters = False 

311 elif self._has_multi_parameters: 

312 self._cant_mix_formats_error() 

313 

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

315 for parameters in statement._multi_values: 

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

317 ( 

318 { 

319 c.key: value 

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

321 } 

322 if isinstance(parameter_set, collections_abc.Sequence) 

323 else parameter_set 

324 ) 

325 for parameter_set in parameters 

326 ] 

327 

328 if self._no_parameters: 

329 self._no_parameters = False 

330 self._has_multi_parameters = True 

331 self._multi_parameters = multi_parameters 

332 self._dict_parameters = self._multi_parameters[0] 

333 elif not self._has_multi_parameters: 

334 self._cant_mix_formats_error() 

335 else: 

336 assert self._multi_parameters 

337 self._multi_parameters.extend(multi_parameters) 

338 

339 

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

341class UpdateDMLState(DMLState): 

342 isupdate = True 

343 

344 include_table_with_column_exprs = False 

345 

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

347 self.statement = statement 

348 

349 self.isupdate = True 

350 if statement._maintain_values_ordering: 

351 self._process_ordered_values(statement) 

352 elif statement._values is not None: 

353 self._process_values(statement) 

354 elif statement._multi_values: 

355 self._no_multi_values_supported(statement) 

356 t, ef = self._make_extra_froms(statement) 

357 self._primary_table = t 

358 self._extra_froms = ef 

359 

360 self.is_multitable = mt = ef 

361 self.include_table_with_column_exprs = bool( 

362 mt and compiler.render_table_with_column_in_update_from 

363 ) 

364 

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

366 parameters = statement._values 

367 if self._no_parameters: 

368 self._no_parameters = False 

369 assert parameters is not None 

370 self._dict_parameters = dict(parameters) 

371 self._maintain_values_ordering = True 

372 else: 

373 raise exc.InvalidRequestError( 

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

375 "with any other values() call" 

376 ) 

377 

378 

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

380class DeleteDMLState(DMLState): 

381 isdelete = True 

382 

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

384 self.statement = statement 

385 

386 self.isdelete = True 

387 t, ef = self._make_extra_froms(statement) 

388 self._primary_table = t 

389 self._extra_froms = ef 

390 self.is_multitable = ef 

391 

392 

393class UpdateBase( 

394 roles.DMLRole, 

395 HasCTE, 

396 HasCompileState, 

397 DialectKWArgs, 

398 HasPrefixes, 

399 Generative, 

400 ExecutableReturnsRows, 

401 ClauseElement, 

402): 

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

404 

405 __visit_name__ = "update_base" 

406 

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

408 util.EMPTY_DICT 

409 ) 

410 named_with_column = False 

411 

412 _label_style: SelectLabelStyle = ( 

413 SelectLabelStyle.LABEL_STYLE_DISAMBIGUATE_ONLY 

414 ) 

415 table: _DMLTableElement 

416 

417 _return_defaults = False 

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

419 None 

420 ) 

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

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

423 

424 is_dml = True 

425 

426 def _generate_fromclause_column_proxies( 

427 self, 

428 fromclause: FromClause, 

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

430 primary_key: ColumnSet, 

431 foreign_keys: Set[KeyedColumnElement[Any]], 

432 ) -> None: 

433 prox = [ 

434 c._make_proxy( 

435 fromclause, 

436 key=proxy_key, 

437 name=required_label_name, 

438 name_is_truncatable=True, 

439 primary_key=primary_key, 

440 foreign_keys=foreign_keys, 

441 ) 

442 for ( 

443 required_label_name, 

444 proxy_key, 

445 fallback_label_name, 

446 c, 

447 repeated, 

448 ) in (self._generate_columns_plus_names(False)) 

449 if is_column_element(c) 

450 ] 

451 

452 columns._populate_separate_keys(prox) 

453 

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

455 """Set the parameters for the statement. 

456 

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

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

459 SET/VALUES clause of UPDATE and INSERT. 

460 

461 """ 

462 raise NotImplementedError( 

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

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

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

466 ) 

467 

468 @_generative 

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

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

471 

472 e.g.:: 

473 

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

475 

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

477 associated with the constructor. 

478 

479 

480 """ 

481 self._validate_dialect_kwargs(opt) 

482 return self 

483 

484 @_generative 

485 def return_defaults( 

486 self, 

487 *cols: _DMLColumnArgument, 

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

489 sort_by_parameter_order: bool = False, 

490 ) -> Self: 

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

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

493 backends only. 

494 

495 .. deepalchemy:: 

496 

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

498 for its internal work in fetching newly generated primary key 

499 and server default values, in particular to provide the underyling 

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

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

502 ORM inserts. Its behavior is fairly idiosyncratic 

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

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

505 add RETURNING clauses to their INSERT, UPDATE and DELETE 

506 statements. 

507 

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

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

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

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

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

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

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

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

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

517 value. 

518 

519 However, when the statement is modified by calling 

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

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

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

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

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

525 from the statement's execution, not only will 

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

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

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

529 of server generated 

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

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

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

533 

534 When invoking INSERT statements with multiple rows using 

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

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

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

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

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

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

541 values for each row inserted. The 

542 :attr:`.CursorResult.inserted_primary_key` and 

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

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

545 

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

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

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

549 INSERT, UPDATE or DELETE statement proceeds normally. 

550 

551 E.g.:: 

552 

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

554 

555 result = connection.execute(stmt) 

556 

557 server_created_at = result.returned_defaults["created_at"] 

558 

559 When used against an UPDATE statement 

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

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

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

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

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

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

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

567 normally change values when a DELETE statement proceeds. 

568 

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

570 for DELETE statements also and has been moved from 

571 :class:`.ValuesBase` to :class:`.UpdateBase`. 

572 

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

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

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

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

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

578 at a time. 

579 

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

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

582 

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

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

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

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

587 

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

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

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

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

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

593 attribute being left unpopulated. 

594 

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

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

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

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

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

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

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

602 ``False``. 

603 

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

605 backend database driver supports the 

606 :ref:`insertmanyvalues <engine_insertmanyvalues>` 

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

608 When executemany is used, the 

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

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

611 will return the inserted defaults and primary keys. 

612 

613 .. versionadded:: 1.4 Added 

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

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

616 In version 2.0, the underlying implementation which fetches and 

617 populates the data for these attributes was generalized to be 

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

619 supported by the ``psycopg2`` driver. 

620 

621 

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

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

624 will be fetched. 

625 :param supplemental_cols: optional list of RETURNING expressions, 

626 in the same form as one would pass to the 

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

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

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

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

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

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

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

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

635 reliably be targeted positionally. 

636 

637 .. versionadded:: 2.0 

638 

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

640 executed against multiple parameter sets, organize the results of 

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

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

643 execution for supporting dialects and typically makes use of the 

644 :term:`insertmanyvalues` feature. 

645 

646 .. versionadded:: 2.0.10 

647 

648 .. seealso:: 

649 

650 :ref:`engine_insertmanyvalues_returning_order` - background on 

651 sorting of RETURNING rows for bulk INSERT 

652 

653 .. seealso:: 

654 

655 :meth:`.UpdateBase.returning` 

656 

657 :attr:`_engine.CursorResult.returned_defaults` 

658 

659 :attr:`_engine.CursorResult.returned_defaults_rows` 

660 

661 :attr:`_engine.CursorResult.inserted_primary_key` 

662 

663 :attr:`_engine.CursorResult.inserted_primary_key_rows` 

664 

665 """ 

666 

667 if self._return_defaults: 

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

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

670 # are columns in the collection 

671 if self._return_defaults_columns and cols: 

672 self._return_defaults_columns = tuple( 

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

674 coercions.expect(roles.ColumnsClauseRole, c) 

675 for c in cols 

676 ) 

677 ) 

678 else: 

679 # set for all columns 

680 self._return_defaults_columns = () 

681 else: 

682 self._return_defaults_columns = tuple( 

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

684 ) 

685 self._return_defaults = True 

686 if sort_by_parameter_order: 

687 if not self.is_insert: 

688 raise exc.ArgumentError( 

689 "The 'sort_by_parameter_order' argument to " 

690 "return_defaults() only applies to INSERT statements" 

691 ) 

692 self._sort_by_parameter_order = True 

693 if supplemental_cols: 

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

695 # is for test suites but also for vertical splicing 

696 supplemental_col_tup = ( 

697 coercions.expect(roles.ColumnsClauseRole, c) 

698 for c in supplemental_cols 

699 ) 

700 

701 if self._supplemental_returning is None: 

702 self._supplemental_returning = tuple( 

703 util.unique_list(supplemental_col_tup) 

704 ) 

705 else: 

706 self._supplemental_returning = tuple( 

707 util.unique_list( 

708 self._supplemental_returning 

709 + tuple(supplemental_col_tup) 

710 ) 

711 ) 

712 

713 return self 

714 

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

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

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

718 

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

720 so we return False for derives. 

721 

722 """ 

723 return False 

724 

725 @_generative 

726 def returning( 

727 self, 

728 *cols: _ColumnsClauseArgument[Any], 

729 sort_by_parameter_order: bool = False, 

730 **__kw: Any, 

731 ) -> UpdateBase: 

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

733 

734 e.g.: 

735 

736 .. sourcecode:: pycon+sql 

737 

738 >>> stmt = ( 

739 ... table.update() 

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

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

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

743 ... ) 

744 >>> print(stmt) 

745 {printsql}UPDATE some_table SET status=:status 

746 WHERE some_table.data = :data_1 

747 RETURNING some_table.server_flag, some_table.updated_timestamp 

748 

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

750 list of expressions to be returned. 

751 

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

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

754 

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

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

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

758 expressions: 

759 

760 .. sourcecode:: pycon+sql 

761 

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

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

764 ... ) 

765 >>> print(stmt) 

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

767 VALUES (:first_name, :last_name) 

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

769 

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

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

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

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

774 

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

776 available via the result set and can be iterated using 

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

778 For DBAPIs which do not 

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

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

781 amount of behavioral neutrality is provided. 

782 

783 Note that not all databases/DBAPIs 

784 support RETURNING. For those backends with no support, 

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

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

787 varies greatly, including restrictions on executemany() 

788 and other statements which return multiple rows. Please 

789 read the documentation notes for the database in use in 

790 order to determine the availability of RETURNING. 

791 

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

793 entities to be returned. 

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

795 executed against multiple parameter sets, organize the results of 

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

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

798 execution for supporting dialects and typically makes use of the 

799 :term:`insertmanyvalues` feature. 

800 

801 .. versionadded:: 2.0.10 

802 

803 .. seealso:: 

804 

805 :ref:`engine_insertmanyvalues_returning_order` - background on 

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

807 

808 :ref:`orm_queryguide_bulk_insert_returning_ordered` - example of 

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

810 

811 .. seealso:: 

812 

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

814 towards efficient fetching of server-side defaults and triggers 

815 for single-row INSERTs or UPDATEs. 

816 

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

818 

819 """ # noqa: E501 

820 if __kw: 

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

822 if self._return_defaults: 

823 raise exc.InvalidRequestError( 

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

825 ) 

826 self._returning += tuple( 

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

828 ) 

829 if sort_by_parameter_order: 

830 if not self.is_insert: 

831 raise exc.ArgumentError( 

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

833 "only applies to INSERT statements" 

834 ) 

835 self._sort_by_parameter_order = True 

836 return self 

837 

838 def corresponding_column( 

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

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

841 return self.exported_columns.corresponding_column( 

842 column, require_embedded=require_embedded 

843 ) 

844 

845 @util.ro_memoized_property 

846 def _all_selected_columns(self) -> _SelectIterable: 

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

848 

849 @util.ro_memoized_property 

850 def exported_columns( 

851 self, 

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

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

854 statement. 

855 

856 .. versionadded:: 1.4 

857 

858 """ 

859 return ColumnCollection( 

860 (c.key, c) 

861 for c in self._all_selected_columns 

862 if is_column_element(c) 

863 ).as_readonly() 

864 

865 @_generative 

866 def with_hint( 

867 self, 

868 text: str, 

869 selectable: Optional[_DMLTableArgument] = None, 

870 dialect_name: str = "*", 

871 ) -> Self: 

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

873 INSERT/UPDATE/DELETE statement. 

874 

875 .. note:: 

876 

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

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

879 :meth:`.UpdateBase.prefix_with`. 

880 

881 The text of the hint is rendered in the appropriate 

882 location for the database backend in use, relative 

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

884 statement, or optionally to that of the given 

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

886 

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

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

889 that only takes effect for SQL Server:: 

890 

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

892 

893 :param text: Text of the hint. 

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

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

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

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

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

899 that dialect is in use. 

900 """ 

901 if selectable is None: 

902 selectable = self.table 

903 else: 

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

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

906 return self 

907 

908 @property 

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

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

911 entity which this DML construct is operating against. 

912 

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

914 extended structure which includes information about mapped 

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

916 contains more background. 

917 

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

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

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

921 

922 >>> stmt = insert(user_table) 

923 >>> stmt.entity_description 

924 { 

925 "name": "user_table", 

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

927 } 

928 

929 .. versionadded:: 1.4.33 

930 

931 .. seealso:: 

932 

933 :attr:`.UpdateBase.returning_column_descriptions` 

934 

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

936 a :func:`.select` construct 

937 

938 :ref:`queryguide_inspection` - ORM background 

939 

940 """ 

941 meth = DMLState.get_plugin_class(self).get_entity_description 

942 return meth(self) 

943 

944 @property 

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

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

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

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

949 

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

951 extended structure which includes information about mapped 

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

953 contains more background. 

954 

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

956 derived from the same objects that are returned by the 

957 :attr:`.UpdateBase.exported_columns` accessor:: 

958 

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

960 >>> stmt.entity_description 

961 [ 

962 { 

963 "name": "id", 

964 "type": Integer, 

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

966 }, 

967 { 

968 "name": "name", 

969 "type": String(), 

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

971 }, 

972 ] 

973 

974 .. versionadded:: 1.4.33 

975 

976 .. seealso:: 

977 

978 :attr:`.UpdateBase.entity_description` 

979 

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

981 a :func:`.select` construct 

982 

983 :ref:`queryguide_inspection` - ORM background 

984 

985 """ # noqa: E501 

986 meth = DMLState.get_plugin_class( 

987 self 

988 ).get_returning_column_descriptions 

989 return meth(self) 

990 

991 

992class ValuesBase(UpdateBase): 

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

994 INSERT and UPDATE constructs.""" 

995 

996 __visit_name__ = "values_base" 

997 

998 _supports_multi_parameters = False 

999 

1000 select: Optional[Select[Unpack[TupleAny]]] = None 

1001 """SELECT statement for INSERT .. FROM SELECT""" 

1002 

1003 _post_values_clause: Optional[ClauseElement] = None 

1004 """used by extensions to Insert etc. to add additional syntactical 

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

1006 

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

1008 _multi_values: Tuple[ 

1009 Union[ 

1010 Sequence[Dict[_DMLColumnElement, Any]], 

1011 Sequence[Sequence[Any]], 

1012 ], 

1013 ..., 

1014 ] = () 

1015 

1016 _maintain_values_ordering: bool = False 

1017 

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

1019 _inline: bool = False 

1020 

1021 def __init__(self, table: _DMLTableArgument): 

1022 self.table = coercions.expect( 

1023 roles.DMLTableRole, table, apply_propagate_attrs=self 

1024 ) 

1025 

1026 @_generative 

1027 @_exclusive_against( 

1028 "_select_names", 

1029 "_maintain_values_ordering", 

1030 msgs={ 

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

1032 "_maintain_values_ordering": "This statement already has ordered " 

1033 "values present", 

1034 }, 

1035 defaults={"_maintain_values_ordering": False}, 

1036 ) 

1037 def values( 

1038 self, 

1039 *args: Union[ 

1040 _DMLColumnKeyMapping[Any], 

1041 Sequence[Any], 

1042 ], 

1043 **kwargs: Any, 

1044 ) -> Self: 

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

1046 clause for an UPDATE. 

1047 

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

1049 :class:`_expression.Update` 

1050 constructs support 

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

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

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

1054 particular set of parameters into the statement. 

1055 

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

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

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

1059 dictionary of parameters, the newly passed keys will replace 

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

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

1062 onto the existing list of values. 

1063 

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

1065 of a :class:`_schema.Column` 

1066 mapped to the value to be rendered into the 

1067 VALUES or SET clause:: 

1068 

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

1070 

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

1072 

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

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

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

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

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

1078 :class:`_expression.Update` construct. 

1079 

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

1081 :class:`_expression.Update` 

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

1083 that of the kwargs form:: 

1084 

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

1086 

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

1088 

1089 Also for either form but more typically for the 

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

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

1092 

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

1094 

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

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

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

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

1099 MySQL, but not necessarily others:: 

1100 

1101 users.insert().values( 

1102 [ 

1103 {"name": "some name"}, 

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

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

1106 ] 

1107 ) 

1108 

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

1110 

1111 .. sourcecode:: sql 

1112 

1113 INSERT INTO users (name) VALUES 

1114 (:name_1), 

1115 (:name_2), 

1116 (:name_3) 

1117 

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

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

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

1121 INSERT statement against multiple rows, the normal method is 

1122 to pass a multiple values list to the 

1123 :meth:`_engine.Connection.execute` 

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

1125 more efficient for a very large number of parameters. 

1126 

1127 .. seealso:: 

1128 

1129 :ref:`tutorial_multiple_parameters` - an introduction to 

1130 the traditional Core method of multiple parameter set 

1131 invocation for INSERTs and other statements. 

1132 

1133 The UPDATE construct also supports rendering the SET parameters 

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

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

1136 

1137 .. seealso:: 

1138 

1139 :meth:`_expression.Update.ordered_values` 

1140 

1141 

1142 """ 

1143 if args: 

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

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

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

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

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

1149 arg = args[0] 

1150 

1151 if kwargs: 

1152 raise exc.ArgumentError( 

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

1154 "simultaneously" 

1155 ) 

1156 elif len(args) > 1: 

1157 raise exc.ArgumentError( 

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

1159 "dictionaries/tuples is accepted positionally." 

1160 ) 

1161 

1162 elif isinstance(arg, collections_abc.Sequence): 

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

1164 multi_kv_generator = DMLState.get_plugin_class( 

1165 self 

1166 )._get_multi_crud_kv_pairs 

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

1168 return self 

1169 

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

1171 self._multi_values += (arg,) 

1172 return self 

1173 

1174 if TYPE_CHECKING: 

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

1176 # case 

1177 assert isinstance(self, Insert) 

1178 

1179 # tuple values 

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

1181 

1182 else: 

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

1184 # so this is fairly quick. 

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

1186 if args: 

1187 raise exc.ArgumentError( 

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

1189 "dictionaries/tuples is accepted positionally." 

1190 ) 

1191 

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

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

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

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

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

1197 

1198 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs 

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

1200 if self._values: 

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

1202 else: 

1203 self._values = util.immutabledict(coerced_arg) 

1204 return self 

1205 

1206 

1207class Insert(ValuesBase, HasSyntaxExtensions[Literal["post_values"]]): 

1208 """Represent an INSERT construct. 

1209 

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

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

1212 

1213 Available extension points: 

1214 

1215 * ``post_values``: applies additional logic after the ``VALUES`` clause. 

1216 

1217 """ 

1218 

1219 __visit_name__ = "insert" 

1220 

1221 _supports_multi_parameters = True 

1222 

1223 select = None 

1224 include_insert_from_select_defaults = False 

1225 

1226 _sort_by_parameter_order: bool = False 

1227 

1228 is_insert = True 

1229 

1230 table: TableClause 

1231 

1232 _traverse_internals = ( 

1233 [ 

1234 ("table", InternalTraversal.dp_clauseelement), 

1235 ("_inline", InternalTraversal.dp_boolean), 

1236 ("_select_names", InternalTraversal.dp_string_list), 

1237 ("_values", InternalTraversal.dp_dml_values), 

1238 ("_multi_values", InternalTraversal.dp_dml_multi_values), 

1239 ("select", InternalTraversal.dp_clauseelement), 

1240 ("_post_values_clause", InternalTraversal.dp_clauseelement), 

1241 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1242 ("_hints", InternalTraversal.dp_table_hint_list), 

1243 ("_return_defaults", InternalTraversal.dp_boolean), 

1244 ( 

1245 "_return_defaults_columns", 

1246 InternalTraversal.dp_clauseelement_tuple, 

1247 ), 

1248 ("_sort_by_parameter_order", InternalTraversal.dp_boolean), 

1249 ] 

1250 + HasPrefixes._has_prefixes_traverse_internals 

1251 + DialectKWArgs._dialect_kwargs_traverse_internals 

1252 + Executable._executable_traverse_internals 

1253 + HasCTE._has_ctes_traverse_internals 

1254 ) 

1255 

1256 _position_map = util.immutabledict( 

1257 { 

1258 "post_values": "_post_values_clause", 

1259 } 

1260 ) 

1261 

1262 _post_values_clause: Optional[ClauseElement] = None 

1263 """extension point for a ClauseElement that will be compiled directly 

1264 after the VALUES portion of the :class:`.Insert` statement 

1265 

1266 """ 

1267 

1268 def __init__(self, table: _DMLTableArgument): 

1269 super().__init__(table) 

1270 

1271 def _apply_syntax_extension_to_self( 

1272 self, extension: SyntaxExtension 

1273 ) -> None: 

1274 extension.apply_to_insert(self) 

1275 

1276 @_generative 

1277 def inline(self) -> Self: 

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

1279 

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

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

1282 in particular, 

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

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

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

1286 returning" feature for the statement. 

1287 

1288 

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

1290 parameter 

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

1292 

1293 """ 

1294 self._inline = True 

1295 return self 

1296 

1297 @_generative 

1298 def from_select( 

1299 self, 

1300 names: Sequence[_DMLColumnArgument], 

1301 select: Selectable, 

1302 include_defaults: bool = True, 

1303 ) -> Self: 

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

1305 an ``INSERT...FROM SELECT`` statement. 

1306 

1307 e.g.:: 

1308 

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

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

1311 

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

1313 :class:`_schema.Column` 

1314 objects representing the target columns. 

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

1316 :class:`_expression.FromClause` 

1317 or other construct which resolves into a 

1318 :class:`_expression.FromClause`, 

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

1320 columns returned from this FROM clause should correspond to the 

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

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

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

1324 correspond. 

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

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

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

1328 otherwise specified in the list of names will be rendered 

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

1330 included in the data to be inserted. 

1331 

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

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

1334 per row**. 

1335 

1336 """ 

1337 

1338 if self._values: 

1339 raise exc.InvalidRequestError( 

1340 "This construct already inserts value expressions" 

1341 ) 

1342 

1343 self._select_names = [ 

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

1345 for name in names 

1346 ] 

1347 self._inline = True 

1348 self.include_insert_from_select_defaults = include_defaults 

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

1350 return self 

1351 

1352 if TYPE_CHECKING: 

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

1354 

1355 # code within this block is **programmatically, 

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

1357 

1358 @overload 

1359 def returning( 

1360 self, 

1361 __ent0: _TCCA[_T0], 

1362 /, 

1363 *, 

1364 sort_by_parameter_order: bool = False, 

1365 ) -> ReturningInsert[_T0]: ... 

1366 

1367 @overload 

1368 def returning( 

1369 self, 

1370 __ent0: _TCCA[_T0], 

1371 __ent1: _TCCA[_T1], 

1372 /, 

1373 *, 

1374 sort_by_parameter_order: bool = False, 

1375 ) -> ReturningInsert[_T0, _T1]: ... 

1376 

1377 @overload 

1378 def returning( 

1379 self, 

1380 __ent0: _TCCA[_T0], 

1381 __ent1: _TCCA[_T1], 

1382 __ent2: _TCCA[_T2], 

1383 /, 

1384 *, 

1385 sort_by_parameter_order: bool = False, 

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

1387 

1388 @overload 

1389 def returning( 

1390 self, 

1391 __ent0: _TCCA[_T0], 

1392 __ent1: _TCCA[_T1], 

1393 __ent2: _TCCA[_T2], 

1394 __ent3: _TCCA[_T3], 

1395 /, 

1396 *, 

1397 sort_by_parameter_order: bool = False, 

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

1399 

1400 @overload 

1401 def returning( 

1402 self, 

1403 __ent0: _TCCA[_T0], 

1404 __ent1: _TCCA[_T1], 

1405 __ent2: _TCCA[_T2], 

1406 __ent3: _TCCA[_T3], 

1407 __ent4: _TCCA[_T4], 

1408 /, 

1409 *, 

1410 sort_by_parameter_order: bool = False, 

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

1412 

1413 @overload 

1414 def returning( 

1415 self, 

1416 __ent0: _TCCA[_T0], 

1417 __ent1: _TCCA[_T1], 

1418 __ent2: _TCCA[_T2], 

1419 __ent3: _TCCA[_T3], 

1420 __ent4: _TCCA[_T4], 

1421 __ent5: _TCCA[_T5], 

1422 /, 

1423 *, 

1424 sort_by_parameter_order: bool = False, 

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

1426 

1427 @overload 

1428 def returning( 

1429 self, 

1430 __ent0: _TCCA[_T0], 

1431 __ent1: _TCCA[_T1], 

1432 __ent2: _TCCA[_T2], 

1433 __ent3: _TCCA[_T3], 

1434 __ent4: _TCCA[_T4], 

1435 __ent5: _TCCA[_T5], 

1436 __ent6: _TCCA[_T6], 

1437 /, 

1438 *, 

1439 sort_by_parameter_order: bool = False, 

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

1441 

1442 @overload 

1443 def returning( 

1444 self, 

1445 __ent0: _TCCA[_T0], 

1446 __ent1: _TCCA[_T1], 

1447 __ent2: _TCCA[_T2], 

1448 __ent3: _TCCA[_T3], 

1449 __ent4: _TCCA[_T4], 

1450 __ent5: _TCCA[_T5], 

1451 __ent6: _TCCA[_T6], 

1452 __ent7: _TCCA[_T7], 

1453 /, 

1454 *entities: _ColumnsClauseArgument[Any], 

1455 sort_by_parameter_order: bool = False, 

1456 ) -> ReturningInsert[ 

1457 _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, Unpack[TupleAny] 

1458 ]: ... 

1459 

1460 # END OVERLOADED FUNCTIONS self.returning 

1461 

1462 @overload 

1463 def returning( 

1464 self, 

1465 *cols: _ColumnsClauseArgument[Any], 

1466 sort_by_parameter_order: bool = False, 

1467 **__kw: Any, 

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

1469 

1470 def returning( 

1471 self, 

1472 *cols: _ColumnsClauseArgument[Any], 

1473 sort_by_parameter_order: bool = False, 

1474 **__kw: Any, 

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

1476 

1477 

1478class ReturningInsert(Insert, TypedReturnsRows[Unpack[_Ts]]): 

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

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

1481 

1482 This datatype is delivered when calling the 

1483 :meth:`.Insert.returning` method. 

1484 

1485 .. versionadded:: 2.0 

1486 

1487 """ 

1488 

1489 

1490# note: if not for MRO issues, this class should extend 

1491# from HasSyntaxExtensions[Literal["post_criteria"]] 

1492class DMLWhereBase: 

1493 table: _DMLTableElement 

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

1495 

1496 _post_criteria_clause: Optional[ClauseElement] = None 

1497 """used by extensions to Update/Delete etc. to add additional syntacitcal 

1498 constructs, e.g. LIMIT etc. 

1499 

1500 .. versionadded:: 2.1 

1501 

1502 """ 

1503 

1504 # can't put position_map here either without HasSyntaxExtensions 

1505 # _position_map = util.immutabledict( 

1506 # {"post_criteria": "_post_criteria_clause"} 

1507 # ) 

1508 

1509 @_generative 

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

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

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

1513 

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

1515 support multiple-table forms, including database-specific 

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

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

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

1519 See the linked tutorial sections below for examples. 

1520 

1521 .. seealso:: 

1522 

1523 :ref:`tutorial_correlated_updates` 

1524 

1525 :ref:`tutorial_update_from` 

1526 

1527 :ref:`tutorial_multi_table_deletes` 

1528 

1529 """ 

1530 

1531 for criterion in whereclause: 

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

1533 roles.WhereHavingRole, criterion, apply_propagate_attrs=self 

1534 ) 

1535 self._where_criteria += (where_criteria,) 

1536 return self 

1537 

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

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

1540 

1541 .. versionadded:: 1.4 

1542 

1543 """ 

1544 

1545 return self.where(*criteria) 

1546 

1547 def _filter_by_zero(self) -> _DMLTableElement: 

1548 return self.table 

1549 

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

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

1552 to this select. 

1553 

1554 """ 

1555 from_entity = self._filter_by_zero() 

1556 

1557 clauses = [ 

1558 _entity_namespace_key(from_entity, key) == value 

1559 for key, value in kwargs.items() 

1560 ] 

1561 return self.filter(*clauses) 

1562 

1563 @property 

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

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

1566 statement. 

1567 

1568 This assembles the current collection of WHERE criteria 

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

1570 

1571 

1572 .. versionadded:: 1.4 

1573 

1574 """ 

1575 

1576 return BooleanClauseList._construct_for_whereclause( 

1577 self._where_criteria 

1578 ) 

1579 

1580 

1581class Update( 

1582 DMLWhereBase, ValuesBase, HasSyntaxExtensions[Literal["post_criteria"]] 

1583): 

1584 """Represent an Update construct. 

1585 

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

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

1588 

1589 Available extension points: 

1590 

1591 * ``post_criteria``: applies additional logic after the ``WHERE`` clause. 

1592 

1593 """ 

1594 

1595 __visit_name__ = "update" 

1596 

1597 is_update = True 

1598 

1599 _traverse_internals = ( 

1600 [ 

1601 ("table", InternalTraversal.dp_clauseelement), 

1602 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1603 ("_inline", InternalTraversal.dp_boolean), 

1604 ("_maintain_values_ordering", InternalTraversal.dp_boolean), 

1605 ("_values", InternalTraversal.dp_dml_values), 

1606 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1607 ("_hints", InternalTraversal.dp_table_hint_list), 

1608 ("_return_defaults", InternalTraversal.dp_boolean), 

1609 ("_post_criteria_clause", InternalTraversal.dp_clauseelement), 

1610 ( 

1611 "_return_defaults_columns", 

1612 InternalTraversal.dp_clauseelement_tuple, 

1613 ), 

1614 ] 

1615 + HasPrefixes._has_prefixes_traverse_internals 

1616 + DialectKWArgs._dialect_kwargs_traverse_internals 

1617 + Executable._executable_traverse_internals 

1618 + HasCTE._has_ctes_traverse_internals 

1619 ) 

1620 

1621 _position_map = util.immutabledict( 

1622 {"post_criteria": "_post_criteria_clause"} 

1623 ) 

1624 

1625 def __init__(self, table: _DMLTableArgument): 

1626 super().__init__(table) 

1627 

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

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

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

1631 resulting UPDATE statement. 

1632 

1633 E.g.:: 

1634 

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

1636 

1637 .. seealso:: 

1638 

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

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

1641 

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

1643 method 

1644 supersedes the 

1645 :paramref:`_expression.update.preserve_parameter_order` 

1646 parameter, which will be removed in SQLAlchemy 2.0. 

1647 

1648 """ # noqa: E501 

1649 if self._values: 

1650 raise exc.ArgumentError( 

1651 "This statement already has " 

1652 f"{'ordered ' if self._maintain_values_ordering else ''}" 

1653 "values present" 

1654 ) 

1655 

1656 self = self.values(dict(args)) 

1657 self._maintain_values_ordering = True 

1658 return self 

1659 

1660 @_generative 

1661 def inline(self) -> Self: 

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

1663 

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

1665 objects via the 

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

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

1668 in the dictionary returned from 

1669 :meth:`_engine.CursorResult.last_updated_params`. 

1670 

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

1672 parameter 

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

1674 

1675 """ 

1676 self._inline = True 

1677 return self 

1678 

1679 def _apply_syntax_extension_to_self( 

1680 self, extension: SyntaxExtension 

1681 ) -> None: 

1682 extension.apply_to_update(self) 

1683 

1684 if TYPE_CHECKING: 

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

1686 

1687 # code within this block is **programmatically, 

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

1689 

1690 @overload 

1691 def returning(self, __ent0: _TCCA[_T0], /) -> ReturningUpdate[_T0]: ... 

1692 

1693 @overload 

1694 def returning( 

1695 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], / 

1696 ) -> ReturningUpdate[_T0, _T1]: ... 

1697 

1698 @overload 

1699 def returning( 

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

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

1702 

1703 @overload 

1704 def returning( 

1705 self, 

1706 __ent0: _TCCA[_T0], 

1707 __ent1: _TCCA[_T1], 

1708 __ent2: _TCCA[_T2], 

1709 __ent3: _TCCA[_T3], 

1710 /, 

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

1712 

1713 @overload 

1714 def returning( 

1715 self, 

1716 __ent0: _TCCA[_T0], 

1717 __ent1: _TCCA[_T1], 

1718 __ent2: _TCCA[_T2], 

1719 __ent3: _TCCA[_T3], 

1720 __ent4: _TCCA[_T4], 

1721 /, 

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

1723 

1724 @overload 

1725 def returning( 

1726 self, 

1727 __ent0: _TCCA[_T0], 

1728 __ent1: _TCCA[_T1], 

1729 __ent2: _TCCA[_T2], 

1730 __ent3: _TCCA[_T3], 

1731 __ent4: _TCCA[_T4], 

1732 __ent5: _TCCA[_T5], 

1733 /, 

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

1735 

1736 @overload 

1737 def returning( 

1738 self, 

1739 __ent0: _TCCA[_T0], 

1740 __ent1: _TCCA[_T1], 

1741 __ent2: _TCCA[_T2], 

1742 __ent3: _TCCA[_T3], 

1743 __ent4: _TCCA[_T4], 

1744 __ent5: _TCCA[_T5], 

1745 __ent6: _TCCA[_T6], 

1746 /, 

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

1748 

1749 @overload 

1750 def returning( 

1751 self, 

1752 __ent0: _TCCA[_T0], 

1753 __ent1: _TCCA[_T1], 

1754 __ent2: _TCCA[_T2], 

1755 __ent3: _TCCA[_T3], 

1756 __ent4: _TCCA[_T4], 

1757 __ent5: _TCCA[_T5], 

1758 __ent6: _TCCA[_T6], 

1759 __ent7: _TCCA[_T7], 

1760 /, 

1761 *entities: _ColumnsClauseArgument[Any], 

1762 ) -> ReturningUpdate[ 

1763 _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, Unpack[TupleAny] 

1764 ]: ... 

1765 

1766 # END OVERLOADED FUNCTIONS self.returning 

1767 

1768 @overload 

1769 def returning( 

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

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

1772 

1773 def returning( 

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

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

1776 

1777 

1778class ReturningUpdate(Update, TypedReturnsRows[Unpack[_Ts]]): 

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

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

1781 

1782 This datatype is delivered when calling the 

1783 :meth:`.Update.returning` method. 

1784 

1785 .. versionadded:: 2.0 

1786 

1787 """ 

1788 

1789 

1790class Delete( 

1791 DMLWhereBase, UpdateBase, HasSyntaxExtensions[Literal["post_criteria"]] 

1792): 

1793 """Represent a DELETE construct. 

1794 

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

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

1797 

1798 Available extension points: 

1799 

1800 * ``post_criteria``: applies additional logic after the ``WHERE`` clause. 

1801 

1802 """ 

1803 

1804 __visit_name__ = "delete" 

1805 

1806 is_delete = True 

1807 

1808 _traverse_internals = ( 

1809 [ 

1810 ("table", InternalTraversal.dp_clauseelement), 

1811 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1812 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1813 ("_hints", InternalTraversal.dp_table_hint_list), 

1814 ("_post_criteria_clause", InternalTraversal.dp_clauseelement), 

1815 ] 

1816 + HasPrefixes._has_prefixes_traverse_internals 

1817 + DialectKWArgs._dialect_kwargs_traverse_internals 

1818 + Executable._executable_traverse_internals 

1819 + HasCTE._has_ctes_traverse_internals 

1820 ) 

1821 

1822 _position_map = util.immutabledict( 

1823 {"post_criteria": "_post_criteria_clause"} 

1824 ) 

1825 

1826 def __init__(self, table: _DMLTableArgument): 

1827 self.table = coercions.expect( 

1828 roles.DMLTableRole, table, apply_propagate_attrs=self 

1829 ) 

1830 

1831 def _apply_syntax_extension_to_self( 

1832 self, extension: SyntaxExtension 

1833 ) -> None: 

1834 extension.apply_to_delete(self) 

1835 

1836 if TYPE_CHECKING: 

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

1838 

1839 # code within this block is **programmatically, 

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

1841 

1842 @overload 

1843 def returning(self, __ent0: _TCCA[_T0], /) -> ReturningDelete[_T0]: ... 

1844 

1845 @overload 

1846 def returning( 

1847 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], / 

1848 ) -> ReturningDelete[_T0, _T1]: ... 

1849 

1850 @overload 

1851 def returning( 

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

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

1854 

1855 @overload 

1856 def returning( 

1857 self, 

1858 __ent0: _TCCA[_T0], 

1859 __ent1: _TCCA[_T1], 

1860 __ent2: _TCCA[_T2], 

1861 __ent3: _TCCA[_T3], 

1862 /, 

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

1864 

1865 @overload 

1866 def returning( 

1867 self, 

1868 __ent0: _TCCA[_T0], 

1869 __ent1: _TCCA[_T1], 

1870 __ent2: _TCCA[_T2], 

1871 __ent3: _TCCA[_T3], 

1872 __ent4: _TCCA[_T4], 

1873 /, 

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

1875 

1876 @overload 

1877 def returning( 

1878 self, 

1879 __ent0: _TCCA[_T0], 

1880 __ent1: _TCCA[_T1], 

1881 __ent2: _TCCA[_T2], 

1882 __ent3: _TCCA[_T3], 

1883 __ent4: _TCCA[_T4], 

1884 __ent5: _TCCA[_T5], 

1885 /, 

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

1887 

1888 @overload 

1889 def returning( 

1890 self, 

1891 __ent0: _TCCA[_T0], 

1892 __ent1: _TCCA[_T1], 

1893 __ent2: _TCCA[_T2], 

1894 __ent3: _TCCA[_T3], 

1895 __ent4: _TCCA[_T4], 

1896 __ent5: _TCCA[_T5], 

1897 __ent6: _TCCA[_T6], 

1898 /, 

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

1900 

1901 @overload 

1902 def returning( 

1903 self, 

1904 __ent0: _TCCA[_T0], 

1905 __ent1: _TCCA[_T1], 

1906 __ent2: _TCCA[_T2], 

1907 __ent3: _TCCA[_T3], 

1908 __ent4: _TCCA[_T4], 

1909 __ent5: _TCCA[_T5], 

1910 __ent6: _TCCA[_T6], 

1911 __ent7: _TCCA[_T7], 

1912 /, 

1913 *entities: _ColumnsClauseArgument[Any], 

1914 ) -> ReturningDelete[ 

1915 _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, Unpack[TupleAny] 

1916 ]: ... 

1917 

1918 # END OVERLOADED FUNCTIONS self.returning 

1919 

1920 @overload 

1921 def returning( 

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

1923 ) -> ReturningDelete[Unpack[TupleAny]]: ... 

1924 

1925 def returning( 

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

1927 ) -> ReturningDelete[Unpack[TupleAny]]: ... 

1928 

1929 

1930class ReturningDelete(Update, TypedReturnsRows[Unpack[_Ts]]): 

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

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

1933 

1934 This datatype is delivered when calling the 

1935 :meth:`.Delete.returning` method. 

1936 

1937 .. versionadded:: 2.0 

1938 

1939 """