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

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

474 statements  

1# sql/dml.py 

2# Copyright (C) 2009-2024 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 Tuple 

27from typing import Type 

28from typing import TYPE_CHECKING 

29from typing import TypeVar 

30from typing import Union 

31 

32from . import coercions 

33from . import roles 

34from . import util as sql_util 

35from ._typing import _unexpected_kw 

36from ._typing import is_column_element 

37from ._typing import is_named_from_clause 

38from .base import _entity_namespace_key 

39from .base import _exclusive_against 

40from .base import _from_objects 

41from .base import _generative 

42from .base import _select_iterables 

43from .base import ColumnCollection 

44from .base import CompileState 

45from .base import DialectKWArgs 

46from .base import Executable 

47from .base import Generative 

48from .base import HasCompileState 

49from .elements import BooleanClauseList 

50from .elements import ClauseElement 

51from .elements import ColumnClause 

52from .elements import ColumnElement 

53from .elements import Null 

54from .selectable import Alias 

55from .selectable import ExecutableReturnsRows 

56from .selectable import FromClause 

57from .selectable import HasCTE 

58from .selectable import HasPrefixes 

59from .selectable import Join 

60from .selectable import SelectLabelStyle 

61from .selectable import TableClause 

62from .selectable import TypedReturnsRows 

63from .sqltypes import NullType 

64from .visitors import InternalTraversal 

65from .. import exc 

66from .. import util 

67from ..util.typing import Self 

68from ..util.typing import TupleAny 

69from ..util.typing import TypeGuard 

70from ..util.typing import TypeVarTuple 

71from ..util.typing import Unpack 

72 

73 

74if TYPE_CHECKING: 

75 from ._typing import _ColumnExpressionArgument 

76 from ._typing import _ColumnsClauseArgument 

77 from ._typing import _DMLColumnArgument 

78 from ._typing import _DMLColumnKeyMapping 

79 from ._typing import _DMLTableArgument 

80 from ._typing import _T0 # noqa 

81 from ._typing import _T1 # noqa 

82 from ._typing import _T2 # noqa 

83 from ._typing import _T3 # noqa 

84 from ._typing import _T4 # noqa 

85 from ._typing import _T5 # noqa 

86 from ._typing import _T6 # noqa 

87 from ._typing import _T7 # noqa 

88 from ._typing import _TypedColumnClauseArgument as _TCCA # noqa 

89 from .base import ReadOnlyColumnCollection 

90 from .compiler import SQLCompiler 

91 from .elements import KeyedColumnElement 

92 from .selectable import _ColumnsClauseElement 

93 from .selectable import _SelectIterable 

94 from .selectable import Select 

95 from .selectable import Selectable 

96 

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

98 

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

100 

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

102 

103else: 

104 isupdate = operator.attrgetter("isupdate") 

105 isdelete = operator.attrgetter("isdelete") 

106 isinsert = operator.attrgetter("isinsert") 

107 

108 

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

110_Ts = TypeVarTuple("_Ts") 

111 

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

113_DMLTableElement = Union[TableClause, Alias, Join] 

114 

115 

116class DMLState(CompileState): 

117 _no_parameters = True 

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

119 _multi_parameters: Optional[ 

120 List[MutableMapping[_DMLColumnElement, Any]] 

121 ] = None 

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

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

124 _primary_table: FromClause 

125 _supports_implicit_returning = True 

126 

127 isupdate = False 

128 isdelete = False 

129 isinsert = False 

130 

131 statement: UpdateBase 

132 

133 def __init__( 

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

135 ): 

136 raise NotImplementedError() 

137 

138 @classmethod 

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

140 return { 

141 "name": ( 

142 statement.table.name 

143 if is_named_from_clause(statement.table) 

144 else None 

145 ), 

146 "table": statement.table, 

147 } 

148 

149 @classmethod 

