Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/orm/query.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

792 statements  

1# orm/query.py 

2# Copyright (C) 2005-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 

8"""The Query class and support. 

9 

10Defines the :class:`_query.Query` class, the central 

11construct used by the ORM to construct database queries. 

12 

13The :class:`_query.Query` class should not be confused with the 

14:class:`_expression.Select` class, which defines database 

15SELECT operations at the SQL (non-ORM) level. ``Query`` differs from 

16``Select`` in that it returns ORM-mapped objects and interacts with an 

17ORM session, whereas the ``Select`` construct interacts directly with the 

18database to return iterable result sets. 

19 

20""" 

21from __future__ import annotations 

22 

23import collections.abc as collections_abc 

24import operator 

25from typing import Any 

26from typing import Callable 

27from typing import cast 

28from typing import Dict 

29from typing import Generic 

30from typing import Iterable 

31from typing import Iterator 

32from typing import List 

33from typing import Mapping 

34from typing import Optional 

35from typing import overload 

36from typing import Sequence 

37from typing import Tuple 

38from typing import Type 

39from typing import TYPE_CHECKING 

40from typing import TypeVar 

41from typing import Union 

42 

43from . import attributes 

44from . import interfaces 

45from . import loading 

46from . import util as orm_util 

47from ._typing import _O 

48from .base import _assertions 

49from .context import _column_descriptions 

50from .context import _determine_last_joined_entity 

51from .context import _legacy_filter_by_entity_zero 

52from .context import FromStatement 

53from .context import ORMCompileState 

54from .context import QueryContext 

55from .interfaces import ORMColumnDescription 

56from .interfaces import ORMColumnsClauseRole 

57from .util import AliasedClass 

58from .util import object_mapper 

59from .util import with_parent 

60from .. import exc as sa_exc 

61from .. import inspect 

62from .. import inspection 

63from .. import log 

64from .. import sql 

65from .. import util 

66from ..engine import Result 

67from ..engine import Row 

68from ..event import dispatcher 

69from ..event import EventTarget 

70from ..sql import coercions 

71from ..sql import expression 

72from ..sql import roles 

73from ..sql import Select 

74from ..sql import util as sql_util 

75from ..sql import visitors 

76from ..sql._typing import _FromClauseArgument 

77from ..sql.annotation import SupportsCloneAnnotations 

78from ..sql.base import _entity_namespace_key 

79from ..sql.base import _generative 

80from ..sql.base import _NoArg 

81from ..sql.base import Executable 

82from ..sql.base import Generative 

83from ..sql.elements import BooleanClauseList 

84from ..sql.expression import Exists 

85from ..sql.selectable import _MemoizedSelectEntities 

86from ..sql.selectable import _SelectFromElements 

87from ..sql.selectable import ForUpdateArg 

88from ..sql.selectable import HasHints 

89from ..sql.selectable import HasPrefixes 

90from ..sql.selectable import HasSuffixes 

91from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL 

92from ..sql.selectable import SelectLabelStyle 

93from ..util import deprecated 

94from ..util.typing import Literal 

95from ..util.typing import Self 

96from ..util.typing import TupleAny 

97from ..util.typing import TypeVarTuple 

98from ..util.typing import Unpack 

99 

100 

101if TYPE_CHECKING: 

102 from ._typing import _EntityType 

103 from ._typing import _ExternalEntityType 

104 from ._typing import _InternalEntityType 

105 from ._typing import SynchronizeSessionArgument 

106 from .mapper import Mapper 

107 from .path_registry import PathRegistry 

108 from .session import _PKIdentityArgument 

109 from .session import Session 

110 from .state import InstanceState 

111 from ..engine.cursor import CursorResult 

112 from ..engine.interfaces import _ImmutableExecuteOptions 

113 from ..engine.interfaces import CompiledCacheType 

114 from ..engine.interfaces import IsolationLevel 

115 from ..engine.interfaces import SchemaTranslateMapType 

116 from ..engine.result import FrozenResult 

117 from ..engine.result import ScalarResult 

118 from ..sql._typing import _ColumnExpressionArgument 

119 from ..sql._typing import _ColumnExpressionOrStrLabelArgument 

120 from ..sql._typing import _ColumnsClauseArgument 

121 from ..sql._typing import _DMLColumnArgument 

122 from ..sql._typing import _JoinTargetArgument 

123 from ..sql._typing import _LimitOffsetType 

124 from ..sql._typing import _MAYBE_ENTITY 

125 from ..sql._typing import _no_kw 

126 from ..sql._typing import _NOT_ENTITY 

127 from ..sql._typing import _OnClauseArgument 

128 from ..sql._typing import _PropagateAttrsType 

129 from ..sql._typing import _T0 

130 from ..sql._typing import _T1 

131 from ..sql._typing import _T2 

132 from ..sql._typing import _T3 

133 from ..sql._typing import _T4 

134 from ..sql._typing import _T5 

135 from ..sql._typing import _T6 

136 from ..sql._typing import _T7 

137 from ..sql._typing import _TypedColumnClauseArgument as _TCCA 

138 from ..sql.base import CacheableOptions 

139 from ..sql.base import ExecutableOption 

140 from ..sql.elements import ColumnElement 

141 from ..sql.elements import Label 

142 from ..sql.selectable import _ForUpdateOfArgument 

143 from ..sql.selectable import _JoinTargetElement 

144 from ..sql.selectable import _SetupJoinsElement 

145 from ..sql.selectable import Alias 

146 from ..sql.selectable import CTE 

147 from ..sql.selectable import ExecutableReturnsRows 

148 from ..sql.selectable import FromClause 

149 from ..sql.selectable import ScalarSelect 

150 from ..sql.selectable import Subquery 

151 

152 

153__all__ = ["Query", "QueryContext"] 

154 

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

156_Ts = TypeVarTuple("_Ts") 

157 

158 

159@inspection._self_inspects 

160@log.class_logger 

161class Query( 

162 _SelectFromElements, 

163 SupportsCloneAnnotations, 

164 HasPrefixes, 

165 HasSuffixes, 

166 HasHints, 

167 EventTarget, 

168 log.Identified, 

169 Generative, 

170 Executable, 

171 Generic[_T], 

172): 

173 """ORM-level SQL construction object. 

174 

175 .. legacy:: The ORM :class:`.Query` object is a legacy construct 

176 as of SQLAlchemy 2.0. See the notes at the top of 

177 :ref:`query_api_toplevel` for an overview, including links to migration 

178 documentation. 

179 

180 :class:`_query.Query` objects are normally initially generated using the 

181 :meth:`~.Session.query` method of :class:`.Session`, and in 

182 less common cases by instantiating the :class:`_query.Query` directly and 

183 associating with a :class:`.Session` using the 

184 :meth:`_query.Query.with_session` 

185 method. 

186 

187 """ 

188 

189 # elements that are in Core and can be cached in the same way 

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

191 _having_criteria: Tuple[ColumnElement[Any], ...] = () 

192 

193 _order_by_clauses: Tuple[ColumnElement[Any], ...] = () 

194 _group_by_clauses: Tuple[ColumnElement[Any], ...] = () 

195 _limit_clause: Optional[ColumnElement[Any]] = None 

196 _offset_clause: Optional[ColumnElement[Any]] = None 

197 

198 _distinct: bool = False 

199 _distinct_on: Tuple[ColumnElement[Any], ...] = () 

200 

201 _for_update_arg: Optional[ForUpdateArg] = None 

202 _correlate: Tuple[FromClause, ...] = () 

203 _auto_correlate: bool = True 

204 _from_obj: Tuple[FromClause, ...] = () 

205 _setup_joins: Tuple[_SetupJoinsElement, ...] = () 

206 

207 _label_style: SelectLabelStyle = SelectLabelStyle.LABEL_STYLE_LEGACY_ORM 

208 

209 _memoized_select_entities = () 

210 

211 _compile_options: Union[Type[CacheableOptions], CacheableOptions] = ( 

212 ORMCompileState.default_compile_options 

213 ) 

214 

215 _with_options: Tuple[ExecutableOption, ...] 

216 load_options = QueryContext.default_load_options + { 

217 "_legacy_uniquing": True 

218 } 

219 

220 _params: util.immutabledict[str, Any] = util.EMPTY_DICT 

221 

222 # local Query builder state, not needed for 

223 # compilation or execution 

224 _enable_assertions = True 

225 

226 _statement: Optional[ExecutableReturnsRows] = None 

227 

228 session: Session 

229 

230 dispatch: dispatcher[Query[_T]] 

231 

232 # mirrors that of ClauseElement, used to propagate the "orm" 

233 # plugin as well as the "subject" of the plugin, e.g. the mapper 

234 # we are querying against. 

235 @util.memoized_property 

236 def _propagate_attrs(self) -> _PropagateAttrsType: 

237 return util.EMPTY_DICT 

238 

239 def __init__( 

240 self, 

241 entities: Union[ 

242 _ColumnsClauseArgument[Any], Sequence[_ColumnsClauseArgument[Any]] 

243 ], 

244 session: Optional[Session] = None, 

245 ): 

246 """Construct a :class:`_query.Query` directly. 

247 

248 E.g.:: 

249 

250 q = Query([User, Address], session=some_session) 

251 

252 The above is equivalent to:: 

253 

254 q = some_session.query(User, Address) 

255 

256 :param entities: a sequence of entities and/or SQL expressions. 

257 

258 :param session: a :class:`.Session` with which the 

259 :class:`_query.Query` 

260 will be associated. Optional; a :class:`_query.Query` 

261 can be associated 

262 with a :class:`.Session` generatively via the 

263 :meth:`_query.Query.with_session` method as well. 

264 

265 .. seealso:: 

266 

267 :meth:`.Session.query` 

268 

269 :meth:`_query.Query.with_session` 

270 

271 """ 

272 

273 # session is usually present. There's one case in subqueryloader 

274 # where it stores a Query without a Session and also there are tests 

275 # for the query(Entity).with_session(session) API which is likely in 

276 # some old recipes, however these are legacy as select() can now be 

277 # used. 

278 self.session = session # type: ignore 

279 self._set_entities(entities) 

280 

281 def _set_propagate_attrs(self, values: Mapping[str, Any]) -> Self: 

282 self._propagate_attrs = util.immutabledict(values) 

283 return self 

284 

285 def _set_entities( 

286 self, 

287 entities: Union[ 

288 _ColumnsClauseArgument[Any], Iterable[_ColumnsClauseArgument[Any]] 

289 ], 

290 ) -> None: 

291 self._raw_columns = [ 

292 coercions.expect( 

293 roles.ColumnsClauseRole, 

294 ent, 

295 apply_propagate_attrs=self, 

296 post_inspect=True, 

297 ) 

298 for ent in util.to_list(entities) 

299 ] 

300 

301 @deprecated( 

302 "2.1.0", 

303 "The :meth:`.Query.tuples` method is deprecated, :class:`.Row` " 

304 "now behaves like a tuple and can unpack types directly.", 

305 ) 

306 def tuples(self: Query[_O]) -> Query[Tuple[_O]]: 

307 """return a tuple-typed form of this :class:`.Query`. 

308 

309 This method invokes the :meth:`.Query.only_return_tuples` 

310 method with a value of ``True``, which by itself ensures that this 

311 :class:`.Query` will always return :class:`.Row` objects, even 

312 if the query is made against a single entity. It then also 

313 at the typing level will return a "typed" query, if possible, 

314 that will type result rows as ``Tuple`` objects with typed 

315 elements. 

316 

317 This method can be compared to the :meth:`.Result.tuples` method, 

318 which returns "self", but from a typing perspective returns an object 

319 that will yield typed ``Tuple`` objects for results. Typing 

320 takes effect only if this :class:`.Query` object is a typed 

321 query object already. 

322 

323 .. versionadded:: 2.0 

324 

325 .. seealso:: 

326 

327 :ref:`change_10635` - describes a migration path from this 

328 workaround for SQLAlchemy 2.1. 

329 

330 :meth:`.Result.tuples` - v2 equivalent method. 

331 

332 """ 

333 return self.only_return_tuples(True) # type: ignore 

334 

335 def _entity_from_pre_ent_zero(self) -> Optional[_InternalEntityType[Any]]: 

336 if not self._raw_columns: 

337 return None 

338 

339 ent = self._raw_columns[0] 

340 

341 if "parententity" in ent._annotations: 

342 return ent._annotations["parententity"] # type: ignore 

343 elif "bundle" in ent._annotations: 

344 return ent._annotations["bundle"] # type: ignore 

345 else: 

346 # label, other SQL expression 

347 for element in visitors.iterate(ent): 

348 if "parententity" in element._annotations: 

349 return element._annotations["parententity"] # type: ignore # noqa: E501 

350 else: 

351 return None 

352 

353 def _only_full_mapper_zero(self, methname: str) -> Mapper[Any]: 

354 if ( 

355 len(self._raw_columns) != 1 

356 or "parententity" not in self._raw_columns[0]._annotations 

357 or not self._raw_columns[0].is_selectable 

358 ): 

359 raise sa_exc.InvalidRequestError( 

360 "%s() can only be used against " 

361 "a single mapped class." % methname 

362 ) 

363 

364 return self._raw_columns[0]._annotations["parententity"] # type: ignore # noqa: E501 

365 

366 def _set_select_from( 

367 self, obj: Iterable[_FromClauseArgument], set_base_alias: bool 

368 ) -> None: 

369 fa = [ 

370 coercions.expect( 

371 roles.StrictFromClauseRole, 

372 elem, 

373 allow_select=True, 

374 apply_propagate_attrs=self, 

375 ) 

376 for elem in obj 

377 ] 

378 

379 self._compile_options += {"_set_base_alias": set_base_alias} 

380 self._from_obj = tuple(fa) 

381 

382 @_generative 

383 def _set_lazyload_from(self, state: InstanceState[Any]) -> Self: 

384 self.load_options += {"_lazy_loaded_from": state} 

385 return self 

386 

387 def _get_condition(self) -> None: 

388 """used by legacy BakedQuery""" 

389 self._no_criterion_condition("get", order_by=False, distinct=False) 

390 

391 def _get_existing_condition(self) -> None: 

392 self._no_criterion_assertion("get", order_by=False, distinct=False) 

393 

394 def _no_criterion_assertion( 

395 self, meth: str, order_by: bool = True, distinct: bool = True 

396 ) -> None: 

397 if not self._enable_assertions: 

398 return 

399 if ( 

400 self._where_criteria 

401 or self._statement is not None 

402 or self._from_obj 

403 or self._setup_joins 

404 or self._limit_clause is not None 

405 or self._offset_clause is not None 

406 or self._group_by_clauses 

407 or (order_by and self._order_by_clauses) 

408 or (distinct and self._distinct) 

409 ): 

410 raise sa_exc.InvalidRequestError( 

411 "Query.%s() being called on a " 

412 "Query with existing criterion. " % meth 

413 ) 

414 

415 def _no_criterion_condition( 

416 self, meth: str, order_by: bool = True, distinct: bool = True 

417 ) -> None: 

418 self._no_criterion_assertion(meth, order_by, distinct) 

419 

420 self._from_obj = self._setup_joins = () 

421 if self._statement is not None: 

422 self._compile_options += {"_statement": None} 

423 self._where_criteria = () 

424 self._distinct = False 

425 

426 self._order_by_clauses = self._group_by_clauses = () 

427 

428 def _no_clauseelement_condition(self, meth: str) -> None: 

429 if not self._enable_assertions: 

