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

478 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 MutableMapping 

22from typing import NoReturn 

23from typing import Optional 

24from typing import overload 

25from typing import Sequence 

26from typing import Set 

27from typing import Tuple 

28from typing import Type 

29from typing import TYPE_CHECKING 

30from typing import TypeVar 

31from typing import Union 

32 

33from . import coercions 

34from . import roles 

35from . import util as sql_util 

36from ._typing import _TP 

37from ._typing import _unexpected_kw 

38from ._typing import is_column_element 

39from ._typing import is_named_from_clause 

40from .base import _entity_namespace_key 

41from .base import _exclusive_against 

42from .base import _from_objects 

43from .base import _generative 

44from .base import _select_iterables 

45from .base import ColumnCollection 

46from .base import ColumnSet 

47from .base import CompileState 

48from .base import DialectKWArgs 

49from .base import Executable 

50from .base import Generative 

51from .base import HasCompileState 

52from .elements import BooleanClauseList 

53from .elements import ClauseElement 

54from .elements import ColumnClause 

55from .elements import ColumnElement 

56from .elements import Null 

57from .selectable import Alias 

58from .selectable import ExecutableReturnsRows 

59from .selectable import FromClause 

60from .selectable import HasCTE 

61from .selectable import HasPrefixes 

62from .selectable import Join 

63from .selectable import SelectLabelStyle 

64from .selectable import TableClause 

65from .selectable import TypedReturnsRows 

66from .sqltypes import NullType 

67from .visitors import InternalTraversal 

68from .. import exc 

69from .. import util 

70from ..util.typing import Self 

71from ..util.typing import TypeGuard 

72 

73if TYPE_CHECKING: 

74 from ._typing import _ColumnExpressionArgument 

75 from ._typing import _ColumnsClauseArgument 

76 from ._typing import _DMLColumnArgument 

77 from ._typing import _DMLColumnKeyMapping 

78 from ._typing import _DMLTableArgument 

79 from ._typing import _T0 # noqa 

80 from ._typing import _T1 # noqa 

81 from ._typing import _T2 # noqa 

82 from ._typing import _T3 # noqa 

83 from ._typing import _T4 # noqa 

84 from ._typing import _T5 # noqa 

85 from ._typing import _T6 # noqa 

86 from ._typing import _T7 # noqa 

87 from ._typing import _TypedColumnClauseArgument as _TCCA # noqa 

88 from .base import ReadOnlyColumnCollection 

89 from .compiler import SQLCompiler 

90 from .elements import KeyedColumnElement 

91 from .selectable import _ColumnsClauseElement 

92 from .selectable import _SelectIterable 

93 from .selectable import Select 

94 from .selectable import Selectable 

95 

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

97 

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

99 

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

101 

102else: 

103 isupdate = operator.attrgetter("isupdate") 

104 isdelete = operator.attrgetter("isdelete") 

105 isinsert = operator.attrgetter("isinsert") 

106 

107 

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

109 

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

111_DMLTableElement = Union[TableClause, Alias, Join] 

112 

113 

114class DMLState(CompileState): 

115 _no_parameters = True 

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

117 _multi_parameters: Optional[ 

118 List[MutableMapping[_DMLColumnElement, Any]] 

119 ] = None 

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

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

122 _primary_table: FromClause 

123 _supports_implicit_returning = True 

124 

125 isupdate = False 

126 isdelete = False 

127 isinsert = False 

128 

129 statement: UpdateBase 

130 

131 def __init__( 

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

133 ): 

134 raise NotImplementedError() 

135 

136 @classmethod 

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

138 return { 

139 "name": ( 

140 statement.table.name 

141 if is_named_from_clause(statement.table) 

142 else None 

143 ), 

144 "table": statement.table, 

145 } 

146 

147 @classmethod 