150 def get_returning_column_descriptions( 

151 cls, statement: UpdateBase 

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

153 return [ 

154 { 

155 "name": c.key, 

156 "type": c.type, 

157 "expr": c, 

158 } 

159 for c in statement._all_selected_columns 

160 ] 

161 

162 @property 

163 def dml_table(self) -> _DMLTableElement: 

164 return self.statement.table 

165 

166 if TYPE_CHECKING: 

167 

168 @classmethod 

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

170 

171 @classmethod 

172 def _get_multi_crud_kv_pairs( 

173 cls, 

174 statement: UpdateBase, 

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

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

177 return [ 

178 { 

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

180 for k, v in mapping.items() 

181 } 

182 for mapping in multi_kv_iterator 

183 ] 

184 

185 @classmethod 

186 def _get_crud_kv_pairs( 

187 cls, 

188 statement: UpdateBase, 

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

190 needs_to_be_cacheable: bool, 

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

192 return [ 

193 ( 

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

195 ( 

196 v 

197 if not needs_to_be_cacheable 

198 else coercions.expect( 

199 roles.ExpressionElementRole, 

200 v, 

201 type_=NullType(), 

202 is_crud=True, 

203 ) 

204 ), 

205 ) 

206 for k, v in kv_iterator 

207 ] 

208 

209 def _make_extra_froms( 

210 self, statement: DMLWhereBase 

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

212 froms: List[FromClause] = [] 

213 

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

215 primary_table = all_tables[0] 

216 seen = {primary_table} 

217 

218 consider = statement._where_criteria 

219 if self._dict_parameters: 

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

221 

222 for crit in consider: 

223 for item in _from_objects(crit): 

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

225 froms.append(item) 

226 seen.update(item._cloned_set) 

227 

228 froms.extend(all_tables[1:]) 

229 return primary_table, froms 

230 

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

232 if self._no_parameters: 

233 self._dict_parameters = statement._values 

234 self._no_parameters = False 

235 

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

237 assert statement._select_names is not None 

238 parameters: MutableMapping[_DMLColumnElement, Any] = { 

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

240 } 

241 

242 if self._no_parameters: 

243 self._no_parameters = False 

244 self._dict_parameters = parameters 

245 else: 

246 # this condition normally not reachable as the Insert 

247 # does not allow this construction to occur 

248 assert False, "This statement already has parameters" 

249 

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

251 raise exc.InvalidRequestError( 

252 "%s construct does not support " 

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

254 ) 

255 

256 def _cant_mix_formats_error(self) -> NoReturn: 

257 raise exc.InvalidRequestError( 

258 "Can't mix single and multiple VALUES " 

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

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

261 "ambiguous." 

262 ) 

263 

264 

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

266class InsertDMLState(DMLState): 

267 isinsert = True 

268 

269 include_table_with_column_exprs = False 

270 

271 _has_multi_parameters = False 

272 

273 def __init__( 

274 self, 

275 statement: Insert, 

276 compiler: SQLCompiler, 

277 disable_implicit_returning: bool = False, 

278 **kw: Any, 

279 ): 

280 self.statement = statement 

281 self._primary_table = statement.table 

282 

283 if disable_implicit_returning: 

284 self._supports_implicit_returning = False 

285 

286 self.isinsert = True 

287 if statement._select_names: 

288 self._process_select_values(statement) 

289 if statement._values is not None: 

290 self._process_values(statement) 

291 if statement._multi_values: 

292 self._process_multi_values(statement) 

293 

294 @util.memoized_property 

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

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

297 return [ 

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

299 for col in self._dict_parameters or () 

300 ] 

301 

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

303 if self._no_parameters: 

304 self._has_multi_parameters = False 

305 self._dict_parameters = statement._values 

306 self._no_parameters = False 

307 elif self._has_multi_parameters: 

308 self._cant_mix_formats_error() 

309 

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

311 for parameters in statement._multi_values: 

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

313 ( 

314 { 

315 c.key: value 

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

317 } 

318 if isinstance(parameter_set, collections_abc.Sequence) 

319 else parameter_set 

320 ) 

321 for parameter_set in parameters 

322 ] 

323 

324 if self._no_parameters: 

325 self._no_parameters = False 

326 self._has_multi_parameters = True 

327 self._multi_parameters = multi_parameters 

328 self._dict_parameters = self._multi_parameters[0] 

329 elif not self._has_multi_parameters: 

330 self._cant_mix_formats_error() 

331 else: 

332 assert self._multi_parameters 

333 self._multi_parameters.extend(multi_parameters) 

334 

335 

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

337class UpdateDMLState(DMLState): 

338 isupdate = True 

339 

340 include_table_with_column_exprs = False 

341 

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

343 self.statement = statement 

344 

345 self.isupdate = True 

346 if statement._ordered_values is not None: 

347 self._process_ordered_values(statement) 

348 elif statement._values is not None: 

349 self._process_values(statement) 

350 elif statement._multi_values: 

351 self._no_multi_values_supported(statement) 

352 t, ef = self._make_extra_froms(statement) 

353 self._primary_table = t 

354 self._extra_froms = ef 

355 

356 self.is_multitable = mt = ef 

357 self.include_table_with_column_exprs = bool( 

358 mt and compiler.render_table_with_column_in_update_from 

359 ) 

360 

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

362 parameters = statement._ordered_values 

363 

364 if self._no_parameters: 

365 self._no_parameters = False 

366 assert parameters is not None 

367 self._dict_parameters = dict(parameters) 

368 self._ordered_values = parameters 

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

370 else: 

371 raise exc.InvalidRequestError( 

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

373 "with any other values() call" 

374 ) 

375 

376 

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

378class DeleteDMLState(DMLState): 

379 isdelete = True 

380 

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

382 self.statement = statement 

383 

384 self.isdelete = True 

385 t, ef = self._make_extra_froms(statement) 

386 self._primary_table = t 

387 self._extra_froms = ef 

388 self.is_multitable = ef 

389 

390 

391class UpdateBase( 

392 roles.DMLRole, 

393 HasCTE, 

394 HasCompileState, 

395 DialectKWArgs, 

396 HasPrefixes, 

397 Generative, 

398 ExecutableReturnsRows, 

399 ClauseElement, 

400): 

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

402 

403 __visit_name__ = "update_base" 

404 

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

406 util.EMPTY_DICT 

407 ) 

408 named_with_column = False 

409 

410 _label_style: SelectLabelStyle = ( 

411 SelectLabelStyle.LABEL_STYLE_DISAMBIGUATE_ONLY 

412 ) 

413 table: _DMLTableElement 

414 

415 _return_defaults = False 

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

417 None 

418 ) 

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

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

421 

422 is_dml = True 

423 

424 def _generate_fromclause_column_proxies( 

425 self, fromclause: FromClause 

426 ) -> None: 

427 fromclause._columns._populate_separate_keys( 

428 col._make_proxy(fromclause) 

429 for col in self._all_selected_columns 

430 if is_column_element(col) 

431 ) 

432 

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

434 """Set the parameters for the statement. 

435 

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

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

438 SET/VALUES clause of UPDATE and INSERT. 

439 

440 """ 

441 raise NotImplementedError( 

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

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

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

445 ) 

446 

447 @_generative 

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

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

450 

451 e.g.:: 

452 

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

454 

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

456 associated with the constructor. 

457 

458 

459 """ 

460 self._validate_dialect_kwargs(opt) 

461 return self 

462 

463 @_generative 

464 def return_defaults( 

465 self, 

466 *cols: _DMLColumnArgument, 

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

468 sort_by_parameter_order: bool = False, 

469 ) -> Self: 

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

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

472 backends only. 

473 

474 .. deepalchemy:: 

475 

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

477 for its internal work in fetching newly generated primary key 

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

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

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

481 ORM inserts. Its behavior is fairly idiosyncratic 

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

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

484 add RETURNING clauses to their INSERT, UPDATE and DELETE 

485 statements. 

486 

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

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

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

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

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

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

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

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

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

496 value. 

497 

498 However, when the statement is modified by calling 

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

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

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

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

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

504 from the statement's execution, not only will 

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

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

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

508 of server generated 

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

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

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

512 

513 When invoking INSERT statements with multiple rows using 

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

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

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

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

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

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

520 values for each row inserted. The 

521 :attr:`.CursorResult.inserted_primary_key` and 

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

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

524 

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

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

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

528 INSERT, UPDATE or DELETE statement proceeds normally. 

529 

530 E.g.:: 

531 

532 stmt = table.insert().values(data='newdata').return_defaults() 

533 

534 result = connection.execute(stmt) 

535 

536 server_created_at = result.returned_defaults['created_at'] 

537 

538 When used against an UPDATE statement 

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

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

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

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

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

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

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

546 normally change values when a DELETE statement proceeds. 

547 

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

549 for DELETE statements also and has been moved from 

550 :class:`.ValuesBase` to :class:`.UpdateBase`. 

551 

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

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

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

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

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

557 at a time. 

558 

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

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

561 

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

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

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

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

566 

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

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

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

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

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

572 attribute being left unpopulated. 

573 

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

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

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

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

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

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

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

581 ``False``. 

582 

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

584 backend database driver supports the 

585 :ref:`insertmanyvalues <engine_insertmanyvalues>` 

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

587 When executemany is used, the 

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

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

590 will return the inserted defaults and primary keys. 

591 

592 .. versionadded:: 1.4 Added 

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

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

595 In version 2.0, the underlying implementation which fetches and 

596 populates the data for these attributes was generalized to be 

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

598 supported by the ``psycopg2`` driver. 

599 

600 

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

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

603 will be fetched. 

604 :param supplemental_cols: optional list of RETURNING expressions, 

605 in the same form as one would pass to the 

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

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

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

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

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

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

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

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

614 reliably be targeted positionally. 

615 

616 .. versionadded:: 2.0 

617 

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

619 executed against multiple parameter sets, organize the results of 

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

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

622 execution for supporting dialects and typically makes use of the 

623 :term:`insertmanyvalues` feature. 

624 

625 .. versionadded:: 2.0.10 

626 

627 .. seealso:: 

628 

629 :ref:`engine_insertmanyvalues_returning_order` - background on 

630 sorting of RETURNING rows for bulk INSERT 

631 

632 .. seealso:: 

633 

634 :meth:`.UpdateBase.returning` 

635 

636 :attr:`_engine.CursorResult.returned_defaults` 

637 

638 :attr:`_engine.CursorResult.returned_defaults_rows` 

639 

640 :attr:`_engine.CursorResult.inserted_primary_key` 

641 

642 :attr:`_engine.CursorResult.inserted_primary_key_rows` 

643 

644 """ 

645 

646 if self._return_defaults: 

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

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

649 # are columns in the collection 

650 if self._return_defaults_columns and cols: 

651 self._return_defaults_columns = tuple( 

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

653 coercions.expect(roles.ColumnsClauseRole, c) 

654 for c in cols 

655 ) 

656 ) 