430 return 

431 if self._order_by_clauses: 

432 raise sa_exc.InvalidRequestError( 

433 "Query.%s() being called on a " 

434 "Query with existing criterion. " % meth 

435 ) 

436 self._no_criterion_condition(meth) 

437 

438 def _no_statement_condition(self, meth: str) -> None: 

439 if not self._enable_assertions: 

440 return 

441 if self._statement is not None: 

442 raise sa_exc.InvalidRequestError( 

443 ( 

444 "Query.%s() being called on a Query with an existing full " 

445 "statement - can't apply criterion." 

446 ) 

447 % meth 

448 ) 

449 

450 def _no_limit_offset(self, meth: str) -> None: 

451 if not self._enable_assertions: 

452 return 

453 if self._limit_clause is not None or self._offset_clause is not None: 

454 raise sa_exc.InvalidRequestError( 

455 "Query.%s() being called on a Query which already has LIMIT " 

456 "or OFFSET applied. Call %s() before limit() or offset() " 

457 "are applied." % (meth, meth) 

458 ) 

459 

460 @property 

461 def _has_row_limiting_clause(self) -> bool: 

462 return ( 

463 self._limit_clause is not None or self._offset_clause is not None 

464 ) 

465 

466 def _get_options( 

467 self, 

468 populate_existing: Optional[bool] = None, 

469 version_check: Optional[bool] = None, 

470 only_load_props: Optional[Sequence[str]] = None, 

471 refresh_state: Optional[InstanceState[Any]] = None, 

472 identity_token: Optional[Any] = None, 

473 ) -> Self: 

474 load_options: Dict[str, Any] = {} 

475 compile_options: Dict[str, Any] = {} 

476 

477 if version_check: 

478 load_options["_version_check"] = version_check 

479 if populate_existing: 

480 load_options["_populate_existing"] = populate_existing 

481 if refresh_state: 

482 load_options["_refresh_state"] = refresh_state 

483 compile_options["_for_refresh_state"] = True 

484 if only_load_props: 

485 compile_options["_only_load_props"] = frozenset(only_load_props) 

486 if identity_token: 

487 load_options["_identity_token"] = identity_token 

488 

489 if load_options: 

490 self.load_options += load_options 

491 if compile_options: 

492 self._compile_options += compile_options 

493 

494 return self 

495 

496 def _clone(self, **kw: Any) -> Self: 

497 return self._generate() 

498 

499 def _get_select_statement_only(self) -> Select[_T]: 

500 if self._statement is not None: 

501 raise sa_exc.InvalidRequestError( 

502 "Can't call this method on a Query that uses from_statement()" 

503 ) 

504 return cast("Select[_T]", self.statement) 

505 

506 @property 

507 def statement(self) -> Union[Select[_T], FromStatement[_T]]: 

508 """The full SELECT statement represented by this Query. 

509 

510 The statement by default will not have disambiguating labels 

511 applied to the construct unless with_labels(True) is called 

512 first. 

513 

514 """ 

515 

516 # .statement can return the direct future.Select() construct here, as 

517 # long as we are not using subsequent adaption features that 

518 # are made against raw entities, e.g. from_self(), with_polymorphic(), 

519 # select_entity_from(). If these features are being used, then 

520 # the Select() we return will not have the correct .selected_columns 

521 # collection and will not embed in subsequent queries correctly. 

522 # We could find a way to make this collection "correct", however 

523 # this would not be too different from doing the full compile as 

524 # we are doing in any case, the Select() would still not have the 

525 # proper state for other attributes like whereclause, order_by, 

526 # and these features are all deprecated in any case. 

527 # 

528 # for these reasons, Query is not a Select, it remains an ORM 

529 # object for which __clause_element__() must be called in order for 

530 # it to provide a real expression object. 

531 # 

532 # from there, it starts to look much like Query itself won't be 

533 # passed into the execute process and won't generate its own cache 

534 # key; this will all occur in terms of the ORM-enabled Select. 

535 if not self._compile_options._set_base_alias: 

536 # if we don't have legacy top level aliasing features in use 

537 # then convert to a future select() directly 

538 stmt = self._statement_20(for_statement=True) 

539 else: 

540 stmt = self._compile_state(for_statement=True).statement 

541 

542 if self._params: 

543 stmt = stmt.params(self._params) 

544 

545 return stmt 

546 

547 def _final_statement( 

548 self, legacy_query_style: bool = True 

549 ) -> Select[Unpack[TupleAny]]: 

550 """Return the 'final' SELECT statement for this :class:`.Query`. 

551 

552 This is used by the testing suite only and is fairly inefficient. 

553 

554 This is the Core-only select() that will be rendered by a complete 

555 compilation of this query, and is what .statement used to return 

556 in 1.3. 

557 

558 

559 """ 

560 

561 q = self._clone() 

562 

563 return q._compile_state( 

564 use_legacy_query_style=legacy_query_style 

565 ).statement # type: ignore 

566 

567 def _statement_20( 

568 self, for_statement: bool = False, use_legacy_query_style: bool = True 

569 ) -> Union[Select[_T], FromStatement[_T]]: 

570 # TODO: this event needs to be deprecated, as it currently applies 

571 # only to ORM query and occurs at this spot that is now more 

572 # or less an artificial spot 

573 if self.dispatch.before_compile: 

574 for fn in self.dispatch.before_compile: 

575 new_query = fn(self) 

576 if new_query is not None and new_query is not self: 

577 self = new_query 

578 if not fn._bake_ok: # type: ignore 

579 self._compile_options += {"_bake_ok": False} 

580 

581 compile_options = self._compile_options 

582 compile_options += { 

583 "_for_statement": for_statement, 

584 "_use_legacy_query_style": use_legacy_query_style, 

585 } 

586 

587 stmt: Union[Select[_T], FromStatement[_T]] 

588 

589 if self._statement is not None: 

590 stmt = FromStatement(self._raw_columns, self._statement) 

591 stmt.__dict__.update( 

592 _with_options=self._with_options, 

593 _with_context_options=self._with_context_options, 

594 _compile_options=compile_options, 

595 _execution_options=self._execution_options, 

596 _propagate_attrs=self._propagate_attrs, 

597 ) 

598 else: 

599 # Query / select() internal attributes are 99% cross-compatible 

600 stmt = Select._create_raw_select(**self.__dict__) 

601 stmt.__dict__.update( 

602 _label_style=self._label_style, 

603 _compile_options=compile_options, 

604 _propagate_attrs=self._propagate_attrs, 

605 ) 

606 stmt.__dict__.pop("session", None) 

607 

608 # ensure the ORM context is used to compile the statement, even 

609 # if it has no ORM entities. This is so ORM-only things like 

610 # _legacy_joins are picked up that wouldn't be picked up by the 

611 # Core statement context 

612 if "compile_state_plugin" not in stmt._propagate_attrs: 

613 stmt._propagate_attrs = stmt._propagate_attrs.union( 

614 {"compile_state_plugin": "orm", "plugin_subject": None} 

615 ) 

616 

617 return stmt 

618 

619 def subquery( 

620 self, 

621 name: Optional[str] = None, 

622 with_labels: bool = False, 

623 reduce_columns: bool = False, 

624 ) -> Subquery: 

625 """Return the full SELECT statement represented by 

626 this :class:`_query.Query`, embedded within an 

627 :class:`_expression.Alias`. 

628 

629 Eager JOIN generation within the query is disabled. 

630 

631 .. seealso:: 

632 

633 :meth:`_sql.Select.subquery` - v2 comparable method. 

634 

635 :param name: string name to be assigned as the alias; 

636 this is passed through to :meth:`_expression.FromClause.alias`. 

637 If ``None``, a name will be deterministically generated 

638 at compile time. 

639 

640 :param with_labels: if True, :meth:`.with_labels` will be called 

641 on the :class:`_query.Query` first to apply table-qualified labels 

642 to all columns. 

643 

644 :param reduce_columns: if True, 

645 :meth:`_expression.Select.reduce_columns` will 

646 be called on the resulting :func:`_expression.select` construct, 

647 to remove same-named columns where one also refers to the other 

648 via foreign key or WHERE clause equivalence. 

649 

650 """ 

651 q = self.enable_eagerloads(False) 

652 if with_labels: 

653 q = q.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) 

654 

655 stmt = q._get_select_statement_only() 

656 

657 if TYPE_CHECKING: 

658 assert isinstance(stmt, Select) 

659 

660 if reduce_columns: 

661 stmt = stmt.reduce_columns() 

662 return stmt.subquery(name=name) 

663 

664 def cte( 

665 self, 

666 name: Optional[str] = None, 

667 recursive: bool = False, 

668 nesting: bool = False, 

669 ) -> CTE: 

670 r"""Return the full SELECT statement represented by this 

671 :class:`_query.Query` represented as a common table expression (CTE). 

672 

673 Parameters and usage are the same as those of the 

674 :meth:`_expression.SelectBase.cte` method; see that method for 

675 further details. 

676 

677 Here is the `PostgreSQL WITH 

678 RECURSIVE example 

679 <https://www.postgresql.org/docs/current/static/queries-with.html>`_. 

680 Note that, in this example, the ``included_parts`` cte and the 

681 ``incl_alias`` alias of it are Core selectables, which 

682 means the columns are accessed via the ``.c.`` attribute. The 

683 ``parts_alias`` object is an :func:`_orm.aliased` instance of the 

684 ``Part`` entity, so column-mapped attributes are available 

685 directly:: 

686 

687 from sqlalchemy.orm import aliased 

688 

689 class Part(Base): 

690 __tablename__ = 'part' 

691 part = Column(String, primary_key=True) 

692 sub_part = Column(String, primary_key=True) 

693 quantity = Column(Integer) 

694 

695 included_parts = session.query( 

696 Part.sub_part, 

697 Part.part, 

698 Part.quantity).\ 

699 filter(Part.part=="our part").\ 

700 cte(name="included_parts", recursive=True) 

701 

702 incl_alias = aliased(included_parts, name="pr") 

703 parts_alias = aliased(Part, name="p") 

704 included_parts = included_parts.union_all( 

705 session.query( 

706 parts_alias.sub_part, 

707 parts_alias.part, 

708 parts_alias.quantity).\ 

709 filter(parts_alias.part==incl_alias.c.sub_part) 

710 ) 

711 

712 q = session.query( 

713 included_parts.c.sub_part, 

714 func.sum(included_parts.c.quantity). 

715 label('total_quantity') 

716 ).\ 

717 group_by(included_parts.c.sub_part) 

718 

719 .. seealso:: 

720 

721 :meth:`_sql.Select.cte` - v2 equivalent method. 

722 

723 """ 

724 return ( 

725 self.enable_eagerloads(False) 

726 ._get_select_statement_only() 

727 .cte(name=name, recursive=recursive, nesting=nesting) 

728 ) 

729 

730 def label(self, name: Optional[str]) -> Label[Any]: 

731 """Return the full SELECT statement represented by this 

732 :class:`_query.Query`, converted 

733 to a scalar subquery with a label of the given name. 

734 

735 .. seealso:: 

736 

737 :meth:`_sql.Select.label` - v2 comparable method. 

738 

739 """ 

740 

741 return ( 

742 self.enable_eagerloads(False) 

743 ._get_select_statement_only() 

744 .label(name) 

745 ) 

746 

747 @overload 

748 def as_scalar( # type: ignore[overload-overlap] 

749 self: Query[Tuple[_MAYBE_ENTITY]], 

750 ) -> ScalarSelect[_MAYBE_ENTITY]: ... 

751 

752 @overload 

753 def as_scalar( 

754 self: Query[Tuple[_NOT_ENTITY]], 

755 ) -> ScalarSelect[_NOT_ENTITY]: ... 

756 

757 @overload 

758 def as_scalar(self) -> ScalarSelect[Any]: ... 

759 

760 @util.deprecated( 

761 "1.4", 

762 "The :meth:`_query.Query.as_scalar` method is deprecated and will be " 

763 "removed in a future release. Please refer to " 

764 ":meth:`_query.Query.scalar_subquery`.", 

765 ) 

766 def as_scalar(self) -> ScalarSelect[Any]: 

767 """Return the full SELECT statement represented by this 

768 :class:`_query.Query`, converted to a scalar subquery. 

769 

770 """ 

771 return self.scalar_subquery() 

772 

773 @overload 

774 def scalar_subquery( 

775 self: Query[Tuple[_MAYBE_ENTITY]], 

776 ) -> ScalarSelect[Any]: ... 

777 

778 @overload 

779 def scalar_subquery( 

780 self: Query[Tuple[_NOT_ENTITY]], 

781 ) -> ScalarSelect[_NOT_ENTITY]: ... 

782 

783 @overload 

784 def scalar_subquery(self) -> ScalarSelect[Any]: ... 

785 

786 def scalar_subquery(self) -> ScalarSelect[Any]: 

787 """Return the full SELECT statement represented by this 

788 :class:`_query.Query`, converted to a scalar subquery. 

789 

790 Analogous to 

791 :meth:`sqlalchemy.sql.expression.SelectBase.scalar_subquery`. 

792 

793 .. versionchanged:: 1.4 The :meth:`_query.Query.scalar_subquery` 

794 method replaces the :meth:`_query.Query.as_scalar` method. 

795 

796 .. seealso:: 

797 

798 :meth:`_sql.Select.scalar_subquery` - v2 comparable method. 

799 

800 """ 

801 

802 return ( 

803 self.enable_eagerloads(False) 

804 ._get_select_statement_only() 

805 .scalar_subquery() 

806 ) 

807 

808 @property 

809 def selectable(self) -> Union[Select[_T], FromStatement[_T]]: 

810 """Return the :class:`_expression.Select` object emitted by this 

811 :class:`_query.Query`. 

812 

813 Used for :func:`_sa.inspect` compatibility, this is equivalent to:: 

814 

815 query.enable_eagerloads(False).with_labels().statement 

816 

817 """ 

818 return self.__clause_element__() 

819 

820 def __clause_element__(self) -> Union[Select[_T], FromStatement[_T]]: 

821 return ( 

822 self._with_compile_options( 

823 _enable_eagerloads=False, _render_for_subquery=True 

824 ) 

825 .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) 

826 .statement 

827 ) 

828 

829 @overload 

830 def only_return_tuples( 

831 self: Query[_O], value: Literal[True] 

832 ) -> RowReturningQuery[_O]: ... 

833 

834 @overload 

835 def only_return_tuples( 

836 self: Query[_O], value: Literal[False] 

837 ) -> Query[_O]: ... 

838 

839 @_generative 

840 def only_return_tuples(self, value: bool) -> Query[Any]: 

841 """When set to True, the query results will always be a 

842 :class:`.Row` object. 

843 

844 This can change a query that normally returns a single entity 

845 as a scalar to return a :class:`.Row` result in all cases. 

846 

847 .. seealso:: 

848 

849 :meth:`.Query.tuples` - returns tuples, but also at the typing 

850 level will type results as ``Tuple``. 

851 

852 :meth:`_query.Query.is_single_entity` 

853 

854 :meth:`_engine.Result.tuples` - v2 comparable method. 

855 

856 """ 

857 self.load_options += dict(_only_return_tuples=value) 

858 return self 

859 

860 @property 

861 def is_single_entity(self) -> bool: 

862 """Indicates if this :class:`_query.Query` 

863 returns tuples or single entities. 

864 

865 Returns True if this query returns a single entity for each instance 

866 in its result list, and False if this query returns a tuple of entities 

867 for each result. 

868 

869 .. versionadded:: 1.3.11 

870 

871 .. seealso:: 

872 

873 :meth:`_query.Query.only_return_tuples` 

874 

875 """ 