148 def get_returning_column_descriptions( 

149 cls, statement: UpdateBase 

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

151 return [ 

152 { 

153 "name": c.key, 

154 "type": c.type, 

155 "expr": c, 

156 } 

157 for c in statement._all_selected_columns 

158 ] 

159 

160 @property 

161 def dml_table(self) -> _DMLTableElement: 

162 return self.statement.table 

163 

164 if TYPE_CHECKING: 

165 

166 @classmethod 

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

168 

169 @classmethod 

170 def _get_multi_crud_kv_pairs( 

171 cls, 

172 statement: UpdateBase, 

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

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

175 return [ 

176 { 

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

178 for k, v in mapping.items() 

179 } 

180 for mapping in multi_kv_iterator 

181 ] 

182 

183 @classmethod 

184 def _get_crud_kv_pairs( 

185 cls, 

186 statement: UpdateBase, 

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

188 needs_to_be_cacheable: bool, 

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

190 return [ 

191 ( 

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

193 ( 

194 v 

195 if not needs_to_be_cacheable 

196 else coercions.expect( 

197 roles.ExpressionElementRole, 

198 v, 

199 type_=NullType(), 

200 is_crud=True, 

201 ) 

202 ), 

203 ) 

204 for k, v in kv_iterator 

205 ] 

206 

207 def _make_extra_froms( 

208 self, statement: DMLWhereBase 

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

210 froms: List[FromClause] = [] 

211 

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

213 primary_table = all_tables[0] 

214 seen = {primary_table} 

215 

216 consider = statement._where_criteria 

217 if self._dict_parameters: 

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

219 

220 for crit in consider: 

221 for item in _from_objects(crit): 

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

223 froms.append(item) 

224 seen.update(item._cloned_set) 

225 

226 froms.extend(all_tables[1:]) 

227 return primary_table, froms 

228 

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

230 if self._no_parameters: 

231 self._dict_parameters = statement._values 

232 self._no_parameters = False 

233 

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

235 assert statement._select_names is not None 

236 parameters: MutableMapping[_DMLColumnElement, Any] = { 

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

238 } 

239 

240 if self._no_parameters: 

241 self._no_parameters = False 

242 self._dict_parameters = parameters 

243 else: 

244 # this condition normally not reachable as the Insert 

245 # does not allow this construction to occur 

246 assert False, "This statement already has parameters" 

247 

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

249 raise exc.InvalidRequestError( 

250 "%s construct does not support " 

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

252 ) 

253 

254 def _cant_mix_formats_error(self) -> NoReturn: 

255 raise exc.InvalidRequestError( 

256 "Can't mix single and multiple VALUES " 

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

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

259 "ambiguous." 

260 ) 

261 

262 

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

264class InsertDMLState(DMLState): 

265 isinsert = True 

266 

267 include_table_with_column_exprs = False 

268 

269 _has_multi_parameters = False 

270 

271 def __init__( 

272 self, 

273 statement: Insert, 

274 compiler: SQLCompiler, 

275 disable_implicit_returning: bool = False, 

276 **kw: Any, 

277 ): 

278 self.statement = statement 

279 self._primary_table = statement.table 

280 

281 if disable_implicit_returning: 

282 self._supports_implicit_returning = False 

283 

284 self.isinsert = True 

285 if statement._select_names: 

286 self._process_select_values(statement) 

287 if statement._values is not None: 

288 self._process_values(statement) 

289 if statement._multi_values: 

290 self._process_multi_values(statement) 

291 

292 @util.memoized_property 

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

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

295 return [ 

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

297 for col in self._dict_parameters or () 

298 ] 

299 

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

301 if self._no_parameters: 

302 self._has_multi_parameters = False 

303 self._dict_parameters = statement._values 

304 self._no_parameters = False 

305 elif self._has_multi_parameters: 

306 self._cant_mix_formats_error() 

307 

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

309 for parameters in statement._multi_values: 

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

311 ( 

312 { 

313 c.key: value 

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

315 } 

316 if isinstance(parameter_set, collections_abc.Sequence) 

317 else parameter_set 

318 ) 

319 for parameter_set in parameters 

320 ] 

321 

322 if self._no_parameters: 

323 self._no_parameters = False 

324 self._has_multi_parameters = True 

325 self._multi_parameters = multi_parameters 

326 self._dict_parameters = self._multi_parameters[0] 

327 elif not self._has_multi_parameters: 

328 self._cant_mix_formats_error() 

329 else: 

330 assert self._multi_parameters 

331 self._multi_parameters.extend(multi_parameters) 

332 

333 

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

335class UpdateDMLState(DMLState): 

336 isupdate = True 

337 

338 include_table_with_column_exprs = False 

339 

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

341 self.statement = statement 

342 

343 self.isupdate = True 

344 if statement._ordered_values is not None: 

345 self._process_ordered_values(statement) 

346 elif statement._values is not None: 

347 self._process_values(statement) 

348 elif statement._multi_values: 

349 self._no_multi_values_supported(statement) 

350 t, ef = self._make_extra_froms(statement) 

351 self._primary_table = t 

352 self._extra_froms = ef 

353 

354 self.is_multitable = mt = ef 

355 self.include_table_with_column_exprs = bool( 

356 mt and compiler.render_table_with_column_in_update_from 

357 ) 

358 

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

360 parameters = statement._ordered_values 

361 

362 if self._no_parameters: 

363 self._no_parameters = False 

364 assert parameters is not None 

365 self._dict_parameters = dict(parameters) 

366 self._ordered_values = parameters 

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

368 else: 

369 raise exc.InvalidRequestError( 

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

371 "with any other values() call" 

372 ) 

373 

374 

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

376class DeleteDMLState(DMLState): 

377 isdelete = True 

378 

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

380 self.statement = statement 

381 

382 self.isdelete = True 

383 t, ef = self._make_extra_froms(statement) 

384 self._primary_table = t 

385 self._extra_froms = ef 

386 self.is_multitable = ef 

387 

388 

389class UpdateBase( 

390 roles.DMLRole, 

391 HasCTE, 

392 HasCompileState, 

393 DialectKWArgs, 

394 HasPrefixes, 

395 Generative, 

396 ExecutableReturnsRows, 

397 ClauseElement, 

398): 

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

400 

401 __visit_name__ = "update_base" 

402 

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

404 util.EMPTY_DICT 

405 ) 

406 named_with_column = False 

407 

408 _label_style: SelectLabelStyle = ( 

409 SelectLabelStyle.LABEL_STYLE_DISAMBIGUATE_ONLY 

410 ) 

411 table: _DMLTableElement 

412 

413 _return_defaults = False 

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

415 None 

416 ) 

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

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

419 

420 is_dml = True 

421 

422 def _generate_fromclause_column_proxies( 

423 self, 

424 fromclause: FromClause, 

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

426 primary_key: ColumnSet, 

427 foreign_keys: Set[KeyedColumnElement[Any]], 

428 ) -> None: 

429 columns._populate_separate_keys( 

430 col._make_proxy( 

431 fromclause, primary_key=primary_key, foreign_keys=foreign_keys 

432 ) 

433 for col in self._all_selected_columns 

434 if is_column_element(col) 

435 ) 

436 

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

438 """Set the parameters for the statement. 

439 

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

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

442 SET/VALUES clause of UPDATE and INSERT. 

443 

444 """ 

445 raise NotImplementedError( 

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

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

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

449 ) 

450 

451 @_generative 

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

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

454 

455 e.g.:: 

456 

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

458 

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

460 associated with the constructor. 

461 

462 

463 """ 

464 self._validate_dialect_kwargs(opt) 

465 return self 

466 

467 @_generative 

468 def return_defaults( 

469 self, 

470 *cols: _DMLColumnArgument, 

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

472 sort_by_parameter_order: bool = False, 

473 ) -> Self: 

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

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

476 backends only. 

477 

478 .. deepalchemy:: 

479 

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

481 for its internal work in fetching newly generated primary key 

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

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

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

485 ORM inserts. Its behavior is fairly idiosyncratic 

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

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

488 add RETURNING clauses to their INSERT, UPDATE and DELETE 

489 statements. 

490 

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

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

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

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

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

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

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

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

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

500 value. 

501 

502 However, when the statement is modified by calling 

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

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

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

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

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

508 from the statement's execution, not only will 

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

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

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

512 of server generated 

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

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

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

516 

517 When invoking INSERT statements with multiple rows using 

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

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

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

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

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

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

524 values for each row inserted. The 

525 :attr:`.CursorResult.inserted_primary_key` and 

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

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

528 

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

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

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

532 INSERT, UPDATE or DELETE statement proceeds normally. 

533 

534 E.g.:: 

535 

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

537 

538 result = connection.execute(stmt) 

539 

540 server_created_at = result.returned_defaults["created_at"] 

541 

542 When used against an UPDATE statement 

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

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

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

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

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

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

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

550 normally change values when a DELETE statement proceeds. 

551 

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

553 for DELETE statements also and has been moved from 

554 :class:`.ValuesBase` to :class:`.UpdateBase`. 

555 

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

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

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

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

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

561 at a time. 

562 

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

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

565 

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

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

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

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

570 

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

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

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

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

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

576 attribute being left unpopulated. 

577 

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

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

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

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

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

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

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

585 ``False``. 

586 

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

588 backend database driver supports the 

589 :ref:`insertmanyvalues <engine_insertmanyvalues>` 

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

591 When executemany is used, the 

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

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

594 will return the inserted defaults and primary keys. 

595 

596 .. versionadded:: 1.4 Added 

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

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

599 In version 2.0, the underlying implementation which fetches and 

600 populates the data for these attributes was generalized to be 

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

602 supported by the ``psycopg2`` driver. 

603 

604 

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

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

607 will be fetched. 

608 :param supplemental_cols: optional list of RETURNING expressions, 

609 in the same form as one would pass to the 

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

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

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

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

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

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

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

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

618 reliably be targeted positionally. 

619 

620 .. versionadded:: 2.0 

621 

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

623 executed against multiple parameter sets, organize the results of 

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

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

626 execution for supporting dialects and typically makes use of the 

627 :term:`insertmanyvalues` feature. 

628 

629 .. versionadded:: 2.0.10 

630 

631 .. seealso:: 

632 

633 :ref:`engine_insertmanyvalues_returning_order` - background on 

634 sorting of RETURNING rows for bulk INSERT 

635 

636 .. seealso:: 

637 

638 :meth:`.UpdateBase.returning` 

639 

640 :attr:`_engine.CursorResult.returned_defaults` 

641 

642 :attr:`_engine.CursorResult.returned_defaults_rows` 

643 

644 :attr:`_engine.CursorResult.inserted_primary_key` 

645 

646 :attr:`_engine.CursorResult.inserted_primary_key_rows` 

647 

648 """ 

649 

650 if self._return_defaults: 

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

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

653 # are columns in the collection 

654 if self._return_defaults_columns and cols: 

655 self._return_defaults_columns = tuple( 

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

657 coercions.expect(roles.ColumnsClauseRole, c) 

658 for c in cols 

659 ) 

660 ) 