657 else: 

658 # set for all columns 

659 self._return_defaults_columns = () 

660 else: 

661 self._return_defaults_columns = tuple( 

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

663 ) 

664 self._return_defaults = True 

665 if sort_by_parameter_order: 

666 if not self.is_insert: 

667 raise exc.ArgumentError( 

668 "The 'sort_by_parameter_order' argument to " 

669 "return_defaults() only applies to INSERT statements" 

670 ) 

671 self._sort_by_parameter_order = True 

672 if supplemental_cols: 

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

674 # is for test suites but also for vertical splicing 

675 supplemental_col_tup = ( 

676 coercions.expect(roles.ColumnsClauseRole, c) 

677 for c in supplemental_cols 

678 ) 

679 

680 if self._supplemental_returning is None: 

681 self._supplemental_returning = tuple( 

682 util.unique_list(supplemental_col_tup) 

683 ) 

684 else: 

685 self._supplemental_returning = tuple( 

686 util.unique_list( 

687 self._supplemental_returning 

688 + tuple(supplemental_col_tup) 

689 ) 

690 ) 

691 

692 return self 

693 

694 @_generative 

695 def returning( 

696 self, 

697 *cols: _ColumnsClauseArgument[Any], 

698 sort_by_parameter_order: bool = False, 

699 **__kw: Any, 

700 ) -> UpdateBase: 

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

702 

703 e.g.: 

704 

705 .. sourcecode:: pycon+sql 

706 