876 return ( 

877 not self.load_options._only_return_tuples 

878 and len(self._raw_columns) == 1 

879 and "parententity" in self._raw_columns[0]._annotations 

880 and isinstance( 

881 self._raw_columns[0]._annotations["parententity"], 

882 ORMColumnsClauseRole, 

883 ) 

884 ) 

885 

886 @_generative 

887 def enable_eagerloads(self, value: bool) -> Self: 

888 """Control whether or not eager joins and subqueries are 

889 rendered. 

890 

891 When set to False, the returned Query will not render 

892 eager joins regardless of :func:`~sqlalchemy.orm.joinedload`, 

893 :func:`~sqlalchemy.orm.subqueryload` options 

894 or mapper-level ``lazy='joined'``/``lazy='subquery'`` 

895 configurations. 

896 

897 This is used primarily when nesting the Query's 

898 statement into a subquery or other 

899 selectable, or when using :meth:`_query.Query.yield_per`. 

900 

901 """ 

902 self._compile_options += {"_enable_eagerloads": value} 

903 return self 

904 

905 @_generative 

906 def _with_compile_options(self, **opt: Any) -> Self: 

907 self._compile_options += opt 

908 return self 

909 

910 @util.became_legacy_20( 

911 ":meth:`_orm.Query.with_labels` and :meth:`_orm.Query.apply_labels`", 

912 alternative="Use set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) " 

913 "instead.", 

914 ) 

915 def with_labels(self) -> Self: 

916 return self.set_label_style( 

917 SelectLabelStyle.LABEL_STYLE_TABLENAME_PLUS_COL 

918 ) 

919 

920 apply_labels = with_labels 

921 

922 @property 

923 def get_label_style(self) -> SelectLabelStyle: 

924 """ 

925 Retrieve the current label style. 

926 

927 .. versionadded:: 1.4 

928 

929 .. seealso:: 

930 

931 :meth:`_sql.Select.get_label_style` - v2 equivalent method. 

932 

933 """ 

934 return self._label_style 

935 

936 def set_label_style(self, style: SelectLabelStyle) -> Self: 

937 """Apply column labels to the return value of Query.statement. 

938 

939 Indicates that this Query's `statement` accessor should return 

940 a SELECT statement that applies labels to all columns in the 

941 form <tablename>_<columnname>; this is commonly used to 

942 disambiguate columns from multiple tables which have the same 

943 name. 

944 

945 When the `Query` actually issues SQL to load rows, it always 

946 uses column labeling. 

947 

948 .. note:: The :meth:`_query.Query.set_label_style` method *only* applies 

949 the output of :attr:`_query.Query.statement`, and *not* to any of 

950 the result-row invoking systems of :class:`_query.Query` itself, 

951 e.g. 

952 :meth:`_query.Query.first`, :meth:`_query.Query.all`, etc. 

953 To execute 

954 a query using :meth:`_query.Query.set_label_style`, invoke the 

955 :attr:`_query.Query.statement` using :meth:`.Session.execute`:: 

956 

957 result = session.execute( 

958 query 

959 .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) 

960 .statement 

961 ) 

962 

963 .. versionadded:: 1.4 

964 

965 

966 .. seealso:: 

967 

968 :meth:`_sql.Select.set_label_style` - v2 equivalent method. 

969 

970 """ # noqa 

971 if self._label_style is not style: 

972 self = self._generate() 

973 self._label_style = style 

974 return self 

975 

976 @_generative 

977 def enable_assertions(self, value: bool) -> Self: 

978 """Control whether assertions are generated. 

979 

980 When set to False, the returned Query will 

981 not assert its state before certain operations, 

982 including that LIMIT/OFFSET has not been applied 

983 when filter() is called, no criterion exists 

984 when get() is called, and no "from_statement()" 

985 exists when filter()/order_by()/group_by() etc. 

986 is called. This more permissive mode is used by 

987 custom Query subclasses to specify criterion or 

988 other modifiers outside of the usual usage patterns. 

989 

990 Care should be taken to ensure that the usage 

991 pattern is even possible. A statement applied 

992 by from_statement() will override any criterion 

993 set by filter() or order_by(), for example. 

994 

995 """ 

996 self._enable_assertions = value 

997 return self 

998 

999 @property 

1000 def whereclause(self) -> Optional[ColumnElement[bool]]: 

1001 """A readonly attribute which returns the current WHERE criterion for 

1002 this Query. 

1003 

1004 This returned value is a SQL expression construct, or ``None`` if no 

1005 criterion has been established. 

1006 

1007 .. seealso:: 

1008 

1009 :attr:`_sql.Select.whereclause` - v2 equivalent property. 

1010 

1011 """ 

1012 return BooleanClauseList._construct_for_whereclause( 

1013 self._where_criteria 

1014 ) 

1015 

1016 @_generative 

1017 def _with_current_path(self, path: PathRegistry) -> Self: 

1018 """indicate that this query applies to objects loaded 

1019 within a certain path. 

1020 

1021 Used by deferred loaders (see strategies.py) which transfer 

1022 query options from an originating query to a newly generated 

1023 query intended for the deferred load. 

1024 

1025 """ 

1026 self._compile_options += {"_current_path": path} 

1027 return self 

1028 

1029 @_generative 

1030 def yield_per(self, count: int) -> Self: 

1031 r"""Yield only ``count`` rows at a time. 

1032 

1033 The purpose of this method is when fetching very large result sets 

1034 (> 10K rows), to batch results in sub-collections and yield them 

1035 out partially, so that the Python interpreter doesn't need to declare 

1036 very large areas of memory which is both time consuming and leads 

1037 to excessive memory use. The performance from fetching hundreds of 

1038 thousands of rows can often double when a suitable yield-per setting 

1039 (e.g. approximately 1000) is used, even with DBAPIs that buffer 

1040 rows (which are most). 

1041 

1042 As of SQLAlchemy 1.4, the :meth:`_orm.Query.yield_per` method is 

1043 equivalent to using the ``yield_per`` execution option at the ORM 

1044 level. See the section :ref:`orm_queryguide_yield_per` for further 

1045 background on this option. 

1046 

1047 .. seealso:: 

1048 

1049 :ref:`orm_queryguide_yield_per` 

1050 

1051 """ 

1052 self.load_options += {"_yield_per": count} 

1053 return self 

1054 

1055 @util.became_legacy_20( 

1056 ":meth:`_orm.Query.get`", 

1057 alternative="The method is now available as :meth:`_orm.Session.get`", 

1058 ) 

1059 def get(self, ident: _PKIdentityArgument) -> Optional[Any]: 

1060 """Return an instance based on the given primary key identifier, 

1061 or ``None`` if not found. 

1062 

1063 E.g.:: 

1064 

1065 my_user = session.query(User).get(5) 

1066 

1067 some_object = session.query(VersionedFoo).get((5, 10)) 

1068 

1069 some_object = session.query(VersionedFoo).get( 

1070 {"id": 5, "version_id": 10}) 

1071 

1072 :meth:`_query.Query.get` is special in that it provides direct 

1073 access to the identity map of the owning :class:`.Session`. 

1074 If the given primary key identifier is present 

1075 in the local identity map, the object is returned 

1076 directly from this collection and no SQL is emitted, 

1077 unless the object has been marked fully expired. 

1078 If not present, 

1079 a SELECT is performed in order to locate the object. 

1080 

1081 :meth:`_query.Query.get` also will perform a check if 

1082 the object is present in the identity map and 

1083 marked as expired - a SELECT 

1084 is emitted to refresh the object as well as to 

1085 ensure that the row is still present. 

1086 If not, :class:`~sqlalchemy.orm.exc.ObjectDeletedError` is raised. 

1087 

1088 :meth:`_query.Query.get` is only used to return a single 

1089 mapped instance, not multiple instances or 

1090 individual column constructs, and strictly 

1091 on a single primary key value. The originating 

1092 :class:`_query.Query` must be constructed in this way, 

1093 i.e. against a single mapped entity, 

1094 with no additional filtering criterion. Loading 

1095 options via :meth:`_query.Query.options` may be applied 

1096 however, and will be used if the object is not 

1097 yet locally present. 

1098 

1099 :param ident: A scalar, tuple, or dictionary representing the 

1100 primary key. For a composite (e.g. multiple column) primary key, 

1101 a tuple or dictionary should be passed. 

1102 

1103 For a single-column primary key, the scalar calling form is typically 

1104 the most expedient. If the primary key of a row is the value "5", 

1105 the call looks like:: 

1106 

1107 my_object = query.get(5) 

1108 

1109 The tuple form contains primary key values typically in 

1110 the order in which they correspond to the mapped 

1111 :class:`_schema.Table` 

1112 object's primary key columns, or if the 

1113 :paramref:`_orm.Mapper.primary_key` configuration parameter were 

1114 used, in 

1115 the order used for that parameter. For example, if the primary key 

1116 of a row is represented by the integer 

1117 digits "5, 10" the call would look like:: 

1118 

1119 my_object = query.get((5, 10)) 

1120 

1121 The dictionary form should include as keys the mapped attribute names 

1122 corresponding to each element of the primary key. If the mapped class 

1123 has the attributes ``id``, ``version_id`` as the attributes which 

1124 store the object's primary key value, the call would look like:: 

1125 

1126 my_object = query.get({"id": 5, "version_id": 10}) 

1127 

1128 .. versionadded:: 1.3 the :meth:`_query.Query.get` 

1129 method now optionally 

1130 accepts a dictionary of attribute names to values in order to 

1131 indicate a primary key identifier. 

1132 

1133 

1134 :return: The object instance, or ``None``. 

1135 

1136 """ 

1137 self._no_criterion_assertion("get", order_by=False, distinct=False) 

1138 

1139 # we still implement _get_impl() so that baked query can override 

1140 # it 

1141 return self._get_impl(ident, loading.load_on_pk_identity) 

1142 

1143 def _get_impl( 

1144 self, 

1145 primary_key_identity: _PKIdentityArgument, 

1146 db_load_fn: Callable[..., Any], 

1147 identity_token: Optional[Any] = None, 

1148 ) -> Optional[Any]: 

1149 mapper = self._only_full_mapper_zero("get") 

1150 return self.session._get_impl( 

1151 mapper, 

1152 primary_key_identity, 

1153 db_load_fn, 

1154 populate_existing=self.load_options._populate_existing, 

1155 with_for_update=self._for_update_arg, 

1156 options=self._with_options, 

1157 identity_token=identity_token, 

1158 execution_options=self._execution_options, 

1159 ) 

1160 

1161 @property 

1162 def lazy_loaded_from(self) -> Optional[InstanceState[Any]]: 

1163 """An :class:`.InstanceState` that is using this :class:`_query.Query` 

1164 for a lazy load operation. 

1165 

1166 .. deprecated:: 1.4 This attribute should be viewed via the 

1167 :attr:`.ORMExecuteState.lazy_loaded_from` attribute, within 

1168 the context of the :meth:`.SessionEvents.do_orm_execute` 

1169 event. 

1170 

1171 .. seealso:: 

1172 

1173 :attr:`.ORMExecuteState.lazy_loaded_from` 

1174 

1175 """ 

1176 return self.load_options._lazy_loaded_from # type: ignore 

1177 

1178 @property 

1179 def _current_path(self) -> PathRegistry: 

1180 return self._compile_options._current_path # type: ignore 

1181 

1182 @_generative 

1183 def correlate( 

1184 self, 

1185 *fromclauses: Union[Literal[None, False], _FromClauseArgument], 

1186 ) -> Self: 

1187 """Return a :class:`.Query` construct which will correlate the given 

1188 FROM clauses to that of an enclosing :class:`.Query` or 

1189 :func:`~.expression.select`. 

1190 

1191 The method here accepts mapped classes, :func:`.aliased` constructs, 

1192 and :class:`_orm.Mapper` constructs as arguments, which are resolved 

1193 into expression constructs, in addition to appropriate expression 

1194 constructs. 

1195 

1196 The correlation arguments are ultimately passed to 

1197 :meth:`_expression.Select.correlate` 

1198 after coercion to expression constructs. 

1199 

1200 The correlation arguments take effect in such cases 

1201 as when :meth:`_query.Query.from_self` is used, or when 

1202 a subquery as returned by :meth:`_query.Query.subquery` is 

1203 embedded in another :func:`_expression.select` construct. 

1204 

1205 .. seealso:: 

1206 

1207 :meth:`_sql.Select.correlate` - v2 equivalent method. 

1208 

1209 """ 

1210 

1211 self._auto_correlate = False 

1212 if fromclauses and fromclauses[0] in {None, False}: 

1213 self._correlate = () 

1214 else: 

1215 self._correlate = self._correlate + tuple( 

1216 coercions.expect(roles.FromClauseRole, f) for f in fromclauses 

1217 ) 

1218 return self 

1219 

1220 @_generative 

1221 def autoflush(self, setting: bool) -> Self: 

1222 """Return a Query with a specific 'autoflush' setting. 

1223 

1224 As of SQLAlchemy 1.4, the :meth:`_orm.Query.autoflush` method 

1225 is equivalent to using the ``autoflush`` execution option at the 

1226 ORM level. See the section :ref:`orm_queryguide_autoflush` for 

1227 further background on this option. 

1228 

1229 """ 

1230 self.load_options += {"_autoflush": setting} 

1231 return self 

1232 

1233 @_generative 

1234 def populate_existing(self) -> Self: 

1235 """Return a :class:`_query.Query` 

1236 that will expire and refresh all instances 

1237 as they are loaded, or reused from the current :class:`.Session`. 

1238 

1239 As of SQLAlchemy 1.4, the :meth:`_orm.Query.populate_existing` method 

1240 is equivalent to using the ``populate_existing`` execution option at 

1241 the ORM level. See the section :ref:`orm_queryguide_populate_existing` 

1242 for further background on this option. 

1243 

1244 """ 

1245 self.load_options += {"_populate_existing": True} 

1246 return self 

1247 

1248 @_generative 

1249 def _with_invoke_all_eagers(self, value: bool) -> Self: 

1250 """Set the 'invoke all eagers' flag which causes joined- and 

1251 subquery loaders to traverse into already-loaded related objects 

1252 and collections. 

1253 

1254 Default is that of :attr:`_query.Query._invoke_all_eagers`. 

1255 

1256 """ 

1257 self.load_options += {"_invoke_all_eagers": value} 

1258 return self 

1259 

1260 @util.became_legacy_20( 

1261 ":meth:`_orm.Query.with_parent`", 

1262 alternative="Use the :func:`_orm.with_parent` standalone construct.", 

1263 ) 

1264 @util.preload_module("sqlalchemy.orm.relationships") 

1265 def with_parent( 

1266 self, 

1267 instance: object, 

1268 property: Optional[ # noqa: A002 

1269 attributes.QueryableAttribute[Any] 

1270 ] = None, 

1271 from_entity: Optional[_ExternalEntityType[Any]] = None, 

1272 ) -> Self: 