661 else: 

662 # set for all columns 

663 self._return_defaults_columns = () 

664 else: 

665 self._return_defaults_columns = tuple( 

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

667 ) 

668 self._return_defaults = True 

669 if sort_by_parameter_order: 

670 if not self.is_insert: 

671 raise exc.ArgumentError( 

672 "The 'sort_by_parameter_order' argument to " 

673 "return_defaults() only applies to INSERT statements" 

674 ) 

675 self._sort_by_parameter_order = True 

676 if supplemental_cols: 

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

678 # is for test suites but also for vertical splicing 

679 supplemental_col_tup = ( 

680 coercions.expect(roles.ColumnsClauseRole, c) 

681 for c in supplemental_cols 

682 ) 

683 

684 if self._supplemental_returning is None: 

685 self._supplemental_returning = tuple( 

686 util.unique_list(supplemental_col_tup) 

687 ) 

688 else: 

689 self._supplemental_returning = tuple( 

690 util.unique_list( 

691 self._supplemental_returning 

692 + tuple(supplemental_col_tup) 

693 ) 

694 ) 

695 

696 return self 

697 

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

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

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

701 

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

703 so we return False for derives. 

704 

705 """ 

706 return False 

707 

708 @_generative 

709 def returning( 

710 self, 

711 *cols: _ColumnsClauseArgument[Any], 

712 sort_by_parameter_order: bool = False, 

713 **__kw: Any, 

714 ) -> UpdateBase: 

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

716 

717 e.g.: 

718 

719 .. sourcecode:: pycon+sql 

720 

721 >>> stmt = ( 

722 ... table.update() 

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

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

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

726 ... ) 

727 >>> print(stmt) 

728 {printsql}UPDATE some_table SET status=:status 

729 WHERE some_table.data = :data_1 

730 RETURNING some_table.server_flag, some_table.updated_timestamp 

731 

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

733 list of expressions to be returned. 

734 

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

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

737 

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

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

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

741 expressions: 

742 

743 .. sourcecode:: pycon+sql 

744 

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

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

747 ... ) 

748 >>> print(stmt) 

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

750 VALUES (:first_name, :last_name) 

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

752 

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

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

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

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

757 

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

759 available via the result set and can be iterated using 

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

761 For DBAPIs which do not 

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

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

764 amount of behavioral neutrality is provided. 

765 

766 Note that not all databases/DBAPIs 

767 support RETURNING. For those backends with no support, 

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

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

770 varies greatly, including restrictions on executemany() 

771 and other statements which return multiple rows. Please 

772 read the documentation notes for the database in use in 

773 order to determine the availability of RETURNING. 

774 

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

776 entities to be returned. 

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

778 executed against multiple parameter sets, organize the results of 

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

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

781 execution for supporting dialects and typically makes use of the 

782 :term:`insertmanyvalues` feature. 

783 

784 .. versionadded:: 2.0.10 

785 

786 .. seealso:: 

787 

788 :ref:`engine_insertmanyvalues_returning_order` - background on 

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

790 

791 :ref:`orm_queryguide_bulk_insert_returning_ordered` - example of 

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

793 

794 .. seealso:: 

795 

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

797 towards efficient fetching of server-side defaults and triggers 

798 for single-row INSERTs or UPDATEs. 

799 

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

801 

802 """ # noqa: E501 