707 >>> stmt = ( 

708 ... table.update() 

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

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

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

712 ... ) 

713 >>> print(stmt) 

714 {printsql}UPDATE some_table SET status=:status 

715 WHERE some_table.data = :data_1 

716 RETURNING some_table.server_flag, some_table.updated_timestamp 

717 

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

719 list of expressions to be returned. 

720 

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

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

723 

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

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

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

727 expressions: 

728 

729 .. sourcecode:: pycon+sql 

730 

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

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

733 ... ) 

734 >>> print(stmt) 

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

736 VALUES (:first_name, :last_name) 

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

738 

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

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

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

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

743 

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

745 available via the result set and can be iterated using 

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

747 For DBAPIs which do not 

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

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

750 amount of behavioral neutrality is provided. 

751 

752 Note that not all databases/DBAPIs 

753 support RETURNING. For those backends with no support, 

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

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

756 varies greatly, including restrictions on executemany() 

757 and other statements which return multiple rows. Please 

758 read the documentation notes for the database in use in 

759 order to determine the availability of RETURNING. 

760 

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

762 entities to be returned. 

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

764 executed against multiple parameter sets, organize the results of 

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

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

767 execution for supporting dialects and typically makes use of the 

768 :term:`insertmanyvalues` feature. 

769 

770 .. versionadded:: 2.0.10 

771 

772 .. seealso:: 

773 

774 :ref:`engine_insertmanyvalues_returning_order` - background on 

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

776 

777 :ref:`orm_queryguide_bulk_insert_returning_ordered` - example of 

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

779 

780 .. seealso:: 

781 

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

783 towards efficient fetching of server-side defaults and triggers 

784 for single-row INSERTs or UPDATEs. 

785 

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

787 

788 """ # noqa: E501 

789 if __kw: 

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

791 if self._return_defaults: 

792 raise exc.InvalidRequestError( 

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

794 ) 

795 self._returning += tuple( 

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

797 ) 

798 if sort_by_parameter_order: 

799 if not self.is_insert: 

800 raise exc.ArgumentError( 

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

802 "only applies to INSERT statements" 

803 ) 

804 self._sort_by_parameter_order = True 

805 return self 

806 

807 def corresponding_column( 

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

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

810 return self.exported_columns.corresponding_column( 

811 column, require_embedded=require_embedded 

812 ) 

813 

814 @util.ro_memoized_property 

815 def _all_selected_columns(self) -> _SelectIterable: 

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

817 

818 @util.ro_memoized_property 

819 def exported_columns( 

820 self, 

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

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

823 statement. 

824 

825 .. versionadded:: 1.4 

826 

827 """ 

828 return ColumnCollection( 

829 (c.key, c) 

830 for c in self._all_selected_columns 

831 if is_column_element(c) 

832 ).as_readonly() 

833 

834 @_generative 

835 def with_hint( 

836 self, 

837 text: str, 

838 selectable: Optional[_DMLTableArgument] = None, 

839 dialect_name: str = "*", 

840 ) -> Self: 

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

842 INSERT/UPDATE/DELETE statement. 

843 

844 .. note:: 

845 

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

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

848 :meth:`.UpdateBase.prefix_with`. 

849 

850 The text of the hint is rendered in the appropriate 

851 location for the database backend in use, relative 

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

853 statement, or optionally to that of the given 

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

855 

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

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

858 that only takes effect for SQL Server:: 

859 

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

861 

862 :param text: Text of the hint. 

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

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

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

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

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

868 that dialect is in use. 

869 """ 

870 if selectable is None: 

871 selectable = self.table 

872 else: 

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

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

875 return self 

876 

877 @property 

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

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

880 entity which this DML construct is operating against. 

881 

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

883 extended structure which includes information about mapped 

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

885 contains more background. 

886 

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

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

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

890 

891 >>> stmt = insert(user_table) 

892 >>> stmt.entity_description 

893 { 

894 "name": "user_table", 

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

896 } 

897 

898 .. versionadded:: 1.4.33 

899 

900 .. seealso:: 

901 

902 :attr:`.UpdateBase.returning_column_descriptions` 

903 

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

905 a :func:`.select` construct 

906 

907 :ref:`queryguide_inspection` - ORM background 

908 

909 """ 

910 meth = DMLState.get_plugin_class(self).get_entity_description 

911 return meth(self) 

912 

913 @property 

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

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

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

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

918 

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

920 extended structure which includes information about mapped 

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

922 contains more background. 

923 

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

925 derived from the same objects that are returned by the 

926 :attr:`.UpdateBase.exported_columns` accessor:: 

927 

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

929 >>> stmt.entity_description 

930 [ 

931 { 

932 "name": "id", 

933 "type": Integer, 

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

935 }, 

936 { 

937 "name": "name", 

938 "type": String(), 

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

940 }, 

941 ] 

942 

943 .. versionadded:: 1.4.33 

944 

945 .. seealso:: 

946 

947 :attr:`.UpdateBase.entity_description` 

948 

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

950 a :func:`.select` construct 

951 

952 :ref:`queryguide_inspection` - ORM background 

953 

954 """ # noqa: E501 

955 meth = DMLState.get_plugin_class( 

956 self 

957 ).get_returning_column_descriptions 

958 return meth(self) 

959 

960 

961class ValuesBase(UpdateBase): 

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

963 INSERT and UPDATE constructs.""" 

964 

965 __visit_name__ = "values_base" 

966 

967 _supports_multi_parameters = False 