1273 """Add filtering criterion that relates the given instance 

1274 to a child object or collection, using its attribute state 

1275 as well as an established :func:`_orm.relationship()` 

1276 configuration. 

1277 

1278 The method uses the :func:`.with_parent` function to generate 

1279 the clause, the result of which is passed to 

1280 :meth:`_query.Query.filter`. 

1281 

1282 Parameters are the same as :func:`.with_parent`, with the exception 

1283 that the given property can be None, in which case a search is 

1284 performed against this :class:`_query.Query` object's target mapper. 

1285 

1286 :param instance: 

1287 An instance which has some :func:`_orm.relationship`. 

1288 

1289 :param property: 

1290 Class bound attribute which indicates 

1291 what relationship from the instance should be used to reconcile the 

1292 parent/child relationship. 

1293 

1294 :param from_entity: 

1295 Entity in which to consider as the left side. This defaults to the 

1296 "zero" entity of the :class:`_query.Query` itself. 

1297 

1298 """ 

1299 relationships = util.preloaded.orm_relationships 

1300 

1301 if from_entity: 

1302 entity_zero = inspect(from_entity) 

1303 else: 

1304 entity_zero = _legacy_filter_by_entity_zero(self) 

1305 if property is None: 

1306 # TODO: deprecate, property has to be supplied 

1307 mapper = object_mapper(instance) 

1308 

1309 for prop in mapper.iterate_properties: 

1310 if ( 

1311 isinstance(prop, relationships.RelationshipProperty) 

1312 and prop.mapper is entity_zero.mapper # type: ignore 

1313 ): 

1314 property = prop # type: ignore # noqa: A001 

1315 break 

1316 else: 

1317 raise sa_exc.InvalidRequestError( 

1318 "Could not locate a property which relates instances " 

1319 "of class '%s' to instances of class '%s'" 

1320 % ( 

1321 entity_zero.mapper.class_.__name__, # type: ignore 

1322 instance.__class__.__name__, 

1323 ) 

1324 ) 

1325 

1326 return self.filter( 

1327 with_parent( 

1328 instance, 

1329 property, # type: ignore 

1330 entity_zero.entity, # type: ignore 

1331 ) 

1332 ) 

1333 

1334 @_generative 

1335 def add_entity( 

1336 self, 

1337 entity: _EntityType[Any], 

1338 alias: Optional[Union[Alias, Subquery]] = None, 

1339 ) -> Query[Any]: 

1340 """add a mapped entity to the list of result columns 

1341 to be returned. 

1342 

1343 .. seealso:: 

1344 

1345 :meth:`_sql.Select.add_columns` - v2 comparable method. 

1346 """ 

1347 

1348 if alias is not None: 

1349 # TODO: deprecate 

1350 entity = AliasedClass(entity, alias) 

1351 

1352 self._raw_columns = list(self._raw_columns) 

1353 

1354 self._raw_columns.append( 

1355 coercions.expect( 

1356 roles.ColumnsClauseRole, entity, apply_propagate_attrs=self 

1357 ) 

1358 ) 

1359 return self 

1360 

1361 @_generative 

1362 def with_session(self, session: Session) -> Self: 

1363 """Return a :class:`_query.Query` that will use the given 

1364 :class:`.Session`. 

1365 

1366 While the :class:`_query.Query` 

1367 object is normally instantiated using the 

1368 :meth:`.Session.query` method, it is legal to build the 

1369 :class:`_query.Query` 

1370 directly without necessarily using a :class:`.Session`. Such a 

1371 :class:`_query.Query` object, or any :class:`_query.Query` 

1372 already associated 

1373 with a different :class:`.Session`, can produce a new 

1374 :class:`_query.Query` 

1375 object associated with a target session using this method:: 

1376 

1377 from sqlalchemy.orm import Query 

1378 

1379 query = Query([MyClass]).filter(MyClass.id == 5) 

1380 

1381 result = query.with_session(my_session).one() 

1382 

1383 """ 

1384 

1385 self.session = session 

1386 return self 

1387 

1388 def _legacy_from_self( 

1389 self, *entities: _ColumnsClauseArgument[Any] 

1390 ) -> Self: 

1391 # used for query.count() as well as for the same 

1392 # function in BakedQuery, as well as some old tests in test_baked.py. 

1393 

1394 fromclause = ( 

1395 self.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) 

1396 .correlate(None) 

1397 .subquery() 

1398 ._anonymous_fromclause() 

1399 ) 

1400 

1401 q = self._from_selectable(fromclause) 

1402 

1403 if entities: 

1404 q._set_entities(entities) 

1405 return q 

1406 

1407 @_generative 

1408 def _set_enable_single_crit(self, val: bool) -> Self: 

1409 self._compile_options += {"_enable_single_crit": val} 

1410 return self 

1411 

1412 @_generative 

1413 def _from_selectable( 

1414 self, fromclause: FromClause, set_entity_from: bool = True 

1415 ) -> Self: 

1416 for attr in ( 

1417 "_where_criteria", 

1418 "_order_by_clauses", 

1419 "_group_by_clauses", 

1420 "_limit_clause", 

1421 "_offset_clause", 

1422 "_last_joined_entity", 

1423 "_setup_joins", 

1424 "_memoized_select_entities", 

1425 "_distinct", 

1426 "_distinct_on", 

1427 "_having_criteria", 

1428 "_prefixes", 

1429 "_suffixes", 

1430 ): 

1431 self.__dict__.pop(attr, None) 

1432 self._set_select_from([fromclause], set_entity_from) 

1433 self._compile_options += { 

1434 "_enable_single_crit": False, 

1435 } 

1436 

1437 return self 

1438 

1439 @util.deprecated( 

1440 "1.4", 

1441 ":meth:`_query.Query.values` " 

1442 "is deprecated and will be removed in a " 

1443 "future release. Please use :meth:`_query.Query.with_entities`", 

1444 ) 

1445 def values(self, *columns: _ColumnsClauseArgument[Any]) -> Iterable[Any]: 

1446 """Return an iterator yielding result tuples corresponding 

1447 to the given list of columns 

1448 

1449 """ 

1450 return self._values_no_warn(*columns) 

1451 

1452 _values = values 

1453 

1454 def _values_no_warn( 

1455 self, *columns: _ColumnsClauseArgument[Any] 

1456 ) -> Iterable[Any]: 

1457 if not columns: 

1458 return iter(()) 

1459 q = self._clone().enable_eagerloads(False) 

1460 q._set_entities(columns) 

1461 if not q.load_options._yield_per: 

1462 q.load_options += {"_yield_per": 10} 

1463 return iter(q) 

1464 

1465 @util.deprecated( 

1466 "1.4", 

1467 ":meth:`_query.Query.value` " 

1468 "is deprecated and will be removed in a " 

1469 "future release. Please use :meth:`_query.Query.with_entities` " 

1470 "in combination with :meth:`_query.Query.scalar`", 

1471 ) 

1472 def value(self, column: _ColumnExpressionArgument[Any]) -> Any: 

1473 """Return a scalar result corresponding to the given 

1474 column expression. 

1475 

1476 """ 

1477 try: 

1478 return next(self._values_no_warn(column))[0] # type: ignore 

1479 except StopIteration: 

1480 return None 

1481 

1482 @overload 

1483 def with_entities(self, _entity: _EntityType[_O]) -> Query[_O]: ... 

1484 

1485 @overload 

1486 def with_entities( 

1487 self, 

1488 _colexpr: roles.TypedColumnsClauseRole[_T], 

1489 ) -> RowReturningQuery[Tuple[_T]]: ... 

1490 

1491 # START OVERLOADED FUNCTIONS self.with_entities RowReturningQuery 2-8 

1492 

1493 # code within this block is **programmatically, 

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

1495 

1496 @overload 

1497 def with_entities( 

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

1499 ) -> RowReturningQuery[_T0, _T1]: ... 

1500 

1501 @overload 

1502 def with_entities( 

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

1504 ) -> RowReturningQuery[_T0, _T1, _T2]: ... 

1505 

1506 @overload 

1507 def with_entities( 

1508 self, 

1509 __ent0: _TCCA[_T0], 

1510 __ent1: _TCCA[_T1], 

1511 __ent2: _TCCA[_T2], 

1512 __ent3: _TCCA[_T3], 

1513 /, 

1514 ) -> RowReturningQuery[_T0, _T1, _T2, _T3]: ... 

1515 

1516 @overload 

1517 def with_entities( 

1518 self, 

1519 __ent0: _TCCA[_T0], 

1520 __ent1: _TCCA[_T1], 

1521 __ent2: _TCCA[_T2], 

1522 __ent3: _TCCA[_T3], 

1523 __ent4: _TCCA[_T4], 

1524 /, 

1525 ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4]: ... 

1526 

1527 @overload 

1528 def with_entities( 

1529 self, 

1530 __ent0: _TCCA[_T0], 

1531 __ent1: _TCCA[_T1], 

1532 __ent2: _TCCA[_T2], 

1533 __ent3: _TCCA[_T3], 

1534 __ent4: _TCCA[_T4], 

1535 __ent5: _TCCA[_T5], 

1536 /, 

1537 ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4, _T5]: ... 

1538 

1539 @overload 

1540 def with_entities( 

1541 self, 

1542 __ent0: _TCCA[_T0], 

1543 __ent1: _TCCA[_T1], 

1544 __ent2: _TCCA[_T2], 

1545 __ent3: _TCCA[_T3], 

1546 __ent4: _TCCA[_T4], 

1547 __ent5: _TCCA[_T5], 

1548 __ent6: _TCCA[_T6], 

1549 /, 

1550 ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4, _T5, _T6]: ... 

1551 

1552 @overload 

1553 def with_entities( 

1554 self, 

1555 __ent0: _TCCA[_T0], 

1556 __ent1: _TCCA[_T1], 

1557 __ent2: _TCCA[_T2], 

1558 __ent3: _TCCA[_T3], 

1559 __ent4: _TCCA[_T4], 

1560 __ent5: _TCCA[_T5], 

1561 __ent6: _TCCA[_T6], 

1562 __ent7: _TCCA[_T7], 

1563 /, 

1564 *entities: _ColumnsClauseArgument[Any], 

1565 ) -> RowReturningQuery[ 

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

1567 ]: ... 

1568 

1569 # END OVERLOADED FUNCTIONS self.with_entities 

1570 

1571 @overload 

1572 def with_entities( 

1573 self, *entities: _ColumnsClauseArgument[Any] 

1574 ) -> Query[Any]: ... 

1575 

1576 @_generative 

1577 def with_entities( 

1578 self, *entities: _ColumnsClauseArgument[Any], **__kw: Any 

1579 ) -> Query[Any]: 

1580 r"""Return a new :class:`_query.Query` 

1581 replacing the SELECT list with the 

1582 given entities. 

1583 

1584 e.g.:: 

1585 

1586 # Users, filtered on some arbitrary criterion 

1587 # and then ordered by related email address 

1588 q = session.query(User).\ 

1589 join(User.address).\ 

1590 filter(User.name.like('%ed%')).\ 

1591 order_by(Address.email) 

1592 

1593 # given *only* User.id==5, Address.email, and 'q', what 

1594 # would the *next* User in the result be ? 

1595 subq = q.with_entities(Address.email).\ 

1596 order_by(None).\ 

1597 filter(User.id==5).\ 

1598 subquery() 

1599 q = q.join((subq, subq.c.email < Address.email)).\ 

1600 limit(1) 

1601 

1602 .. seealso:: 

1603 

1604 :meth:`_sql.Select.with_only_columns` - v2 comparable method. 

1605 """ 

1606 if __kw: 

1607 raise _no_kw() 

1608 

1609 # Query has all the same fields as Select for this operation 

1610 # this could in theory be based on a protocol but not sure if it's 

1611 # worth it 

1612 _MemoizedSelectEntities._generate_for_statement(self) # type: ignore 

1613 self._set_entities(entities) 

1614 return self 

1615 

1616 @_generative 

1617 def add_columns( 

1618 self, *column: _ColumnExpressionArgument[Any] 

1619 ) -> Query[Any]: 

1620 """Add one or more column expressions to the list 

1621 of result columns to be returned. 

1622 

1623 .. seealso:: 

1624 

1625 :meth:`_sql.Select.add_columns` - v2 comparable method. 

1626 """ 

1627 

1628 self._raw_columns = list(self._raw_columns) 

1629 

1630 self._raw_columns.extend( 

1631 coercions.expect( 

1632 roles.ColumnsClauseRole, 

1633 c, 

1634 apply_propagate_attrs=self, 

1635 post_inspect=True, 

1636 ) 

1637 for c in column 

1638 ) 

1639 return self 

1640 

1641 @util.deprecated( 

1642 "1.4", 

1643 ":meth:`_query.Query.add_column` " 

1644 "is deprecated and will be removed in a " 

1645 "future release. Please use :meth:`_query.Query.add_columns`", 

1646 ) 

1647 def add_column(self, column: _ColumnExpressionArgument[Any]) -> Query[Any]: 

1648 """Add a column expression to the list of result columns to be 

1649 returned. 

1650 

1651 """ 

1652 return self.add_columns(column) 

1653 

1654 @_generative 

1655 def options(self, *args: ExecutableOption) -> Self: 

1656 """Return a new :class:`_query.Query` object, 

1657 applying the given list of 

1658 mapper options. 

1659 

1660 Most supplied options regard changing how column- and 

1661 relationship-mapped attributes are loaded. 

1662 

1663 .. seealso:: 

1664 

1665 :ref:`loading_columns` 

1666 

1667 :ref:`relationship_loader_options` 

1668 

1669 """ 

1670 

1671 opts = tuple(util.flatten_iterator(args)) 

1672 if self._compile_options._current_path: 

1673 # opting for lower method overhead for the checks 

1674 for opt in opts: 

1675 if not opt._is_core and opt._is_legacy_option: # type: ignore 

1676 opt.process_query_conditionally(self) # type: ignore 

1677 else: 

1678 for opt in opts: 

1679 if not opt._is_core and opt._is_legacy_option: # type: ignore 

1680 opt.process_query(self) # type: ignore 

1681 

1682 self._with_options += opts 

1683 return self 

1684 

1685 def with_transformation( 

1686 self, fn: Callable[[Query[Any]], Query[Any]] 

1687 ) -> Query[Any]: 

1688 """Return a new :class:`_query.Query` object transformed by 

1689 the given function. 

1690 

1691 E.g.:: 

1692 

1693 def filter_something(criterion): 

1694 def transform(q): 

1695 return q.filter(criterion) 

1696 return transform 

1697 

1698 q = q.with_transformation(filter_something(x==5)) 

1699 

1700 This allows ad-hoc recipes to be created for :class:`_query.Query` 

1701 objects. 

1702 

1703 """ 

1704 return fn(self) 

1705 

1706 def get_execution_options(self) -> _ImmutableExecuteOptions: 

1707 """Get the non-SQL options which will take effect during execution. 

1708 

1709 .. versionadded:: 1.3 

1710 

1711 .. seealso:: 

1712 

1713 :meth:`_query.Query.execution_options` 

1714 

1715 :meth:`_sql.Select.get_execution_options` - v2 comparable method. 

1716 

1717 """ 

1718 return self._execution_options 

1719 

1720 @overload 

1721 def execution_options( 

1722 self, 

1723 *, 

1724 compiled_cache: Optional[CompiledCacheType] = ..., 

1725 logging_token: str = ..., 

1726 isolation_level: IsolationLevel = ..., 

1727 no_parameters: bool = False, 

1728 stream_results: bool = False, 

1729 max_row_buffer: int = ..., 

1730 yield_per: int = ..., 

1731 driver_column_names: bool = ..., 

1732 insertmanyvalues_page_size: int = ..., 

1733 schema_translate_map: Optional[SchemaTranslateMapType] = ..., 

1734 populate_existing: bool = False, 

1735 autoflush: bool = False, 

1736 preserve_rowcount: bool = False, 

1737 **opt: Any, 

1738 ) -> Self: ... 