803 if __kw: 

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

805 if self._return_defaults: 

806 raise exc.InvalidRequestError( 

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

808 ) 

809 self._returning += tuple( 

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

811 ) 

812 if sort_by_parameter_order: 

813 if not self.is_insert: 

814 raise exc.ArgumentError( 

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

816 "only applies to INSERT statements" 

817 ) 

818 self._sort_by_parameter_order = True 

819 return self 

820 

821 def corresponding_column( 

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

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

824 return self.exported_columns.corresponding_column( 

825 column, require_embedded=require_embedded 

826 ) 

827 

828 @util.ro_memoized_property 

829 def _all_selected_columns(self) -> _SelectIterable: 

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

831 

832 @util.ro_memoized_property 

833 def exported_columns( 

834 self, 

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

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

837 statement. 

838 

839 .. versionadded:: 1.4 

840 

841 """ 

842 return ColumnCollection( 

843 (c.key, c) 

844 for c in self._all_selected_columns 

845 if is_column_element(c) 

846 ).as_readonly() 

847 

848 @_generative 

849 def with_hint( 

850 self, 

851 text: str, 

852 selectable: Optional[_DMLTableArgument] = None, 

853 dialect_name: str = "*", 

854 ) -> Self: 

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

856 INSERT/UPDATE/DELETE statement. 

857 

858 .. note:: 

859 

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

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

862 :meth:`.UpdateBase.prefix_with`. 

863 

864 The text of the hint is rendered in the appropriate 

865 location for the database backend in use, relative 

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

867 statement, or optionally to that of the given 

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

869 

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

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

872 that only takes effect for SQL Server:: 

873 

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

875 

876 :param text: Text of the hint. 

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

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

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

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

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

882 that dialect is in use. 

883 """ 

884 if selectable is None: 

885 selectable = self.table 

886 else: 

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

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

889 return self 

890 

891 @property 

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

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

894 entity which this DML construct is operating against. 

895 

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

897 extended structure which includes information about mapped 

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

899 contains more background. 

900 

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

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

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

904 

905 >>> stmt = insert(user_table) 

906 >>> stmt.entity_description 

907 { 

908 "name": "user_table", 

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

910 } 

911 

912 .. versionadded:: 1.4.33 

913 

914 .. seealso:: 

915 

916 :attr:`.UpdateBase.returning_column_descriptions` 

917 

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

919 a :func:`.select` construct 

920 

921 :ref:`queryguide_inspection` - ORM background 

922 

923 """ 

924 meth = DMLState.get_plugin_class(self).get_entity_description 

925 return meth(self) 

926 

927 @property 

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

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

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

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

932 

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

934 extended structure which includes information about mapped 

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

936 contains more background. 

937 

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

939 derived from the same objects that are returned by the 

940 :attr:`.UpdateBase.exported_columns` accessor:: 

941 

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

943 >>> stmt.entity_description 

944 [ 

945 { 

946 "name": "id", 

947 "type": Integer, 

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

949 }, 

950 { 

951 "name": "name", 

952 "type": String(), 

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

954 }, 

955 ] 

956 

957 .. versionadded:: 1.4.33 

958 

959 .. seealso:: 

960 

961 :attr:`.UpdateBase.entity_description` 

962 

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

964 a :func:`.select` construct 

965 

966 :ref:`queryguide_inspection` - ORM background 

967 

968 """ # noqa: E501 

969 meth = DMLState.get_plugin_class( 

970 self 

971 ).get_returning_column_descriptions 

972 return meth(self) 

973 

974 

975class ValuesBase(UpdateBase): 

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

977 INSERT and UPDATE constructs.""" 

978 

979 __visit_name__ = "values_base" 

980 

981 _supports_multi_parameters = False 

982 

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

984 """SELECT statement for INSERT .. FROM SELECT""" 

985 

986 _post_values_clause: Optional[ClauseElement] = None 

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

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

989 

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

991 _multi_values: Tuple[ 

992 Union[ 

993 Sequence[Dict[_DMLColumnElement, Any]], 

994 Sequence[Sequence[Any]], 

995 ], 

996 ..., 

997 ] = () 

998 

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

1000 

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

1002 _inline: bool = False 

1003 

1004 def __init__(self, table: _DMLTableArgument): 

1005 self.table = coercions.expect( 

1006 roles.DMLTableRole, table, apply_propagate_attrs=self 

1007 ) 

1008 

1009 @_generative 

1010 @_exclusive_against( 

1011 "_select_names", 

1012 "_ordered_values", 

1013 msgs={ 

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

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

1016 "values present", 

1017 }, 

1018 ) 

1019 def values( 

1020 self, 

1021 *args: Union[ 

1022 _DMLColumnKeyMapping[Any], 

1023 Sequence[Any], 

1024 ], 

1025 **kwargs: Any, 

1026 ) -> Self: 

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

1028 clause for an UPDATE. 

1029 

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

1031 :class:`_expression.Update` 

1032 constructs support 

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

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

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

1036 particular set of parameters into the statement. 

1037 

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

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

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

1041 dictionary of parameters, the newly passed keys will replace 

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

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

1044 onto the existing list of values. 

1045 

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

1047 of a :class:`_schema.Column` 

1048 mapped to the value to be rendered into the 

1049 VALUES or SET clause:: 

1050 

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

1052 

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

1054 

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

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

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

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

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

1060 :class:`_expression.Update` construct. 

1061 

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

1063 :class:`_expression.Update` 

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

1065 that of the kwargs form:: 

1066 

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

1068 

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

1070 

1071 Also for either form but more typically for the 

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

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

1074 

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

1076 

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

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

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

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

1081 MySQL, but not necessarily others:: 

1082 

1083 users.insert().values( 

1084 [ 

1085 {"name": "some name"}, 

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

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

1088 ] 

1089 ) 

1090 

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

1092 

1093 .. sourcecode:: sql 

1094 

1095 INSERT INTO users (name) VALUES 

1096 (:name_1), 

1097 (:name_2), 

1098 (:name_3) 

1099 

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

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

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

1103 INSERT statement against multiple rows, the normal method is 

1104 to pass a multiple values list to the 

1105 :meth:`_engine.Connection.execute` 

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

1107 more efficient for a very large number of parameters. 

1108 

1109 .. seealso:: 

1110 

1111 :ref:`tutorial_multiple_parameters` - an introduction to 

1112 the traditional Core method of multiple parameter set 

1113 invocation for INSERTs and other statements. 

1114 

1115 The UPDATE construct also supports rendering the SET parameters 

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

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

1118 

1119 .. seealso:: 

1120 

1121 :meth:`_expression.Update.ordered_values` 

1122 

1123 

1124 """ 

1125 if args: 

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

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

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

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

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

1131 arg = args[0] 

1132 

1133 if kwargs: 

1134 raise exc.ArgumentError( 

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

1136 "simultaneously" 

1137 ) 

1138 elif len(args) > 1: 

1139 raise exc.ArgumentError( 

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

1141 "dictionaries/tuples is accepted positionally." 

1142 ) 

1143 

1144 elif isinstance(arg, collections_abc.Sequence): 

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

1146 multi_kv_generator = DMLState.get_plugin_class( 

1147 self 

1148 )._get_multi_crud_kv_pairs 

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

1150 return self 

1151 

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

1153 self._multi_values += (arg,) 

1154 return self 

1155 

1156 if TYPE_CHECKING: 

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

1158 # case 

1159 assert isinstance(self, Insert) 

1160 

1161 # tuple values 

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

1163 

1164 else: 

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

1166 # so this is fairly quick. 

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

1168 if args: 

1169 raise exc.ArgumentError( 

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

1171 "dictionaries/tuples is accepted positionally." 

1172 ) 

1173 

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

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

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

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

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

1179 

1180 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs 

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

1182 if self._values: 

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

1184 else: 

1185 self._values = util.immutabledict(coerced_arg) 

1186 return self 

1187 

1188 

1189class Insert(ValuesBase): 

1190 """Represent an INSERT construct. 

1191 

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

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

1194 

1195 """ 

1196 

1197 __visit_name__ = "insert" 

1198 

1199 _supports_multi_parameters = True 

1200 

1201 select = None 

1202 include_insert_from_select_defaults = False 

1203 

1204 _sort_by_parameter_order: bool = False 

1205 

1206 is_insert = True 

1207 

1208 table: TableClause 

1209 

1210 _traverse_internals = ( 

1211 [ 

1212 ("table", InternalTraversal.dp_clauseelement), 

1213 ("_inline", InternalTraversal.dp_boolean), 

1214 ("_select_names", InternalTraversal.dp_string_list), 

1215 ("_values", InternalTraversal.dp_dml_values), 

1216 ("_multi_values", InternalTraversal.dp_dml_multi_values), 

1217 ("select", InternalTraversal.dp_clauseelement), 

1218 ("_post_values_clause", InternalTraversal.dp_clauseelement), 

1219 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1220 ("_hints", InternalTraversal.dp_table_hint_list), 

1221 ("_return_defaults", InternalTraversal.dp_boolean), 

1222 ( 

1223 "_return_defaults_columns", 

1224 InternalTraversal.dp_clauseelement_tuple, 

1225 ), 

1226 ("_sort_by_parameter_order", InternalTraversal.dp_boolean), 

1227 ] 

1228 + HasPrefixes._has_prefixes_traverse_internals 

1229 + DialectKWArgs._dialect_kwargs_traverse_internals 

1230 + Executable._executable_traverse_internals 

1231 + HasCTE._has_ctes_traverse_internals 

1232 ) 

1233 

1234 def __init__(self, table: _DMLTableArgument): 

1235 super().__init__(table) 

1236 

1237 @_generative 

1238 def inline(self) -> Self: 

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

1240 

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

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

1243 in particular, 

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

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

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

1247 returning" feature for the statement. 

1248 

1249 

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

1251 parameter 

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

1253 

1254 """ 

1255 self._inline = True 

1256 return self 

1257 

1258 @_generative 

1259 def from_select( 

1260 self, 

1261 names: Sequence[_DMLColumnArgument], 

1262 select: Selectable, 

1263 include_defaults: bool = True, 

1264 ) -> Self: 

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

1266 an ``INSERT...FROM SELECT`` statement. 

1267 

1268 e.g.:: 

1269 

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

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

1272 

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

1274 :class:`_schema.Column` 

1275 objects representing the target columns. 

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

1277 :class:`_expression.FromClause` 

1278 or other construct which resolves into a 

1279 :class:`_expression.FromClause`, 

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

1281 columns returned from this FROM clause should correspond to the 

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

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

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

1285 correspond. 

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

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

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

1289 otherwise specified in the list of names will be rendered 

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

1291 included in the data to be inserted. 

1292 

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

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

1295 per row**. 

1296 

1297 """ 

1298 

1299 if self._values: 

1300 raise exc.InvalidRequestError( 

1301 "This construct already inserts value expressions" 

1302 ) 

1303 

1304 self._select_names = [ 

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

1306 for name in names 

1307 ] 

1308 self._inline = True 

1309 self.include_insert_from_select_defaults = include_defaults 

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

1311 return self 

1312 

1313 if TYPE_CHECKING: 

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

1315 

1316 # code within this block is **programmatically, 

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

1318 

1319 @overload 

1320 def returning( 

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

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

1323 

1324 @overload 

1325 def returning( 

1326 self, 

1327 __ent0: _TCCA[_T0], 

1328 __ent1: _TCCA[_T1], 

1329 *, 

1330 sort_by_parameter_order: bool = False, 

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

1332 

1333 @overload 

1334 def returning( 

1335 self, 

1336 __ent0: _TCCA[_T0], 

1337 __ent1: _TCCA[_T1], 

1338 __ent2: _TCCA[_T2], 

1339 *, 

1340 sort_by_parameter_order: bool = False, 

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

1342 

1343 @overload 

1344 def returning( 

1345 self, 

1346 __ent0: _TCCA[_T0], 

1347 __ent1: _TCCA[_T1], 

1348 __ent2: _TCCA[_T2], 

1349 __ent3: _TCCA[_T3], 

1350 *, 

1351 sort_by_parameter_order: bool = False, 

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

1353 

1354 @overload 

1355 def returning( 

1356 self, 

1357 __ent0: _TCCA[_T0], 

1358 __ent1: _TCCA[_T1], 

1359 __ent2: _TCCA[_T2], 

1360 __ent3: _TCCA[_T3], 

1361 __ent4: _TCCA[_T4], 

1362 *, 

1363 sort_by_parameter_order: bool = False, 

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

1365 

1366 @overload 

1367 def returning( 

1368 self, 

1369 __ent0: _TCCA[_T0], 

1370 __ent1: _TCCA[_T1], 

1371 __ent2: _TCCA[_T2], 

1372 __ent3: _TCCA[_T3], 

1373 __ent4: _TCCA[_T4], 

1374 __ent5: _TCCA[_T5], 

1375 *, 

1376 sort_by_parameter_order: bool = False, 

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

1378 

1379 @overload 

1380 def returning( 

1381 self, 

1382 __ent0: _TCCA[_T0], 

1383 __ent1: _TCCA[_T1], 

1384 __ent2: _TCCA[_T2], 

1385 __ent3: _TCCA[_T3], 

1386 __ent4: _TCCA[_T4], 

1387 __ent5: _TCCA[_T5], 

1388 __ent6: _TCCA[_T6], 

1389 *, 

1390 sort_by_parameter_order: bool = False, 

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

1392 

1393 @overload 

1394 def returning( 

1395 self, 

1396 __ent0: _TCCA[_T0], 

1397 __ent1: _TCCA[_T1], 

1398 __ent2: _TCCA[_T2], 

1399 __ent3: _TCCA[_T3], 

1400 __ent4: _TCCA[_T4], 

1401 __ent5: _TCCA[_T5], 

1402 __ent6: _TCCA[_T6], 

1403 __ent7: _TCCA[_T7], 

1404 *, 

1405 sort_by_parameter_order: bool = False, 

1406 ) -> ReturningInsert[ 

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

1408 ]: ... 

1409 

1410 # END OVERLOADED FUNCTIONS self.returning 

1411 

1412 @overload 

1413 def returning( 

1414 self, 

1415 *cols: _ColumnsClauseArgument[Any], 

1416 sort_by_parameter_order: bool = False, 

1417 **__kw: Any, 

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

1419 

1420 def returning( 

1421 self, 

1422 *cols: _ColumnsClauseArgument[Any], 

1423 sort_by_parameter_order: bool = False, 

1424 **__kw: Any, 

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

1426 

1427 

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

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

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

1431 

1432 This datatype is delivered when calling the 

1433 :meth:`.Insert.returning` method. 

1434 

1435 .. versionadded:: 2.0 

1436 

1437 """ 

1438 

1439 

1440class DMLWhereBase: 

1441 table: _DMLTableElement 

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

1443 

1444 @_generative 

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

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

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

1448 

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

1450 support multiple-table forms, including database-specific 

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

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

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

1454 See the linked tutorial sections below for examples. 

1455 

1456 .. seealso:: 

1457 

1458 :ref:`tutorial_correlated_updates` 

1459 

1460 :ref:`tutorial_update_from` 

1461 

1462 :ref:`tutorial_multi_table_deletes` 

1463 

1464 """ 

1465 

1466 for criterion in whereclause: 

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

1468 roles.WhereHavingRole, criterion, apply_propagate_attrs=self 

1469 ) 

1470 self._where_criteria += (where_criteria,) 

1471 return self 

1472 

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

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

1475 

1476 .. versionadded:: 1.4 

1477 

1478 """ 

1479 

1480 return self.where(*criteria) 

1481 

1482 def _filter_by_zero(self) -> _DMLTableElement: 

1483 return self.table 

1484 

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

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

1487 to this select. 

1488 

1489 """ 

1490 from_entity = self._filter_by_zero() 

1491 

1492 clauses = [ 

1493 _entity_namespace_key(from_entity, key) == value 

1494 for key, value in kwargs.items() 

1495 ] 

1496 return self.filter(*clauses) 

1497 

1498 @property 

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

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

1501 statement. 

1502 

1503 This assembles the current collection of WHERE criteria 

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

1505 

1506 

1507 .. versionadded:: 1.4 

1508 

1509 """ 

1510 

1511 return BooleanClauseList._construct_for_whereclause( 

1512 self._where_criteria 

1513 ) 

1514 

1515 

1516class Update(DMLWhereBase, ValuesBase): 

1517 """Represent an Update construct. 

1518 

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

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

1521 

1522 """ 

1523 

1524 __visit_name__ = "update" 

1525 

1526 is_update = True 

1527 

1528 _traverse_internals = ( 

1529 [ 

1530 ("table", InternalTraversal.dp_clauseelement), 

1531 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1532 ("_inline", InternalTraversal.dp_boolean), 

1533 ("_ordered_values", InternalTraversal.dp_dml_ordered_values), 

1534 ("_values", InternalTraversal.dp_dml_values), 

1535 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1536 ("_hints", InternalTraversal.dp_table_hint_list), 

1537 ("_return_defaults", InternalTraversal.dp_boolean), 

1538 ( 

1539 "_return_defaults_columns", 

1540 InternalTraversal.dp_clauseelement_tuple, 

1541 ), 

1542 ] 

1543 + HasPrefixes._has_prefixes_traverse_internals 

1544 + DialectKWArgs._dialect_kwargs_traverse_internals 

1545 + Executable._executable_traverse_internals 

1546 + HasCTE._has_ctes_traverse_internals 

1547 ) 

1548 

1549 def __init__(self, table: _DMLTableArgument): 

1550 super().__init__(table) 

1551 

1552 @_generative 

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

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

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

1556 resulting UPDATE statement. 

1557 

1558 E.g.:: 

1559 

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

1561 

1562 .. seealso:: 

1563 

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

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

1566 

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

1568 method 

1569 supersedes the 

1570 :paramref:`_expression.update.preserve_parameter_order` 

1571 parameter, which will be removed in SQLAlchemy 2.0. 

1572 

1573 """ # noqa: E501 

1574 if self._values: 

1575 raise exc.ArgumentError( 

1576 "This statement already has values present" 

1577 ) 

1578 elif self._ordered_values: 

1579 raise exc.ArgumentError( 

1580 "This statement already has ordered values present" 

1581 ) 

1582 

1583 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs 

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

1585 return self 

1586 

1587 @_generative 

1588 def inline(self) -> Self: 

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

1590 

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

1592 objects via the 

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

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

1595 in the dictionary returned from 

1596 :meth:`_engine.CursorResult.last_updated_params`. 

1597 

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

1599 parameter 

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

1601 

1602 """ 

1603 self._inline = True 

1604 return self 

1605 

1606 if TYPE_CHECKING: 

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

1608 

1609 # code within this block is **programmatically, 

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

1611 

1612 @overload 

1613 def returning( 

1614 self, __ent0: _TCCA[_T0] 

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

1616 

1617 @overload 

1618 def returning( 

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

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

1621 

1622 @overload 

1623 def returning( 

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

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

1626 

1627 @overload 

1628 def returning( 

1629 self, 

1630 __ent0: _TCCA[_T0], 

1631 __ent1: _TCCA[_T1], 

1632 __ent2: _TCCA[_T2], 

1633 __ent3: _TCCA[_T3], 

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

1635 

1636 @overload 

1637 def returning( 

1638 self, 

1639 __ent0: _TCCA[_T0], 

1640 __ent1: _TCCA[_T1], 

1641 __ent2: _TCCA[_T2], 

1642 __ent3: _TCCA[_T3], 

1643 __ent4: _TCCA[_T4], 

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

1645 

1646 @overload 

1647 def returning( 

1648 self, 

1649 __ent0: _TCCA[_T0], 

1650 __ent1: _TCCA[_T1], 

1651 __ent2: _TCCA[_T2], 

1652 __ent3: _TCCA[_T3], 

1653 __ent4: _TCCA[_T4], 

1654 __ent5: _TCCA[_T5], 

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

1656 

1657 @overload 

1658 def returning( 

1659 self, 

1660 __ent0: _TCCA[_T0], 

1661 __ent1: _TCCA[_T1], 

1662 __ent2: _TCCA[_T2], 

1663 __ent3: _TCCA[_T3], 

1664 __ent4: _TCCA[_T4], 

1665 __ent5: _TCCA[_T5], 

1666 __ent6: _TCCA[_T6], 

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

1668 

1669 @overload 

1670 def returning( 

1671 self, 

1672 __ent0: _TCCA[_T0], 

1673 __ent1: _TCCA[_T1], 

1674 __ent2: _TCCA[_T2], 

1675 __ent3: _TCCA[_T3], 

1676 __ent4: _TCCA[_T4], 

1677 __ent5: _TCCA[_T5], 

1678 __ent6: _TCCA[_T6], 

1679 __ent7: _TCCA[_T7], 

1680 ) -> ReturningUpdate[ 

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

1682 ]: ... 

1683 

1684 # END OVERLOADED FUNCTIONS self.returning 

1685 

1686 @overload 

1687 def returning( 

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

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

1690 

1691 def returning( 

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

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

1694 

1695 

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

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

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

1699 

1700 This datatype is delivered when calling the 

1701 :meth:`.Update.returning` method. 

1702 

1703 .. versionadded:: 2.0 

1704 

1705 """ 

1706 

1707 

1708class Delete(DMLWhereBase, UpdateBase): 

1709 """Represent a DELETE construct. 

1710 

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

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

1713 

1714 """ 

1715 

1716 __visit_name__ = "delete" 

1717 

1718 is_delete = True 

1719 

1720 _traverse_internals = ( 

1721 [ 

1722 ("table", InternalTraversal.dp_clauseelement), 

1723 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1724 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1725 ("_hints", InternalTraversal.dp_table_hint_list), 

1726 ] 

1727 + HasPrefixes._has_prefixes_traverse_internals 

1728 + DialectKWArgs._dialect_kwargs_traverse_internals 

1729 + Executable._executable_traverse_internals 

1730 + HasCTE._has_ctes_traverse_internals 

1731 ) 

1732 

1733 def __init__(self, table: _DMLTableArgument): 

1734 self.table = coercions.expect( 

1735 roles.DMLTableRole, table, apply_propagate_attrs=self 

1736 ) 

1737 

1738 if TYPE_CHECKING: 

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

1740 

1741 # code within this block is **programmatically, 

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

1743 

1744 @overload 

1745 def returning( 

1746 self, __ent0: _TCCA[_T0] 

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

1748 

1749 @overload 

1750 def returning( 

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

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

1753 

1754 @overload 

1755 def returning( 

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

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

1758 

1759 @overload 

1760 def returning( 

1761 self, 

1762 __ent0: _TCCA[_T0], 

1763 __ent1: _TCCA[_T1], 

1764 __ent2: _TCCA[_T2], 

1765 __ent3: _TCCA[_T3], 

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

1767 

1768 @overload 

1769 def returning( 

1770 self, 

1771 __ent0: _TCCA[_T0], 

1772 __ent1: _TCCA[_T1], 

1773 __ent2: _TCCA[_T2], 

1774 __ent3: _TCCA[_T3], 

1775 __ent4: _TCCA[_T4], 

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

1777 

1778 @overload 

1779 def returning( 

1780 self, 

1781 __ent0: _TCCA[_T0], 

1782 __ent1: _TCCA[_T1], 

1783 __ent2: _TCCA[_T2], 

1784 __ent3: _TCCA[_T3], 

1785 __ent4: _TCCA[_T4], 

1786 __ent5: _TCCA[_T5], 

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

1788 

1789 @overload 

1790 def returning( 

1791 self, 

1792 __ent0: _TCCA[_T0], 

1793 __ent1: _TCCA[_T1], 

1794 __ent2: _TCCA[_T2], 

1795 __ent3: _TCCA[_T3], 

1796 __ent4: _TCCA[_T4], 

1797 __ent5: _TCCA[_T5], 

1798 __ent6: _TCCA[_T6], 

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

1800 

1801 @overload 

1802 def returning( 

1803 self, 

1804 __ent0: _TCCA[_T0], 

1805 __ent1: _TCCA[_T1], 

1806 __ent2: _TCCA[_T2], 

1807 __ent3: _TCCA[_T3], 

1808 __ent4: _TCCA[_T4], 

1809 __ent5: _TCCA[_T5], 

1810 __ent6: _TCCA[_T6], 

1811 __ent7: _TCCA[_T7], 

1812 ) -> ReturningDelete[ 

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

1814 ]: ... 

1815 

1816 # END OVERLOADED FUNCTIONS self.returning 

1817 

1818 @overload 

1819 def returning( 

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

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

1822 

1823 def returning( 

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

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

1826 

1827 

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

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

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

1831 

1832 This datatype is delivered when calling the 

1833 :meth:`.Delete.returning` method. 

1834 

1835 .. versionadded:: 2.0 

1836 

1837 """