968 

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

970 """SELECT statement for INSERT .. FROM SELECT""" 

971 

972 _post_values_clause: Optional[ClauseElement] = None 

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

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

975 

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

977 _multi_values: Tuple[ 

978 Union[ 

979 Sequence[Dict[_DMLColumnElement, Any]], 

980 Sequence[Sequence[Any]], 

981 ], 

982 ..., 

983 ] = () 

984 

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

986 

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

988 _inline: bool = False 

989 

990 def __init__(self, table: _DMLTableArgument): 

991 self.table = coercions.expect( 

992 roles.DMLTableRole, table, apply_propagate_attrs=self 

993 ) 

994 

995 @_generative 

996 @_exclusive_against( 

997 "_select_names", 

998 "_ordered_values", 

999 msgs={ 

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

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

1002 "values present", 

1003 }, 

1004 ) 

1005 def values( 

1006 self, 

1007 *args: Union[ 

1008 _DMLColumnKeyMapping[Any], 

1009 Sequence[Any], 

1010 ], 

1011 **kwargs: Any, 

1012 ) -> Self: 

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

1014 clause for an UPDATE. 

1015 

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

1017 :class:`_expression.Update` 

1018 constructs support 

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

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

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

1022 particular set of parameters into the statement. 

1023 

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

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

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

1027 dictionary of parameters, the newly passed keys will replace 

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

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

1030 onto the existing list of values. 

1031 

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

1033 of a :class:`_schema.Column` 

1034 mapped to the value to be rendered into the 

1035 VALUES or SET clause:: 

1036 

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

1038 

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

1040 

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

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

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

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

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

1046 :class:`_expression.Update` construct. 

1047 

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

1049 :class:`_expression.Update` 

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

1051 that of the kwargs form:: 

1052 

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

1054 

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

1056 

1057 Also for either form but more typically for the 

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

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

1060 

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

1062 

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

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

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

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

1067 MySQL, but not necessarily others:: 

1068 

1069 users.insert().values([ 

1070 {"name": "some name"}, 

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

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

1073 ]) 

1074 

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

1076 

1077 INSERT INTO users (name) VALUES 

1078 (:name_1), 

1079 (:name_2), 

1080 (:name_3) 

1081 

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

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

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

1085 INSERT statement against multiple rows, the normal method is 

1086 to pass a multiple values list to the 

1087 :meth:`_engine.Connection.execute` 

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

1089 more efficient for a very large number of parameters. 

1090 

1091 .. seealso:: 

1092 

1093 :ref:`tutorial_multiple_parameters` - an introduction to 

1094 the traditional Core method of multiple parameter set 

1095 invocation for INSERTs and other statements. 

1096 

1097 The UPDATE construct also supports rendering the SET parameters 

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

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

1100 

1101 .. seealso:: 

1102 

1103 :meth:`_expression.Update.ordered_values` 

1104 

1105 

1106 """ 

1107 if args: 

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

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

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

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

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

1113 arg = args[0] 

1114 

1115 if kwargs: 

1116 raise exc.ArgumentError( 

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

1118 "simultaneously" 

1119 ) 

1120 elif len(args) > 1: 

1121 raise exc.ArgumentError( 

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

1123 "dictionaries/tuples is accepted positionally." 

1124 ) 

1125 

1126 elif isinstance(arg, collections_abc.Sequence): 

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

1128 multi_kv_generator = DMLState.get_plugin_class( 

1129 self 

1130 )._get_multi_crud_kv_pairs 

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

1132 return self 

1133 

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

1135 self._multi_values += (arg,) 

1136 return self 

1137 

1138 if TYPE_CHECKING: 

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

1140 # case 

1141 assert isinstance(self, Insert) 

1142 

1143 # tuple values 

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

1145 

1146 else: 

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

1148 # so this is fairly quick. 

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

1150 if args: 

1151 raise exc.ArgumentError( 

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

1153 "dictionaries/tuples is accepted positionally." 

1154 ) 

1155 

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

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

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

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

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

1161 

1162 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs 

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

1164 if self._values: 

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

1166 else: 

1167 self._values = util.immutabledict(coerced_arg) 

1168 return self 

1169 

1170 

1171class Insert(ValuesBase): 

1172 """Represent an INSERT construct. 

1173 

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

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

1176 

1177 """ 

1178 

1179 __visit_name__ = "insert" 

1180 

1181 _supports_multi_parameters = True 

1182 

1183 select = None 

1184 include_insert_from_select_defaults = False 

1185 

1186 _sort_by_parameter_order: bool = False 

1187 

1188 is_insert = True 

1189 

1190 table: TableClause 

1191 

1192 _traverse_internals = ( 

1193 [ 

1194 ("table", InternalTraversal.dp_clauseelement), 

1195 ("_inline", InternalTraversal.dp_boolean), 

1196 ("_select_names", InternalTraversal.dp_string_list), 

1197 ("_values", InternalTraversal.dp_dml_values), 

1198 ("_multi_values", InternalTraversal.dp_dml_multi_values), 

1199 ("select", InternalTraversal.dp_clauseelement), 

1200 ("_post_values_clause", InternalTraversal.dp_clauseelement), 

1201 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1202 ("_hints", InternalTraversal.dp_table_hint_list), 

1203 ("_return_defaults", InternalTraversal.dp_boolean), 

1204 ( 

1205 "_return_defaults_columns", 

1206 InternalTraversal.dp_clauseelement_tuple, 

1207 ), 

1208 ("_sort_by_parameter_order", InternalTraversal.dp_boolean), 

1209 ] 

1210 + HasPrefixes._has_prefixes_traverse_internals 

1211 + DialectKWArgs._dialect_kwargs_traverse_internals 

1212 + Executable._executable_traverse_internals 

1213 + HasCTE._has_ctes_traverse_internals 

1214 ) 

1215 

1216 def __init__(self, table: _DMLTableArgument): 

1217 super().__init__(table) 

1218 

1219 @_generative 

1220 def inline(self) -> Self: 

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

1222 

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

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

1225 in particular, 

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

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

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

1229 returning" feature for the statement. 

1230 

1231 

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

1233 parameter 

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

1235 

1236 """ 