1739 

1740 @overload 

1741 def execution_options(self, **opt: Any) -> Self: ... 

1742 

1743 @_generative 

1744 def execution_options(self, **kwargs: Any) -> Self: 

1745 """Set non-SQL options which take effect during execution. 

1746 

1747 Options allowed here include all of those accepted by 

1748 :meth:`_engine.Connection.execution_options`, as well as a series 

1749 of ORM specific options: 

1750 

1751 ``populate_existing=True`` - equivalent to using 

1752 :meth:`_orm.Query.populate_existing` 

1753 

1754 ``autoflush=True|False`` - equivalent to using 

1755 :meth:`_orm.Query.autoflush` 

1756 

1757 ``yield_per=<value>`` - equivalent to using 

1758 :meth:`_orm.Query.yield_per` 

1759 

1760 Note that the ``stream_results`` execution option is enabled 

1761 automatically if the :meth:`~sqlalchemy.orm.query.Query.yield_per()` 

1762 method or execution option is used. 

1763 

1764 .. versionadded:: 1.4 - added ORM options to 

1765 :meth:`_orm.Query.execution_options` 

1766 

1767 The execution options may also be specified on a per execution basis 

1768 when using :term:`2.0 style` queries via the 

1769 :paramref:`_orm.Session.execution_options` parameter. 

1770 

1771 .. warning:: The 

1772 :paramref:`_engine.Connection.execution_options.stream_results` 

1773 parameter should not be used at the level of individual ORM 

1774 statement executions, as the :class:`_orm.Session` will not track 

1775 objects from different schema translate maps within a single 

1776 session. For multiple schema translate maps within the scope of a 

1777 single :class:`_orm.Session`, see :ref:`examples_sharding`. 

1778 

1779 

1780 .. seealso:: 

1781 

1782 :ref:`engine_stream_results` 

1783 

1784 :meth:`_query.Query.get_execution_options` 

1785 

1786 :meth:`_sql.Select.execution_options` - v2 equivalent method. 

1787 

1788 """ 

1789 self._execution_options = self._execution_options.union(kwargs) 

1790 return self 

1791 

1792 @_generative 

1793 def with_for_update( 

1794 self, 

1795 *, 

1796 nowait: bool = False, 

1797 read: bool = False, 

1798 of: Optional[_ForUpdateOfArgument] = None, 

1799 skip_locked: bool = False, 

1800 key_share: bool = False, 

1801 ) -> Self: 

1802 """return a new :class:`_query.Query` 

1803 with the specified options for the 

1804 ``FOR UPDATE`` clause. 

1805 

1806 The behavior of this method is identical to that of 

1807 :meth:`_expression.GenerativeSelect.with_for_update`. 

1808 When called with no arguments, 

1809 the resulting ``SELECT`` statement will have a ``FOR UPDATE`` clause 

1810 appended. When additional arguments are specified, backend-specific 

1811 options such as ``FOR UPDATE NOWAIT`` or ``LOCK IN SHARE MODE`` 

1812 can take effect. 

1813 

1814 E.g.:: 

1815 

1816 q = sess.query(User).populate_existing().with_for_update(nowait=True, of=User) 

1817 

1818 The above query on a PostgreSQL backend will render like:: 

1819 

1820 SELECT users.id AS users_id FROM users FOR UPDATE OF users NOWAIT 

1821 

1822 .. warning:: 

1823 

1824 Using ``with_for_update`` in the context of eager loading 

1825 relationships is not officially supported or recommended by 

1826 SQLAlchemy and may not work with certain queries on various 

1827 database backends. When ``with_for_update`` is successfully used 

1828 with a query that involves :func:`_orm.joinedload`, SQLAlchemy will 

1829 attempt to emit SQL that locks all involved tables. 

1830 

1831 .. note:: It is generally a good idea to combine the use of the 

1832 :meth:`_orm.Query.populate_existing` method when using the 

1833 :meth:`_orm.Query.with_for_update` method. The purpose of 

1834 :meth:`_orm.Query.populate_existing` is to force all the data read 

1835 from the SELECT to be populated into the ORM objects returned, 

1836 even if these objects are already in the :term:`identity map`. 

1837 

1838 .. seealso:: 

1839 

1840 :meth:`_expression.GenerativeSelect.with_for_update` 

1841 - Core level method with 

1842 full argument and behavioral description. 

1843 

1844 :meth:`_orm.Query.populate_existing` - overwrites attributes of 

1845 objects already loaded in the identity map. 

1846 

1847 """ # noqa: E501 

1848 

1849 self._for_update_arg = ForUpdateArg( 

1850 read=read, 

1851 nowait=nowait, 

1852 of=of, 

1853 skip_locked=skip_locked, 

1854 key_share=key_share, 

1855 ) 

1856 return self 

1857 

1858 @_generative 

1859 def params( 

1860 self, __params: Optional[Dict[str, Any]] = None, /, **kw: Any 

1861 ) -> Self: 

1862 r"""Add values for bind parameters which may have been 

1863 specified in filter(). 

1864 

1865 Parameters may be specified using \**kwargs, or optionally a single 

1866 dictionary as the first positional argument. The reason for both is 

1867 that \**kwargs is convenient, however some parameter dictionaries 

1868 contain unicode keys in which case \**kwargs cannot be used. 

1869 

1870 """ 

1871 if __params: 

1872 kw.update(__params) 

1873 self._params = self._params.union(kw) 

1874 return self 

1875 

1876 def where(self, *criterion: _ColumnExpressionArgument[bool]) -> Self: 

1877 """A synonym for :meth:`.Query.filter`. 

1878 

1879 .. versionadded:: 1.4 

1880 

1881 .. seealso:: 

1882 

1883 :meth:`_sql.Select.where` - v2 equivalent method. 

1884 

1885 """ 

1886 return self.filter(*criterion) 

1887 

1888 @_generative 

1889 @_assertions(_no_statement_condition, _no_limit_offset) 

1890 def filter(self, *criterion: _ColumnExpressionArgument[bool]) -> Self: 

1891 r"""Apply the given filtering criterion to a copy 

1892 of this :class:`_query.Query`, using SQL expressions. 

1893 

1894 e.g.:: 

1895 

1896 session.query(MyClass).filter(MyClass.name == 'some name') 

1897 

1898 Multiple criteria may be specified as comma separated; the effect 

1899 is that they will be joined together using the :func:`.and_` 

1900 function:: 

1901 

1902 session.query(MyClass).\ 

1903 filter(MyClass.name == 'some name', MyClass.id > 5) 

1904 

1905 The criterion is any SQL expression object applicable to the 

1906 WHERE clause of a select. String expressions are coerced 

1907 into SQL expression constructs via the :func:`_expression.text` 

1908 construct. 

1909 

1910 .. seealso:: 

1911 

1912 :meth:`_query.Query.filter_by` - filter on keyword expressions. 

1913 

1914 :meth:`_sql.Select.where` - v2 equivalent method. 

1915 

1916 """ 

1917 for crit in list(criterion): 

1918 crit = coercions.expect( 

1919 roles.WhereHavingRole, crit, apply_propagate_attrs=self 

1920 ) 

1921 

1922 self._where_criteria += (crit,) 

1923 return self 

1924 

1925 @util.memoized_property 

1926 def _last_joined_entity( 

1927 self, 

1928 ) -> Optional[Union[_InternalEntityType[Any], _JoinTargetElement]]: 

1929 if self._setup_joins: 

1930 return _determine_last_joined_entity( 

1931 self._setup_joins, 

1932 ) 

1933 else: 

1934 return None 

1935 

1936 def _filter_by_zero(self) -> Any: 

1937 """for the filter_by() method, return the target entity for which 

1938 we will attempt to derive an expression from based on string name. 

1939 

1940 """ 

1941 

1942 if self._setup_joins: 

1943 _last_joined_entity = self._last_joined_entity 

1944 if _last_joined_entity is not None: 

1945 return _last_joined_entity 

1946 

1947 # discussion related to #7239 

1948 # special check determines if we should try to derive attributes 

1949 # for filter_by() from the "from object", i.e., if the user 

1950 # called query.select_from(some selectable).filter_by(some_attr=value). 

1951 # We don't want to do that in the case that methods like 

1952 # from_self(), select_entity_from(), or a set op like union() were 

1953 # called; while these methods also place a 

1954 # selectable in the _from_obj collection, they also set up 

1955 # the _set_base_alias boolean which turns on the whole "adapt the 

1956 # entity to this selectable" thing, meaning the query still continues 

1957 # to construct itself in terms of the lead entity that was passed 

1958 # to query(), e.g. query(User).from_self() is still in terms of User, 

1959 # and not the subquery that from_self() created. This feature of 

1960 # "implicitly adapt all occurrences of entity X to some arbitrary 

1961 # subquery" is the main thing I am trying to do away with in 2.0 as 

1962 # users should now used aliased() for that, but I can't entirely get 

1963 # rid of it due to query.union() and other set ops relying upon it. 

1964 # 

1965 # compare this to the base Select()._filter_by_zero() which can 

1966 # just return self._from_obj[0] if present, because there is no 

1967 # "_set_base_alias" feature. 

1968 # 

1969 # IOW, this conditional essentially detects if 

1970 # "select_from(some_selectable)" has been called, as opposed to 

1971 # "select_entity_from()", "from_self()" 

1972 # or "union() / some_set_op()". 

1973 if self._from_obj and not self._compile_options._set_base_alias: 

1974 return self._from_obj[0] 

1975 

1976 return self._raw_columns[0] 

1977 

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

1979 r"""Apply the given filtering criterion to a copy 

1980 of this :class:`_query.Query`, using keyword expressions. 

1981 

1982 e.g.:: 

1983 

1984 session.query(MyClass).filter_by(name = 'some name') 

1985 

1986 Multiple criteria may be specified as comma separated; the effect 

1987 is that they will be joined together using the :func:`.and_` 

1988 function:: 

1989 

1990 session.query(MyClass).\ 

1991 filter_by(name = 'some name', id = 5) 

1992 

1993 The keyword expressions are extracted from the primary 

1994 entity of the query, or the last entity that was the 

1995 target of a call to :meth:`_query.Query.join`. 

1996 

1997 .. seealso:: 

1998 

1999 :meth:`_query.Query.filter` - filter on SQL expressions. 

2000 

2001 :meth:`_sql.Select.filter_by` - v2 comparable method. 

2002 

2003 """ 

2004 from_entity = self._filter_by_zero() 

2005 

2006 clauses = [ 

2007 _entity_namespace_key(from_entity, key) == value 

2008 for key, value in kwargs.items() 

2009 ] 

2010 return self.filter(*clauses) 

2011 

2012 @_generative 

2013 def order_by( 

2014 self, 

2015 __first: Union[ 

2016 Literal[None, False, _NoArg.NO_ARG], 

2017 _ColumnExpressionOrStrLabelArgument[Any], 

2018 ] = _NoArg.NO_ARG, 

2019 /, 

2020 *clauses: _ColumnExpressionOrStrLabelArgument[Any], 

2021 ) -> Self: 

2022 """Apply one or more ORDER BY criteria to the query and return 

2023 the newly resulting :class:`_query.Query`. 

2024 

2025 e.g.:: 

2026 

2027 q = session.query(Entity).order_by(Entity.id, Entity.name) 

2028 

2029 Calling this method multiple times is equivalent to calling it once 

2030 with all the clauses concatenated. All existing ORDER BY criteria may 

2031 be cancelled by passing ``None`` by itself. New ORDER BY criteria may 

2032 then be added by invoking :meth:`_orm.Query.order_by` again, e.g.:: 

2033 

2034 # will erase all ORDER BY and ORDER BY new_col alone 

2035 q = q.order_by(None).order_by(new_col) 

2036 

2037 .. seealso:: 

2038 

2039 These sections describe ORDER BY in terms of :term:`2.0 style` 

2040 invocation but apply to :class:`_orm.Query` as well: 

2041 

2042 :ref:`tutorial_order_by` - in the :ref:`unified_tutorial` 

2043 

2044 :ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial` 

2045 

2046 :meth:`_sql.Select.order_by` - v2 equivalent method. 

2047 

2048 """ 

2049 

2050 for assertion in (self._no_statement_condition, self._no_limit_offset): 

2051 assertion("order_by") 

2052 

2053 if not clauses and (__first is None or __first is False): 

2054 self._order_by_clauses = () 

2055 elif __first is not _NoArg.NO_ARG: 

2056 criterion = tuple( 

2057 coercions.expect(roles.OrderByRole, clause) 

2058 for clause in (__first,) + clauses 

2059 ) 

2060 self._order_by_clauses += criterion 

2061 

2062 return self 

2063 

2064 @_generative 

2065 def group_by( 

2066 self, 

2067 __first: Union[ 

2068 Literal[None, False, _NoArg.NO_ARG], 

2069 _ColumnExpressionOrStrLabelArgument[Any], 

2070 ] = _NoArg.NO_ARG, 

2071 /, 

2072 *clauses: _ColumnExpressionOrStrLabelArgument[Any], 

2073 ) -> Self: 

2074 """Apply one or more GROUP BY criterion to the query and return 

2075 the newly resulting :class:`_query.Query`. 

2076 

2077 All existing GROUP BY settings can be suppressed by 

2078 passing ``None`` - this will suppress any GROUP BY configured 

2079 on mappers as well. 

2080 

2081 .. seealso:: 

2082 

2083 These sections describe GROUP BY in terms of :term:`2.0 style` 

2084 invocation but apply to :class:`_orm.Query` as well: 

2085 

2086 :ref:`tutorial_group_by_w_aggregates` - in the 

2087 :ref:`unified_tutorial` 

2088 

2089 :ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial` 

2090 

2091 :meth:`_sql.Select.group_by` - v2 equivalent method. 

2092 

2093 """ 

2094 

2095 for assertion in (self._no_statement_condition, self._no_limit_offset): 

2096 assertion("group_by") 

2097 

2098 if not clauses and (__first is None or __first is False): 

2099 self._group_by_clauses = () 

2100 elif __first is not _NoArg.NO_ARG: 

2101 criterion = tuple( 

2102 coercions.expect(roles.GroupByRole, clause) 

2103 for clause in (__first,) + clauses 

2104 ) 

2105 self._group_by_clauses += criterion 

2106 return self 

2107 

2108 @_generative 

2109 @_assertions(_no_statement_condition, _no_limit_offset) 

2110 def having(self, *having: _ColumnExpressionArgument[bool]) -> Self: 

2111 r"""Apply a HAVING criterion to the query and return the 

2112 newly resulting :class:`_query.Query`. 

2113 

2114 :meth:`_query.Query.having` is used in conjunction with 

2115 :meth:`_query.Query.group_by`. 

2116 

2117 HAVING criterion makes it possible to use filters on aggregate 

2118 functions like COUNT, SUM, AVG, MAX, and MIN, eg.:: 

2119 

2120 q = session.query(User.id).\ 

2121 join(User.addresses).\ 

2122 group_by(User.id).\ 

2123 having(func.count(Address.id) > 2) 

2124 

2125 .. seealso:: 

2126 

2127 :meth:`_sql.Select.having` - v2 equivalent method. 

2128 

2129 """ 

2130 

2131 for criterion in having: 