1237 self._inline = True 

1238 return self 

1239 

1240 @_generative 

1241 def from_select( 

1242 self, 

1243 names: Sequence[_DMLColumnArgument], 

1244 select: Selectable, 

1245 include_defaults: bool = True, 

1246 ) -> Self: 

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

1248 an ``INSERT...FROM SELECT`` statement. 

1249 

1250 e.g.:: 

1251 

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

1253 ins = table2.insert().from_select(['a', 'b'], sel) 

1254 

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

1256 :class:`_schema.Column` 

1257 objects representing the target columns. 

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

1259 :class:`_expression.FromClause` 

1260 or other construct which resolves into a 

1261 :class:`_expression.FromClause`, 

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

1263 columns returned from this FROM clause should correspond to the 

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

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

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

1267 correspond. 

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

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

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

1271 otherwise specified in the list of names will be rendered 

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

1273 included in the data to be inserted. 

1274 

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

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

1277 per row**. 

1278 

1279 """ 

1280 

1281 if self._values: 

1282 raise exc.InvalidRequestError( 

1283 "This construct already inserts value expressions" 

1284 ) 

1285 

1286 self._select_names = [ 

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

1288 for name in names 

1289 ] 

1290 self._inline = True 

1291 self.include_insert_from_select_defaults = include_defaults 

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

1293 return self 

1294 

1295 if TYPE_CHECKING: 

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

1297 

1298 # code within this block is **programmatically, 

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

1300 

1301 @overload 

1302 def returning( 

1303 self, 

1304 __ent0: _TCCA[_T0], 

1305 /, 

1306 *, 

1307 sort_by_parameter_order: bool = False, 

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

1309 

1310 @overload 

1311 def returning( 

1312 self, 

1313 __ent0: _TCCA[_T0], 

1314 __ent1: _TCCA[_T1], 

1315 /, 

1316 *, 

1317 sort_by_parameter_order: bool = False, 

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

1319 

1320 @overload 

1321 def returning( 

1322 self, 

1323 __ent0: _TCCA[_T0], 

1324 __ent1: _TCCA[_T1], 

1325 __ent2: _TCCA[_T2], 

1326 /, 

1327 *, 

1328 sort_by_parameter_order: bool = False, 

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

1330 

1331 @overload 

1332 def returning( 

1333 self, 

1334 __ent0: _TCCA[_T0], 

1335 __ent1: _TCCA[_T1], 

1336 __ent2: _TCCA[_T2], 

1337 __ent3: _TCCA[_T3], 

1338 /, 

1339 *, 

1340 sort_by_parameter_order: bool = False, 

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

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 __ent4: _TCCA[_T4], 

1351 /, 

1352 *, 

1353 sort_by_parameter_order: bool = False, 

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

1355 

1356 @overload 

1357 def returning( 

1358 self, 

1359 __ent0: _TCCA[_T0], 

1360 __ent1: _TCCA[_T1], 

1361 __ent2: _TCCA[_T2], 

1362 __ent3: _TCCA[_T3], 

1363 __ent4: _TCCA[_T4], 

1364 __ent5: _TCCA[_T5], 

1365 /, 

1366 *, 

1367 sort_by_parameter_order: bool = False, 

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

1369 

1370 @overload 

1371 def returning( 

1372 self, 

1373 __ent0: _TCCA[_T0], 

1374 __ent1: _TCCA[_T1], 

1375 __ent2: _TCCA[_T2], 

1376 __ent3: _TCCA[_T3], 

1377 __ent4: _TCCA[_T4], 

1378 __ent5: _TCCA[_T5], 

1379 __ent6: _TCCA[_T6], 

1380 /, 

1381 *, 

1382 sort_by_parameter_order: bool = False, 

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

1384 

1385 @overload 

1386 def returning( 

1387 self, 

1388 __ent0: _TCCA[_T0], 

1389 __ent1: _TCCA[_T1], 

1390 __ent2: _TCCA[_T2], 

1391 __ent3: _TCCA[_T3], 

1392 __ent4: _TCCA[_T4], 

1393 __ent5: _TCCA[_T5], 

1394 __ent6: _TCCA[_T6], 

1395 __ent7: _TCCA[_T7], 

1396 /, 

1397 *entities: _ColumnsClauseArgument[Any], 

1398 sort_by_parameter_order: bool = False, 

1399 ) -> ReturningInsert[ 

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

1401 ]: ... 

1402 

1403 # END OVERLOADED FUNCTIONS self.returning 

1404 

1405 @overload 

1406 def returning( 

1407 self, 

1408 *cols: _ColumnsClauseArgument[Any], 

1409 sort_by_parameter_order: bool = False, 

1410 **__kw: Any, 

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

1412 

1413 def returning( 

1414 self, 

1415 *cols: _ColumnsClauseArgument[Any], 

1416 sort_by_parameter_order: bool = False, 

1417 **__kw: Any, 

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

1419 

1420 

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

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

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

1424 

1425 This datatype is delivered when calling the 

1426 :meth:`.Insert.returning` method. 

1427 

1428 .. versionadded:: 2.0 

1429 

1430 """ 