2132 having_criteria = coercions.expect( 

2133 roles.WhereHavingRole, criterion 

2134 ) 

2135 self._having_criteria += (having_criteria,) 

2136 return self 

2137 

2138 def _set_op(self, expr_fn: Any, *q: Query[Any]) -> Self: 

2139 list_of_queries = (self,) + q 

2140 return self._from_selectable(expr_fn(*(list_of_queries)).subquery()) 

2141 

2142 def union(self, *q: Query[Any]) -> Self: 

2143 """Produce a UNION of this Query against one or more queries. 

2144 

2145 e.g.:: 

2146 

2147 q1 = sess.query(SomeClass).filter(SomeClass.foo=='bar') 

2148 q2 = sess.query(SomeClass).filter(SomeClass.bar=='foo') 

2149 

2150 q3 = q1.union(q2) 

2151 

2152 The method accepts multiple Query objects so as to control 

2153 the level of nesting. A series of ``union()`` calls such as:: 

2154 

2155 x.union(y).union(z).all() 

2156 

2157 will nest on each ``union()``, and produces:: 

2158 

2159 SELECT * FROM (SELECT * FROM (SELECT * FROM X UNION 

2160 SELECT * FROM y) UNION SELECT * FROM Z) 

2161 

2162 Whereas:: 

2163 

2164 x.union(y, z).all() 

2165 

2166 produces:: 

2167 

2168 SELECT * FROM (SELECT * FROM X UNION SELECT * FROM y UNION 

2169 SELECT * FROM Z) 

2170 

2171 Note that many database backends do not allow ORDER BY to 

2172 be rendered on a query called within UNION, EXCEPT, etc. 

2173 To disable all ORDER BY clauses including those configured 

2174 on mappers, issue ``query.order_by(None)`` - the resulting 

2175 :class:`_query.Query` object will not render ORDER BY within 

2176 its SELECT statement. 

2177 

2178 .. seealso:: 

2179 

2180 :meth:`_sql.Select.union` - v2 equivalent method. 

2181 

2182 """ 

2183 return self._set_op(expression.union, *q) 

2184 

2185 def union_all(self, *q: Query[Any]) -> Self: 

2186 """Produce a UNION ALL of this Query against one or more queries. 

2187 

2188 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See 

2189 that method for usage examples. 

2190 

2191 .. seealso:: 

2192 

2193 :meth:`_sql.Select.union_all` - v2 equivalent method. 

2194 

2195 """ 

2196 return self._set_op(expression.union_all, *q) 

2197 

2198 def intersect(self, *q: Query[Any]) -> Self: 

2199 """Produce an INTERSECT of this Query against one or more queries. 

2200 

2201 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See 

2202 that method for usage examples. 

2203 

2204 .. seealso:: 

2205 

2206 :meth:`_sql.Select.intersect` - v2 equivalent method. 

2207 

2208 """ 

2209 return self._set_op(expression.intersect, *q) 

2210 

2211 def intersect_all(self, *q: Query[Any]) -> Self: 

2212 """Produce an INTERSECT ALL of this Query against one or more queries. 

2213 

2214 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See 

2215 that method for usage examples. 

2216 

2217 .. seealso:: 

2218 

2219 :meth:`_sql.Select.intersect_all` - v2 equivalent method. 

2220 

2221 """ 

2222 return self._set_op(expression.intersect_all, *q) 

2223 

2224 def except_(self, *q: Query[Any]) -> Self: 

2225 """Produce an EXCEPT of this Query against one or more queries. 

2226 

2227 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See 

2228 that method for usage examples. 

2229 

2230 .. seealso:: 

2231 

2232 :meth:`_sql.Select.except_` - v2 equivalent method. 

2233 

2234 """ 

2235 return self._set_op(expression.except_, *q) 

2236 

2237 def except_all(self, *q: Query[Any]) -> Self: 

2238 """Produce an EXCEPT ALL of this Query against one or more queries. 

2239 

2240 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See 

2241 that method for usage examples. 

2242 

2243 .. seealso:: 

2244 

2245 :meth:`_sql.Select.except_all` - v2 equivalent method. 

2246 

2247 """ 

2248 return self._set_op(expression.except_all, *q) 

2249 

2250 @_generative 

2251 @_assertions(_no_statement_condition, _no_limit_offset) 

2252 def join( 

2253 self, 

2254 target: _JoinTargetArgument, 

2255 onclause: Optional[_OnClauseArgument] = None, 

2256 *, 

2257 isouter: bool = False, 

2258 full: bool = False, 

2259 ) -> Self: 

2260 r"""Create a SQL JOIN against this :class:`_query.Query` 

2261 object's criterion 

2262 and apply generatively, returning the newly resulting 

2263 :class:`_query.Query`. 

2264 

2265 **Simple Relationship Joins** 

2266 

2267 Consider a mapping between two classes ``User`` and ``Address``, 

2268 with a relationship ``User.addresses`` representing a collection 

2269 of ``Address`` objects associated with each ``User``. The most 

2270 common usage of :meth:`_query.Query.join` 

2271 is to create a JOIN along this 

2272 relationship, using the ``User.addresses`` attribute as an indicator 

2273 for how this should occur:: 

2274 

2275 q = session.query(User).join(User.addresses) 

2276 

2277 Where above, the call to :meth:`_query.Query.join` along 

2278 ``User.addresses`` will result in SQL approximately equivalent to:: 

2279 

2280 SELECT user.id, user.name 

2281 FROM user JOIN address ON user.id = address.user_id 

2282 

2283 In the above example we refer to ``User.addresses`` as passed to 

2284 :meth:`_query.Query.join` as the "on clause", that is, it indicates 

2285 how the "ON" portion of the JOIN should be constructed. 

2286 

2287 To construct a chain of joins, multiple :meth:`_query.Query.join` 

2288 calls may be used. The relationship-bound attribute implies both 

2289 the left and right side of the join at once:: 

2290 

2291 q = session.query(User).\ 

2292 join(User.orders).\ 

2293 join(Order.items).\ 

2294 join(Item.keywords) 

2295 

2296 .. note:: as seen in the above example, **the order in which each 

2297 call to the join() method occurs is important**. Query would not, 

2298 for example, know how to join correctly if we were to specify 

2299 ``User``, then ``Item``, then ``Order``, in our chain of joins; in 

2300 such a case, depending on the arguments passed, it may raise an 

2301 error that it doesn't know how to join, or it may produce invalid 

2302 SQL in which case the database will raise an error. In correct 

2303 practice, the 

2304 :meth:`_query.Query.join` method is invoked in such a way that lines 

2305 up with how we would want the JOIN clauses in SQL to be 

2306 rendered, and each call should represent a clear link from what 

2307 precedes it. 

2308 

2309 **Joins to a Target Entity or Selectable** 

2310 

2311 A second form of :meth:`_query.Query.join` allows any mapped entity or 

2312 core selectable construct as a target. In this usage, 

2313 :meth:`_query.Query.join` will attempt to create a JOIN along the 

2314 natural foreign key relationship between two entities:: 

2315 

2316 q = session.query(User).join(Address) 

2317 

2318 In the above calling form, :meth:`_query.Query.join` is called upon to 

2319 create the "on clause" automatically for us. This calling form will 

2320 ultimately raise an error if either there are no foreign keys between 

2321 the two entities, or if there are multiple foreign key linkages between 

2322 the target entity and the entity or entities already present on the 

2323 left side such that creating a join requires more information. Note 

2324 that when indicating a join to a target without any ON clause, ORM 

2325 configured relationships are not taken into account. 

2326 

2327 **Joins to a Target with an ON Clause** 

2328 

2329 The third calling form allows both the target entity as well 

2330 as the ON clause to be passed explicitly. A example that includes 

2331 a SQL expression as the ON clause is as follows:: 

2332 

2333 q = session.query(User).join(Address, User.id==Address.user_id) 

2334 

2335 The above form may also use a relationship-bound attribute as the 

2336 ON clause as well:: 

2337 

2338 q = session.query(User).join(Address, User.addresses) 

2339 

2340 The above syntax can be useful for the case where we wish 

2341 to join to an alias of a particular target entity. If we wanted 

2342 to join to ``Address`` twice, it could be achieved using two 

2343 aliases set up using the :func:`~sqlalchemy.orm.aliased` function:: 

2344 

2345 a1 = aliased(Address) 

2346 a2 = aliased(Address) 

2347 

2348 q = session.query(User).\ 

2349 join(a1, User.addresses).\ 

2350 join(a2, User.addresses).\ 

2351 filter(a1.email_address=='ed@foo.com').\ 

2352 filter(a2.email_address=='ed@bar.com') 

2353 

2354 The relationship-bound calling form can also specify a target entity 

2355 using the :meth:`_orm.PropComparator.of_type` method; a query 

2356 equivalent to the one above would be:: 

2357 

2358 a1 = aliased(Address) 

2359 a2 = aliased(Address) 

2360 

2361 q = session.query(User).\ 

2362 join(User.addresses.of_type(a1)).\ 

2363 join(User.addresses.of_type(a2)).\ 

2364 filter(a1.email_address == 'ed@foo.com').\ 

2365 filter(a2.email_address == 'ed@bar.com') 

2366 

2367 **Augmenting Built-in ON Clauses** 

2368 

2369 As a substitute for providing a full custom ON condition for an 

2370 existing relationship, the :meth:`_orm.PropComparator.and_` function 

2371 may be applied to a relationship attribute to augment additional 

2372 criteria into the ON clause; the additional criteria will be combined 

2373 with the default criteria using AND:: 

2374 

2375 q = session.query(User).join( 

2376 User.addresses.and_(Address.email_address != 'foo@bar.com') 

2377 ) 

2378 

2379 .. versionadded:: 1.4 

2380 

2381 **Joining to Tables and Subqueries** 

2382 

2383 

2384 The target of a join may also be any table or SELECT statement, 

2385 which may be related to a target entity or not. Use the 

2386 appropriate ``.subquery()`` method in order to make a subquery 

2387 out of a query:: 

2388 

2389 subq = session.query(Address).\ 

2390 filter(Address.email_address == 'ed@foo.com').\ 

2391 subquery() 

2392 

2393 

2394 q = session.query(User).join( 

2395 subq, User.id == subq.c.user_id 

2396 ) 

2397 

2398 Joining to a subquery in terms of a specific relationship and/or 

2399 target entity may be achieved by linking the subquery to the 

2400 entity using :func:`_orm.aliased`:: 

2401 

2402 subq = session.query(Address).\ 

2403 filter(Address.email_address == 'ed@foo.com').\ 

2404 subquery() 

2405 

2406 address_subq = aliased(Address, subq) 

2407 

2408 q = session.query(User).join( 

2409 User.addresses.of_type(address_subq) 

2410 ) 

2411 

2412 

2413 **Controlling what to Join From** 

2414 

2415 In cases where the left side of the current state of 

2416 :class:`_query.Query` is not in line with what we want to join from, 

2417 the :meth:`_query.Query.select_from` method may be used:: 

2418 

2419 q = session.query(Address).select_from(User).\ 

2420 join(User.addresses).\ 

2421 filter(User.name == 'ed') 

2422 

2423 Which will produce SQL similar to:: 

2424 

2425 SELECT address.* FROM user 

2426 JOIN address ON user.id=address.user_id 

2427 WHERE user.name = :name_1 

2428 

2429 .. seealso:: 

2430 

2431 :meth:`_sql.Select.join` - v2 equivalent method. 

2432 

2433 :param \*props: Incoming arguments for :meth:`_query.Query.join`, 

2434 the props collection in modern use should be considered to be a one 

2435 or two argument form, either as a single "target" entity or ORM 

2436 attribute-bound relationship, or as a target entity plus an "on 

2437 clause" which may be a SQL expression or ORM attribute-bound 

2438 relationship. 

2439 

2440 :param isouter=False: If True, the join used will be a left outer join, 

2441 just as if the :meth:`_query.Query.outerjoin` method were called. 

2442 

2443 :param full=False: render FULL OUTER JOIN; implies ``isouter``. 

2444 

2445 """ 

2446 

2447 join_target = coercions.expect( 

2448 roles.JoinTargetRole, 

2449 target, 

2450 apply_propagate_attrs=self, 

2451 legacy=True, 

2452 ) 

2453 if onclause is not None: 

2454 onclause_element = coercions.expect( 

2455 roles.OnClauseRole, onclause, legacy=True 

2456 ) 

2457 else: 

2458 onclause_element = None 

2459 

2460 self._setup_joins += ( 

2461 ( 

2462 join_target, 

2463 onclause_element, 

2464 None, 

2465 { 

2466 "isouter": isouter, 

2467 "full": full, 

2468 }, 

2469 ), 

2470 ) 

2471 

2472 self.__dict__.pop("_last_joined_entity", None) 

2473 return self 

2474 

2475 def outerjoin( 

2476 self, 

2477 target: _JoinTargetArgument, 

2478 onclause: Optional[_OnClauseArgument] = None, 

2479 *, 

2480 full: bool = False, 

2481 ) -> Self: 

2482 """Create a left outer join against this ``Query`` object's criterion 

2483 and apply generatively, returning the newly resulting ``Query``. 

2484 

2485 Usage is the same as the ``join()`` method. 

2486 

2487 .. seealso:: 

2488 

2489 :meth:`_sql.Select.outerjoin` - v2 equivalent method. 

2490 

2491 """ 

2492 return self.join(target, onclause=onclause, isouter=True, full=full) 

2493 

2494 @_generative 

2495 @_assertions(_no_statement_condition) 

2496 def reset_joinpoint(self) -> Self: 

2497 """Return a new :class:`.Query`, where the "join point" has 

2498 been reset back to the base FROM entities of the query. 

2499 

2500 This method is usually used in conjunction with the 

2501 ``aliased=True`` feature of the :meth:`~.Query.join` 

2502 method. See the example in :meth:`~.Query.join` for how 

2503 this is used. 

2504 

2505 """ 

2506 self._last_joined_entity = None 

2507 

2508 return self 

2509 

2510 @_generative 

2511 @_assertions(_no_clauseelement_condition) 

2512 def select_from(self, *from_obj: _FromClauseArgument) -> Self: 

2513 r"""Set the FROM clause of this :class:`.Query` explicitly. 

2514 

2515 :meth:`.Query.select_from` is often used in conjunction with 

2516 :meth:`.Query.join` in order to control which entity is selected 

2517 from on the "left" side of the join. 

2518 

2519 The entity or selectable object here effectively replaces the 

2520 "left edge" of any calls to :meth:`~.Query.join`, when no 

2521 joinpoint is otherwise established - usually, the default "join 

2522 point" is the leftmost entity in the :class:`~.Query` object's 

2523 list of entities to be selected. 

2524 

2525 A typical example:: 

2526 

2527 q = session.query(Address).select_from(User).\ 

2528 join(User.addresses).\ 

2529 filter(User.name == 'ed') 

2530 

2531 Which produces SQL equivalent to:: 

2532 

2533 SELECT address.* FROM user 

2534 JOIN address ON user.id=address.user_id 

2535 WHERE user.name = :name_1 

2536 

2537 :param \*from_obj: collection of one or more entities to apply 

2538 to the FROM clause. Entities can be mapped classes, 

2539 :class:`.AliasedClass` objects, :class:`.Mapper` objects 

2540 as well as core :class:`.FromClause` elements like subqueries. 

2541 

2542 .. seealso:: 

2543 

2544 :meth:`~.Query.join` 

2545 

2546 :meth:`.Query.select_entity_from` 

2547 

2548 :meth:`_sql.Select.select_from` - v2 equivalent method. 

2549 

2550 """ 

2551 

2552 self._set_select_from(from_obj, False) 

2553 return self 

2554 

2555 def __getitem__(self, item: Any) -> Any: 

2556 return orm_util._getitem( 

2557 self, 

2558 item, 

2559 ) 

2560 

2561 @_generative 

2562 @_assertions(_no_statement_condition) 

2563 def slice( 

2564 self, 

2565 start: int, 

2566 stop: int, 

2567 ) -> Self: 

2568 """Computes the "slice" of the :class:`_query.Query` represented by 

2569 the given indices and returns the resulting :class:`_query.Query`. 

2570 

2571 The start and stop indices behave like the argument to Python's 

2572 built-in :func:`range` function. This method provides an 

2573 alternative to using ``LIMIT``/``OFFSET`` to get a slice of the 

2574 query. 

2575 

2576 For example, :: 

2577 

2578 session.query(User).order_by(User.id).slice(1, 3) 

2579 

2580 renders as 

2581 

2582 .. sourcecode:: sql 

2583 

2584 SELECT users.id AS users_id, 

2585 users.name AS users_name 

2586 FROM users ORDER BY users.id 

2587 LIMIT ? OFFSET ? 

2588 (2, 1) 

2589 

2590 .. seealso:: 

2591 

2592 :meth:`_query.Query.limit` 

2593 

2594 :meth:`_query.Query.offset` 

2595 

2596 :meth:`_sql.Select.slice` - v2 equivalent method. 

2597 

2598 """ 

2599 

2600 self._limit_clause, self._offset_clause = sql_util._make_slice( 

2601 self._limit_clause, self._offset_clause, start, stop 

2602 ) 

2603 return self 

2604 

2605 @_generative 

2606 @_assertions(_no_statement_condition) 

2607 def limit(self, limit: _LimitOffsetType) -> Self: 

2608 """Apply a ``LIMIT`` to the query and return the newly resulting 

2609 ``Query``. 

2610 

2611 .. seealso:: 

2612 

2613 :meth:`_sql.Select.limit` - v2 equivalent method. 

2614 

2615 """ 

2616 self._limit_clause = sql_util._offset_or_limit_clause(limit) 

2617 return self 

2618 

2619 @_generative 

2620 @_assertions(_no_statement_condition) 

2621 def offset(self, offset: _LimitOffsetType) -> Self: 

2622 """Apply an ``OFFSET`` to the query and return the newly resulting 

2623 ``Query``. 

2624 

2625 .. seealso:: 

2626 

2627 :meth:`_sql.Select.offset` - v2 equivalent method. 

2628 """ 

2629 self._offset_clause = sql_util._offset_or_limit_clause(offset) 

2630 return self 

2631 

2632 @_generative 

2633 @_assertions(_no_statement_condition) 

2634 def distinct(self, *expr: _ColumnExpressionArgument[Any]) -> Self: 

2635 r"""Apply a ``DISTINCT`` to the query and return the newly resulting 

2636 ``Query``. 

2637 

2638 

2639 .. note:: 

2640 

2641 The ORM-level :meth:`.distinct` call includes logic that will 

2642 automatically add columns from the ORDER BY of the query to the 

2643 columns clause of the SELECT statement, to satisfy the common need 

2644 of the database backend that ORDER BY columns be part of the SELECT 

2645 list when DISTINCT is used. These columns *are not* added to the 

2646 list of columns actually fetched by the :class:`_query.Query`, 

2647 however, 

2648 so would not affect results. The columns are passed through when 

2649 using the :attr:`_query.Query.statement` accessor, however. 

2650 

2651 .. deprecated:: 2.0 This logic is deprecated and will be removed 

2652 in SQLAlchemy 2.0. See :ref:`migration_20_query_distinct` 

2653 for a description of this use case in 2.0. 

2654 

2655 .. seealso:: 

2656 

2657 :meth:`_sql.Select.distinct` - v2 equivalent method. 

2658 

2659 :param \*expr: optional column expressions. When present, 

2660 the PostgreSQL dialect will render a ``DISTINCT ON (<expressions>)`` 

2661 construct. 

2662 

2663 .. deprecated:: 1.4 Using \*expr in other dialects is deprecated 

2664 and will raise :class:`_exc.CompileError` in a future version. 

2665 

2666 """ 

2667 if expr: 

2668 self._distinct = True 

2669 self._distinct_on = self._distinct_on + tuple( 

2670 coercions.expect(roles.ByOfRole, e) for e in expr 

2671 ) 

2672 else: 

2673 self._distinct = True 

2674 return self 

2675 

2676 def all(self) -> List[_T]: 

2677 """Return the results represented by this :class:`_query.Query` 

2678 as a list. 

2679 

2680 This results in an execution of the underlying SQL statement. 

2681 

2682 .. warning:: The :class:`_query.Query` object, 

2683 when asked to return either 

2684 a sequence or iterator that consists of full ORM-mapped entities, 

2685 will **deduplicate entries based on primary key**. See the FAQ for 

2686 more details. 

2687 

2688 .. seealso:: 

2689 

2690 :ref:`faq_query_deduplicating` 

2691 

2692 .. seealso:: 

2693 

2694 :meth:`_engine.Result.all` - v2 comparable method. 

2695 

2696 :meth:`_engine.Result.scalars` - v2 comparable method. 

2697 """ 

2698 return self._iter().all() # type: ignore 

2699 

2700 @_generative 

2701 @_assertions(_no_clauseelement_condition) 

2702 def from_statement(self, statement: ExecutableReturnsRows) -> Self: 

2703 """Execute the given SELECT statement and return results. 

2704 

2705 This method bypasses all internal statement compilation, and the 

2706 statement is executed without modification. 

2707 

2708 The statement is typically either a :func:`_expression.text` 

2709 or :func:`_expression.select` construct, and should return the set 

2710 of columns 

2711 appropriate to the entity class represented by this 

2712 :class:`_query.Query`. 

2713 

2714 .. seealso:: 

2715 

2716 :meth:`_sql.Select.from_statement` - v2 comparable method. 

2717 

2718 """ 

2719 statement = coercions.expect( 

2720 roles.SelectStatementRole, statement, apply_propagate_attrs=self 

2721 ) 

2722 self._statement = statement 

2723 return self 

2724 

2725 def first(self) -> Optional[_T]: 

2726 """Return the first result of this ``Query`` or 

2727 None if the result doesn't contain any row. 

2728 

2729 first() applies a limit of one within the generated SQL, so that 

2730 only one primary entity row is generated on the server side 

2731 (note this may consist of multiple result rows if join-loaded 

2732 collections are present). 

2733 

2734 Calling :meth:`_query.Query.first` 

2735 results in an execution of the underlying 

2736 query. 

2737 

2738 .. seealso:: 

2739 

2740 :meth:`_query.Query.one` 

2741 

2742 :meth:`_query.Query.one_or_none` 

2743 

2744 :meth:`_engine.Result.first` - v2 comparable method. 

2745 

2746 :meth:`_engine.Result.scalars` - v2 comparable method. 

2747 

2748 """ 

2749 # replicates limit(1) behavior 

2750 if self._statement is not None: 

2751 return self._iter().first() # type: ignore 

2752 else: 

2753 return self.limit(1)._iter().first() # type: ignore 

2754 

2755 def one_or_none(self) -> Optional[_T]: 

2756 """Return at most one result or raise an exception. 

2757 

2758 Returns ``None`` if the query selects 

2759 no rows. Raises ``sqlalchemy.orm.exc.MultipleResultsFound`` 

2760 if multiple object identities are returned, or if multiple 

2761 rows are returned for a query that returns only scalar values 

2762 as opposed to full identity-mapped entities. 

2763 

2764 Calling :meth:`_query.Query.one_or_none` 

2765 results in an execution of the 

2766 underlying query. 

2767 

2768 .. seealso:: 

2769 

2770 :meth:`_query.Query.first` 

2771 

2772 :meth:`_query.Query.one` 

2773 

2774 :meth:`_engine.Result.one_or_none` - v2 comparable method. 

2775 

2776 :meth:`_engine.Result.scalar_one_or_none` - v2 comparable method. 

2777 

2778 """ 

2779 return self._iter().one_or_none() # type: ignore 

2780 

2781 def one(self) -> _T: 

2782 """Return exactly one result or raise an exception. 

2783 

2784 Raises ``sqlalchemy.orm.exc.NoResultFound`` if the query selects 

2785 no rows. Raises ``sqlalchemy.orm.exc.MultipleResultsFound`` 

2786 if multiple object identities are returned, or if multiple 

2787 rows are returned for a query that returns only scalar values 

2788 as opposed to full identity-mapped entities. 

2789 

2790 Calling :meth:`.one` results in an execution of the underlying query. 

2791 

2792 .. seealso:: 

2793 

2794 :meth:`_query.Query.first` 

2795 

2796 :meth:`_query.Query.one_or_none` 

2797 

2798 :meth:`_engine.Result.one` - v2 comparable method. 

2799 

2800 :meth:`_engine.Result.scalar_one` - v2 comparable method. 

2801 

2802 """ 

2803 return self._iter().one() # type: ignore 

2804 

2805 def scalar(self) -> Any: 

2806 """Return the first element of the first result or None 

2807 if no rows present. If multiple rows are returned, 

2808 raises MultipleResultsFound. 

2809 

2810 >>> session.query(Item).scalar() 

2811 <Item> 

2812 >>> session.query(Item.id).scalar() 

2813 1 

2814 >>> session.query(Item.id).filter(Item.id < 0).scalar() 

2815 None 

2816 >>> session.query(Item.id, Item.name).scalar() 

2817 1 

2818 >>> session.query(func.count(Parent.id)).scalar() 

2819 20 

2820 

2821 This results in an execution of the underlying query. 

2822 

2823 .. seealso:: 

2824 

2825 :meth:`_engine.Result.scalar` - v2 comparable method. 

2826 

2827 """ 

2828 # TODO: not sure why we can't use result.scalar() here 

2829 try: 

2830 ret = self.one() 

2831 if not isinstance(ret, collections_abc.Sequence): 

2832 return ret 

2833 return ret[0] 

2834 except sa_exc.NoResultFound: 

2835 return None 

2836 

2837 def __iter__(self) -> Iterator[_T]: 

2838 result = self._iter() 

2839 try: 

2840 yield from result # type: ignore 

2841 except GeneratorExit: 

2842 # issue #8710 - direct iteration is not re-usable after 

2843 # an iterable block is broken, so close the result 

2844 result._soft_close() 

2845 raise 

2846 

2847 def _iter(self) -> Union[ScalarResult[_T], Result[_T]]: 

2848 # new style execution. 

2849 params = self._params 

2850 

2851 statement = self._statement_20() 

2852 result: Union[ScalarResult[_T], Result[_T]] = self.session.execute( 

2853 statement, 

2854 params, 

2855 execution_options={"_sa_orm_load_options": self.load_options}, 

2856 ) 

2857 

2858 # legacy: automatically set scalars, unique 

2859 if result._attributes.get("is_single_entity", False): 

2860 result = cast("Result[_T]", result).scalars() 

2861 

2862 if ( 

2863 result._attributes.get("filtered", False) 

2864 and not self.load_options._yield_per 

2865 ): 

2866 result = result.unique() 

2867 

2868 return result 

2869 

2870 def __str__(self) -> str: 

2871 statement = self._statement_20() 

2872 

2873 try: 

2874 bind = ( 

2875 self.session.get_bind(clause=statement) 

2876 if self.session 

2877 else None 

2878 ) 

2879 except sa_exc.UnboundExecutionError: 

2880 bind = None 

2881 

2882 return str(statement.compile(bind)) 

2883 

2884 @property 

2885 def column_descriptions(self) -> List[ORMColumnDescription]: 

2886 """Return metadata about the columns which would be 

2887 returned by this :class:`_query.Query`. 

2888 

2889 Format is a list of dictionaries:: 

2890 

2891 user_alias = aliased(User, name='user2') 

2892 q = sess.query(User, User.id, user_alias) 

2893 

2894 # this expression: 

2895 q.column_descriptions 

2896 

2897 # would return: 

2898 [ 

2899 { 

2900 'name':'User', 

2901 'type':User, 

2902 'aliased':False, 

2903 'expr':User, 

2904 'entity': User 

2905 }, 

2906 { 

2907 'name':'id', 

2908 'type':Integer(), 

2909 'aliased':False, 

2910 'expr':User.id, 

2911 'entity': User 

2912 }, 

2913 { 

2914 'name':'user2', 

2915 'type':User, 

2916 'aliased':True, 

2917 'expr':user_alias, 

2918 'entity': user_alias 

2919 } 

2920 ] 

2921 

2922 .. seealso:: 

2923 

2924 This API is available using :term:`2.0 style` queries as well, 

2925 documented at: 

2926 

2927 * :ref:`queryguide_inspection` 

2928 

2929 * :attr:`.Select.column_descriptions` 

2930 

2931 """ 

2932 

2933 return _column_descriptions(self, legacy=True) 

2934 

2935 @util.deprecated( 

2936 "2.0", 

2937 "The :meth:`_orm.Query.instances` method is deprecated and will " 

2938 "be removed in a future release. " 

2939 "Use the Select.from_statement() method or aliased() construct in " 

2940 "conjunction with Session.execute() instead.", 

2941 ) 

2942 def instances( 

2943 self, 

2944 result_proxy: CursorResult[Any], 

2945 context: Optional[QueryContext] = None, 

2946 ) -> Any: 

2947 """Return an ORM result given a :class:`_engine.CursorResult` and 

2948 :class:`.QueryContext`. 

2949 

2950 """ 

2951 if context is None: 

2952 util.warn_deprecated( 

2953 "Using the Query.instances() method without a context " 

2954 "is deprecated and will be disallowed in a future release. " 

2955 "Please make use of :meth:`_query.Query.from_statement` " 

2956 "for linking ORM results to arbitrary select constructs.", 

2957 version="1.4", 

2958 ) 

2959 compile_state = self._compile_state(for_statement=False) 

2960 

2961 context = QueryContext( 

2962 compile_state, 

2963 compile_state.statement, 

2964 self._params, 

2965 self.session, 

2966 self.load_options, 

2967 ) 

2968 

2969 result = loading.instances(result_proxy, context) 

2970 

2971 # legacy: automatically set scalars, unique 

2972 if result._attributes.get("is_single_entity", False): 

2973 result = result.scalars() # type: ignore 

2974 

2975 if result._attributes.get("filtered", False): 

2976 result = result.unique() 

2977 

2978 # TODO: isn't this supposed to be a list? 

2979 return result 

2980 

2981 @util.became_legacy_20( 

2982 ":meth:`_orm.Query.merge_result`", 

2983 alternative="The method is superseded by the " 

2984 ":func:`_orm.merge_frozen_result` function.", 

2985 enable_warnings=False, # warnings occur via loading.merge_result 

2986 ) 

2987 def merge_result( 

2988 self, 

2989 iterator: Union[ 

2990 FrozenResult[Any], Iterable[Sequence[Any]], Iterable[object] 

2991 ], 

2992 load: bool = True, 

2993 ) -> Union[FrozenResult[Any], Iterable[Any]]: 