1431 

1432 

1433class DMLWhereBase: 

1434 table: _DMLTableElement 

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

1436 

1437 @_generative 

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

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

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

1441 

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

1443 support multiple-table forms, including database-specific 

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

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

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

1447 See the linked tutorial sections below for examples. 

1448 

1449 .. seealso:: 

1450 

1451 :ref:`tutorial_correlated_updates` 

1452 

1453 :ref:`tutorial_update_from` 

1454 

1455 :ref:`tutorial_multi_table_deletes` 

1456 

1457 """ 

1458 

1459 for criterion in whereclause: 

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

1461 roles.WhereHavingRole, criterion, apply_propagate_attrs=self 

1462 ) 

1463 self._where_criteria += (where_criteria,) 

1464 return self 

1465 

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

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

1468 

1469 .. versionadded:: 1.4 

1470 

1471 """ 

1472 

1473 return self.where(*criteria) 

1474 

1475 def _filter_by_zero(self) -> _DMLTableElement: 

1476 return self.table 

1477 

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

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

1480 to this select. 

1481 

1482 """ 

1483 from_entity = self._filter_by_zero() 

1484 

1485 clauses = [ 

1486 _entity_namespace_key(from_entity, key) == value 

1487 for key, value in kwargs.items() 

1488 ] 

1489 return self.filter(*clauses) 

1490 

1491 @property 

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

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

1494 statement. 

1495 

1496 This assembles the current collection of WHERE criteria 

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

1498 

1499 

1500 .. versionadded:: 1.4 

1501 

1502 """ 

1503 

1504 return BooleanClauseList._construct_for_whereclause( 

1505 self._where_criteria 

1506 ) 

1507 

1508 

1509class Update(DMLWhereBase, ValuesBase): 

1510 """Represent an Update construct. 

1511 

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

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

1514 

1515 """ 

1516 

1517 __visit_name__ = "update" 

1518 

1519 is_update = True 

1520 

1521 _traverse_internals = ( 

1522 [ 

1523 ("table", InternalTraversal.dp_clauseelement), 

1524 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1525 ("_inline", InternalTraversal.dp_boolean), 

1526 ("_ordered_values", InternalTraversal.dp_dml_ordered_values), 

1527 ("_values", InternalTraversal.dp_dml_values), 

1528 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1529 ("_hints", InternalTraversal.dp_table_hint_list), 

1530 ("_return_defaults", InternalTraversal.dp_boolean), 

1531 ( 

1532 "_return_defaults_columns", 

1533 InternalTraversal.dp_clauseelement_tuple, 

1534 ), 

1535 ] 

1536 + HasPrefixes._has_prefixes_traverse_internals 

1537 + DialectKWArgs._dialect_kwargs_traverse_internals 

1538 + Executable._executable_traverse_internals 

1539 + HasCTE._has_ctes_traverse_internals 

1540 ) 

1541 

1542 def __init__(self, table: _DMLTableArgument): 

1543 super().__init__(table) 

1544 

1545 @_generative 

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

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

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

1549 resulting UPDATE statement. 

1550 

1551 E.g.:: 

1552 

1553 stmt = table.update().ordered_values( 

1554 ("name", "ed"), ("ident", "foo") 

1555 ) 

1556 

1557 .. seealso:: 

1558 

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

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

1561 

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

1563 method 

1564 supersedes the 

1565 :paramref:`_expression.update.preserve_parameter_order` 

1566 parameter, which will be removed in SQLAlchemy 2.0. 

1567 

1568 """ 

1569 if self._values: 

1570 raise exc.ArgumentError( 

1571 "This statement already has values present" 

1572 ) 

1573 elif self._ordered_values: 

1574 raise exc.ArgumentError( 

1575 "This statement already has ordered values present" 

1576 ) 

1577 

1578 kv_generator = DMLState.get_plugin_class(self)._get_crud_kv_pairs 

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

1580 return self 

1581 

1582 @_generative 

1583 def inline(self) -> Self: 

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

1585 

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

1587 objects via the 

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

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

1590 in the dictionary returned from 

1591 :meth:`_engine.CursorResult.last_updated_params`. 

1592 

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

1594 parameter 

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

1596 

1597 """ 

1598 self._inline = True 

1599 return self 

1600 

1601 if TYPE_CHECKING: 

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

1603 

1604 # code within this block is **programmatically, 

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

1606 

1607 @overload 

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

1609 

1610 @overload 

1611 def returning( 

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

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

1614 

1615 @overload 

1616 def returning( 

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

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

1619 

1620 @overload 

1621 def returning( 

1622 self, 

1623 __ent0: _TCCA[_T0], 

1624 __ent1: _TCCA[_T1], 

1625 __ent2: _TCCA[_T2], 

1626 __ent3: _TCCA[_T3], 

1627 /, 

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

1629 

1630 @overload 

1631 def returning( 

1632 self, 

1633 __ent0: _TCCA[_T0], 

1634 __ent1: _TCCA[_T1], 

1635 __ent2: _TCCA[_T2], 

1636 __ent3: _TCCA[_T3], 

1637 __ent4: _TCCA[_T4], 

1638 /, 

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

1640 

1641 @overload 

1642 def returning( 

1643 self, 

1644 __ent0: _TCCA[_T0], 

1645 __ent1: _TCCA[_T1], 

1646 __ent2: _TCCA[_T2], 

1647 __ent3: _TCCA[_T3], 

1648 __ent4: _TCCA[_T4], 

1649 __ent5: _TCCA[_T5], 

1650 /, 

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

1652 

1653 @overload 

1654 def returning( 

1655 self, 

1656 __ent0: _TCCA[_T0], 

1657 __ent1: _TCCA[_T1], 

1658 __ent2: _TCCA[_T2], 

1659 __ent3: _TCCA[_T3], 

1660 __ent4: _TCCA[_T4], 

1661 __ent5: _TCCA[_T5], 

1662 __ent6: _TCCA[_T6], 

1663 /, 

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

1665 

1666 @overload 

1667 def returning( 

1668 self, 

1669 __ent0: _TCCA[_T0], 

1670 __ent1: _TCCA[_T1], 

1671 __ent2: _TCCA[_T2], 

1672 __ent3: _TCCA[_T3], 

1673 __ent4: _TCCA[_T4], 

1674 __ent5: _TCCA[_T5], 

1675 __ent6: _TCCA[_T6], 

1676 __ent7: _TCCA[_T7], 

1677 /, 

1678 *entities: _ColumnsClauseArgument[Any], 

1679 ) -> ReturningUpdate[ 

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

1681 ]: ... 

1682 

1683 # END OVERLOADED FUNCTIONS self.returning 

1684 

1685 @overload 

1686 def returning( 

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

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

1689 

1690 def returning( 

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

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

1693 

1694 

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

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

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

1698 

1699 This datatype is delivered when calling the 

1700 :meth:`.Update.returning` method. 

1701 

1702 .. versionadded:: 2.0 

1703 

1704 """ 

1705 

1706 

1707class Delete(DMLWhereBase, UpdateBase): 

1708 """Represent a DELETE construct. 

1709 

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

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

1712 

1713 """ 

1714 

1715 __visit_name__ = "delete" 

1716 

1717 is_delete = True 

1718 

1719 _traverse_internals = ( 

1720 [ 

1721 ("table", InternalTraversal.dp_clauseelement), 

1722 ("_where_criteria", InternalTraversal.dp_clauseelement_tuple), 

1723 ("_returning", InternalTraversal.dp_clauseelement_tuple), 

1724 ("_hints", InternalTraversal.dp_table_hint_list), 

1725 ] 

1726 + HasPrefixes._has_prefixes_traverse_internals 

1727 + DialectKWArgs._dialect_kwargs_traverse_internals 

1728 + Executable._executable_traverse_internals 

1729 + HasCTE._has_ctes_traverse_internals 

1730 ) 

1731 

1732 def __init__(self, table: _DMLTableArgument): 

1733 self.table = coercions.expect( 

1734 roles.DMLTableRole, table, apply_propagate_attrs=self 

1735 ) 

1736 

1737 if TYPE_CHECKING: 

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

1739 

1740 # code within this block is **programmatically, 

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

1742 

1743 @overload 

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

1745 

1746 @overload 

1747 def returning( 

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

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

1750 

1751 @overload 

1752 def returning( 

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

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

1755 

1756 @overload 

1757 def returning( 

1758 self, 

1759 __ent0: _TCCA[_T0], 

1760 __ent1: _TCCA[_T1], 

1761 __ent2: _TCCA[_T2], 

1762 __ent3: _TCCA[_T3], 

1763 /, 

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

1765 

1766 @overload 

1767 def returning( 

1768 self, 

1769 __ent0: _TCCA[_T0], 

1770 __ent1: _TCCA[_T1], 

1771 __ent2: _TCCA[_T2], 

1772 __ent3: _TCCA[_T3], 

1773 __ent4: _TCCA[_T4], 

1774 /, 

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

1776 

1777 @overload 

1778 def returning( 

1779 self, 

1780 __ent0: _TCCA[_T0], 

1781 __ent1: _TCCA[_T1], 

1782 __ent2: _TCCA[_T2], 

1783 __ent3: _TCCA[_T3], 

1784 __ent4: _TCCA[_T4], 

1785 __ent5: _TCCA[_T5], 

1786 /, 

1787 ) -> ReturningDelete[_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 /, 

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

1801 

1802 @overload 

1803 def returning( 

1804 self, 

1805 __ent0: _TCCA[_T0], 

1806 __ent1: _TCCA[_T1], 

1807 __ent2: _TCCA[_T2], 

1808 __ent3: _TCCA[_T3], 

1809 __ent4: _TCCA[_T4], 

1810 __ent5: _TCCA[_T5], 

1811 __ent6: _TCCA[_T6], 

1812 __ent7: _TCCA[_T7], 

1813 /, 

1814 *entities: _ColumnsClauseArgument[Any], 

1815 ) -> ReturningDelete[ 

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

1817 ]: ... 

1818 

1819 # END OVERLOADED FUNCTIONS self.returning 

1820 

1821 @overload 

1822 def returning( 

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

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

1825 

1826 def returning( 

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

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

1829 

1830 

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

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

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

1834 

1835 This datatype is delivered when calling the 

1836 :meth:`.Delete.returning` method. 

1837 

1838 .. versionadded:: 2.0 

1839 

1840 """