2994 """Merge a result into this :class:`_query.Query` object's Session. 

2995 

2996 Given an iterator returned by a :class:`_query.Query` 

2997 of the same structure 

2998 as this one, return an identical iterator of results, with all mapped 

2999 instances merged into the session using :meth:`.Session.merge`. This 

3000 is an optimized method which will merge all mapped instances, 

3001 preserving the structure of the result rows and unmapped columns with 

3002 less method overhead than that of calling :meth:`.Session.merge` 

3003 explicitly for each value. 

3004 

3005 The structure of the results is determined based on the column list of 

3006 this :class:`_query.Query` - if these do not correspond, 

3007 unchecked errors 

3008 will occur. 

3009 

3010 The 'load' argument is the same as that of :meth:`.Session.merge`. 

3011 

3012 For an example of how :meth:`_query.Query.merge_result` is used, see 

3013 the source code for the example :ref:`examples_caching`, where 

3014 :meth:`_query.Query.merge_result` is used to efficiently restore state 

3015 from a cache back into a target :class:`.Session`. 

3016 

3017 """ 

3018 

3019 return loading.merge_result(self, iterator, load) 

3020 

3021 def exists(self) -> Exists: 

3022 """A convenience method that turns a query into an EXISTS subquery 

3023 of the form EXISTS (SELECT 1 FROM ... WHERE ...). 

3024 

3025 e.g.:: 

3026 

3027 q = session.query(User).filter(User.name == 'fred') 

3028 session.query(q.exists()) 

3029 

3030 Producing SQL similar to:: 

3031 

3032 SELECT EXISTS ( 

3033 SELECT 1 FROM users WHERE users.name = :name_1 

3034 ) AS anon_1 

3035 

3036 The EXISTS construct is usually used in the WHERE clause:: 

3037 

3038 session.query(User.id).filter(q.exists()).scalar() 

3039 

3040 Note that some databases such as SQL Server don't allow an 

3041 EXISTS expression to be present in the columns clause of a 

3042 SELECT. To select a simple boolean value based on the exists 

3043 as a WHERE, use :func:`.literal`:: 

3044 

3045 from sqlalchemy import literal 

3046 

3047 session.query(literal(True)).filter(q.exists()).scalar() 

3048 

3049 .. seealso:: 

3050 

3051 :meth:`_sql.Select.exists` - v2 comparable method. 

3052 

3053 """ 

3054 

3055 # .add_columns() for the case that we are a query().select_from(X), 

3056 # so that ".statement" can be produced (#2995) but also without 

3057 # omitting the FROM clause from a query(X) (#2818); 

3058 # .with_only_columns() after we have a core select() so that 

3059 # we get just "SELECT 1" without any entities. 

3060 

3061 inner = ( 

3062 self.enable_eagerloads(False) 

3063 .add_columns(sql.literal_column("1")) 

3064 .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) 

3065 ._get_select_statement_only() 

3066 .with_only_columns(1) 

3067 ) 

3068 

3069 ezero = self._entity_from_pre_ent_zero() 

3070 if ezero is not None: 

3071 inner = inner.select_from(ezero) 

3072 

3073 return sql.exists(inner) 

3074 

3075 def count(self) -> int: 

3076 r"""Return a count of rows this the SQL formed by this :class:`Query` 

3077 would return. 

3078 

3079 This generates the SQL for this Query as follows:: 

3080 

3081 SELECT count(1) AS count_1 FROM ( 

3082 SELECT <rest of query follows...> 

3083 ) AS anon_1 

3084 

3085 The above SQL returns a single row, which is the aggregate value 

3086 of the count function; the :meth:`_query.Query.count` 

3087 method then returns 

3088 that single integer value. 

3089 

3090 .. warning:: 

3091 

3092 It is important to note that the value returned by 

3093 count() is **not the same as the number of ORM objects that this 

3094 Query would return from a method such as the .all() method**. 

3095 The :class:`_query.Query` object, 

3096 when asked to return full entities, 

3097 will **deduplicate entries based on primary key**, meaning if the 

3098 same primary key value would appear in the results more than once, 

3099 only one object of that primary key would be present. This does 

3100 not apply to a query that is against individual columns. 

3101 

3102 .. seealso:: 

3103 

3104 :ref:`faq_query_deduplicating` 

3105 

3106 For fine grained control over specific columns to count, to skip the 

3107 usage of a subquery or otherwise control of the FROM clause, or to use 

3108 other aggregate functions, use :attr:`~sqlalchemy.sql.expression.func` 

3109 expressions in conjunction with :meth:`~.Session.query`, i.e.:: 

3110 

3111 from sqlalchemy import func 

3112 

3113 # count User records, without 

3114 # using a subquery. 

3115 session.query(func.count(User.id)) 

3116 

3117 # return count of user "id" grouped 

3118 # by "name" 

3119 session.query(func.count(User.id)).\ 

3120 group_by(User.name) 

3121 

3122 from sqlalchemy import distinct 

3123 

3124 # count distinct "name" values 

3125 session.query(func.count(distinct(User.name))) 

3126 

3127 .. seealso:: 

3128 

3129 :ref:`migration_20_query_usage` 

3130 

3131 """ 

3132 col = sql.func.count(sql.literal_column("*")) 

3133 return ( # type: ignore 

3134 self._legacy_from_self(col).enable_eagerloads(False).scalar() 

3135 ) 

3136 

3137 def delete( 

3138 self, synchronize_session: SynchronizeSessionArgument = "auto" 

3139 ) -> int: 

3140 r"""Perform a DELETE with an arbitrary WHERE clause. 

3141 

3142 Deletes rows matched by this query from the database. 

3143 

3144 E.g.:: 

3145 

3146 sess.query(User).filter(User.age == 25).\ 

3147 delete(synchronize_session=False) 

3148 

3149 sess.query(User).filter(User.age == 25).\ 

3150 delete(synchronize_session='evaluate') 

3151 

3152 .. warning:: 

3153 

3154 See the section :ref:`orm_expression_update_delete` for important 

3155 caveats and warnings, including limitations when using bulk UPDATE 

3156 and DELETE with mapper inheritance configurations. 

3157 

3158 :param synchronize_session: chooses the strategy to update the 

3159 attributes on objects in the session. See the section 

3160 :ref:`orm_expression_update_delete` for a discussion of these 

3161 strategies. 

3162 

3163 :return: the count of rows matched as returned by the database's 

3164 "row count" feature. 

3165 

3166 .. seealso:: 

3167 

3168 :ref:`orm_expression_update_delete` 

3169 

3170 """ 

3171 

3172 bulk_del = BulkDelete(self) 

3173 if self.dispatch.before_compile_delete: 

3174 for fn in self.dispatch.before_compile_delete: 

3175 new_query = fn(bulk_del.query, bulk_del) 

3176 if new_query is not None: 

3177 bulk_del.query = new_query 

3178 

3179 self = bulk_del.query 

3180 

3181 delete_ = sql.delete(*self._raw_columns) # type: ignore 

3182 delete_._where_criteria = self._where_criteria 

3183 result: CursorResult[Any] = self.session.execute( 

3184 delete_, 

3185 self._params, 

3186 execution_options=self._execution_options.union( 

3187 {"synchronize_session": synchronize_session} 

3188 ), 

3189 ) 

3190 bulk_del.result = result # type: ignore 

3191 self.session.dispatch.after_bulk_delete(bulk_del) 

3192 result.close() 

3193 

3194 return result.rowcount 

3195 

3196 def update( 

3197 self, 

3198 values: Dict[_DMLColumnArgument, Any], 

3199 synchronize_session: SynchronizeSessionArgument = "auto", 

3200 update_args: Optional[Dict[Any, Any]] = None, 

3201 ) -> int: 

3202 r"""Perform an UPDATE with an arbitrary WHERE clause. 

3203 

3204 Updates rows matched by this query in the database. 

3205 

3206 E.g.:: 

3207 

3208 sess.query(User).filter(User.age == 25).\ 

3209 update({User.age: User.age - 10}, synchronize_session=False) 

3210 

3211 sess.query(User).filter(User.age == 25).\ 

3212 update({"age": User.age - 10}, synchronize_session='evaluate') 

3213 

3214 .. warning:: 

3215 

3216 See the section :ref:`orm_expression_update_delete` for important 

3217 caveats and warnings, including limitations when using arbitrary 

3218 UPDATE and DELETE with mapper inheritance configurations. 

3219 

3220 :param values: a dictionary with attributes names, or alternatively 

3221 mapped attributes or SQL expressions, as keys, and literal 

3222 values or sql expressions as values. If :ref:`parameter-ordered 

3223 mode <tutorial_parameter_ordered_updates>` is desired, the values can 

3224 be passed as a list of 2-tuples; this requires that the 

3225 :paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order` 

3226 flag is passed to the :paramref:`.Query.update.update_args` dictionary 

3227 as well. 

3228 

3229 :param synchronize_session: chooses the strategy to update the 

3230 attributes on objects in the session. See the section 

3231 :ref:`orm_expression_update_delete` for a discussion of these 

3232 strategies. 

3233 

3234 :param update_args: Optional dictionary, if present will be passed 

3235 to the underlying :func:`_expression.update` 

3236 construct as the ``**kw`` for 

3237 the object. May be used to pass dialect-specific arguments such 

3238 as ``mysql_limit``, as well as other special arguments such as 

3239 :paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order`. 

3240 

3241 :return: the count of rows matched as returned by the database's 

3242 "row count" feature. 

3243 

3244 

3245 .. seealso:: 

3246 

3247 :ref:`orm_expression_update_delete` 

3248 

3249 """ 

3250 

3251 update_args = update_args or {} 

3252 

3253 bulk_ud = BulkUpdate(self, values, update_args) 

3254 

3255 if self.dispatch.before_compile_update: 

3256 for fn in self.dispatch.before_compile_update: 

3257 new_query = fn(bulk_ud.query, bulk_ud) 

3258 if new_query is not None: 

3259 bulk_ud.query = new_query 

3260 self = bulk_ud.query 

3261 

3262 upd = sql.update(*self._raw_columns) # type: ignore 

3263 

3264 ppo = update_args.pop("preserve_parameter_order", False) 

3265 if ppo: 

3266 upd = upd.ordered_values(*values) # type: ignore 

3267 else: 

3268 upd = upd.values(values) 

3269 if update_args: 

3270 upd = upd.with_dialect_options(**update_args) 

3271 

3272 upd._where_criteria = self._where_criteria 

3273 result: CursorResult[Any] = self.session.execute( 

3274 upd, 

3275 self._params, 

3276 execution_options=self._execution_options.union( 

3277 {"synchronize_session": synchronize_session} 

3278 ), 

3279 ) 

3280 bulk_ud.result = result # type: ignore 

3281 self.session.dispatch.after_bulk_update(bulk_ud) 

3282 result.close() 

3283 return result.rowcount 

3284 

3285 def _compile_state( 

3286 self, for_statement: bool = False, **kw: Any 

3287 ) -> ORMCompileState: 

3288 """Create an out-of-compiler ORMCompileState object. 

3289 

3290 The ORMCompileState object is normally created directly as a result 

3291 of the SQLCompiler.process() method being handed a Select() 

3292 or FromStatement() object that uses the "orm" plugin. This method 

3293 provides a means of creating this ORMCompileState object directly 

3294 without using the compiler. 

3295 

3296 This method is used only for deprecated cases, which include 

3297 the .from_self() method for a Query that has multiple levels 

3298 of .from_self() in use, as well as the instances() method. It is 

3299 also used within the test suite to generate ORMCompileState objects 

3300 for test purposes. 

3301 

3302 """ 

3303 

3304 stmt = self._statement_20(for_statement=for_statement, **kw) 

3305 assert for_statement == stmt._compile_options._for_statement 

3306 

3307 # this chooses between ORMFromStatementCompileState and 

3308 # ORMSelectCompileState. We could also base this on 

3309 # query._statement is not None as we have the ORM Query here 

3310 # however this is the more general path. 

3311 compile_state_cls = cast( 

3312 ORMCompileState, 

3313 ORMCompileState._get_plugin_class_for_plugin(stmt, "orm"), 

3314 ) 

3315 

3316 return compile_state_cls.create_for_statement(stmt, None) 

3317 

3318 def _compile_context(self, for_statement: bool = False) -> QueryContext: 

3319 compile_state = self._compile_state(for_statement=for_statement) 

3320 context = QueryContext( 

3321 compile_state, 

3322 compile_state.statement, 

3323 self._params, 

3324 self.session, 

3325 self.load_options, 

3326 ) 

3327 

3328 return context 

3329 

3330 

3331class AliasOption(interfaces.LoaderOption): 

3332 inherit_cache = False 

3333 

3334 @util.deprecated( 

3335 "1.4", 

3336 "The :class:`.AliasOption` object is not necessary " 

3337 "for entities to be matched up to a query that is established " 

3338 "via :meth:`.Query.from_statement` and now does nothing.", 

3339 ) 

3340 def __init__(self, alias: Union[Alias, Subquery]): 

3341 r"""Return a :class:`.MapperOption` that will indicate to the 

3342 :class:`_query.Query` 

3343 that the main table has been aliased. 

3344 

3345 """ 

3346 

3347 def process_compile_state(self, compile_state: ORMCompileState) -> None: 

3348 pass 

3349 

3350 

3351class BulkUD: 

3352 """State used for the orm.Query version of update() / delete(). 

3353 

3354 This object is now specific to Query only. 

3355 

3356 """ 

3357 

3358 def __init__(self, query: Query[Any]): 

3359 self.query = query.enable_eagerloads(False) 

3360 self._validate_query_state() 

3361 self.mapper = self.query._entity_from_pre_ent_zero() 

3362 

3363 def _validate_query_state(self) -> None: 

3364 for attr, methname, notset, op in ( 

3365 ("_limit_clause", "limit()", None, operator.is_), 

3366 ("_offset_clause", "offset()", None, operator.is_), 

3367 ("_order_by_clauses", "order_by()", (), operator.eq), 

3368 ("_group_by_clauses", "group_by()", (), operator.eq), 

3369 ("_distinct", "distinct()", False, operator.is_), 

3370 ( 

3371 "_from_obj", 

3372 "join(), outerjoin(), select_from(), or from_self()", 

3373 (), 

3374 operator.eq, 

3375 ), 

3376 ( 

3377 "_setup_joins", 

3378 "join(), outerjoin(), select_from(), or from_self()", 

3379 (), 

3380 operator.eq, 

3381 ), 

3382 ): 

3383 if not op(getattr(self.query, attr), notset): 

3384 raise sa_exc.InvalidRequestError( 

3385 "Can't call Query.update() or Query.delete() " 

3386 "when %s has been called" % (methname,) 

3387 ) 

3388 

3389 @property 

3390 def session(self) -> Session: 

3391 return self.query.session 

3392 

3393 

3394class BulkUpdate(BulkUD): 

3395 """BulkUD which handles UPDATEs.""" 

3396 

3397 def __init__( 

3398 self, 

3399 query: Query[Any], 

3400 values: Dict[_DMLColumnArgument, Any], 

3401 update_kwargs: Optional[Dict[Any, Any]], 

3402 ): 

3403 super().__init__(query) 

3404 self.values = values 

3405 self.update_kwargs = update_kwargs 

3406 

3407 

3408class BulkDelete(BulkUD): 

3409 """BulkUD which handles DELETEs.""" 

3410 

3411 

3412class RowReturningQuery(Query[Row[Unpack[_Ts]]]): 

3413 if TYPE_CHECKING: 

3414 

3415 def tuples(self) -> Query[Tuple[Unpack[_Ts]]]: # type: ignore 

3416 ...