1# orm/query.py
2# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
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._typing import _TP
78from ..sql.annotation import SupportsCloneAnnotations
79from ..sql.base import _entity_namespace_key
80from ..sql.base import _generative
81from ..sql.base import _NoArg
82from ..sql.base import Executable
83from ..sql.base import Generative
84from ..sql.elements import BooleanClauseList
85from ..sql.expression import Exists
86from ..sql.selectable import _MemoizedSelectEntities
87from ..sql.selectable import _SelectFromElements
88from ..sql.selectable import ForUpdateArg
89from ..sql.selectable import HasHints
90from ..sql.selectable import HasPrefixes
91from ..sql.selectable import HasSuffixes
92from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
93from ..sql.selectable import SelectLabelStyle
94from ..util.typing import Literal
95from ..util.typing import Self
96
97
98if TYPE_CHECKING:
99 from ._typing import _EntityType
100 from ._typing import _ExternalEntityType
101 from ._typing import _InternalEntityType
102 from ._typing import SynchronizeSessionArgument
103 from .mapper import Mapper
104 from .path_registry import PathRegistry
105 from .session import _PKIdentityArgument
106 from .session import Session
107 from .state import InstanceState
108 from ..engine.cursor import CursorResult
109 from ..engine.interfaces import _ImmutableExecuteOptions
110 from ..engine.interfaces import CompiledCacheType
111 from ..engine.interfaces import IsolationLevel
112 from ..engine.interfaces import SchemaTranslateMapType
113 from ..engine.result import FrozenResult
114 from ..engine.result import ScalarResult
115 from ..sql._typing import _ColumnExpressionArgument
116 from ..sql._typing import _ColumnExpressionOrStrLabelArgument
117 from ..sql._typing import _ColumnsClauseArgument
118 from ..sql._typing import _DMLColumnArgument
119 from ..sql._typing import _JoinTargetArgument
120 from ..sql._typing import _LimitOffsetType
121 from ..sql._typing import _MAYBE_ENTITY
122 from ..sql._typing import _no_kw
123 from ..sql._typing import _NOT_ENTITY
124 from ..sql._typing import _OnClauseArgument
125 from ..sql._typing import _PropagateAttrsType
126 from ..sql._typing import _T0
127 from ..sql._typing import _T1
128 from ..sql._typing import _T2
129 from ..sql._typing import _T3
130 from ..sql._typing import _T4
131 from ..sql._typing import _T5
132 from ..sql._typing import _T6
133 from ..sql._typing import _T7
134 from ..sql._typing import _TypedColumnClauseArgument as _TCCA
135 from ..sql.base import CacheableOptions
136 from ..sql.base import ExecutableOption
137 from ..sql.dml import UpdateBase
138 from ..sql.elements import ColumnElement
139 from ..sql.elements import Label
140 from ..sql.selectable import _ForUpdateOfArgument
141 from ..sql.selectable import _JoinTargetElement
142 from ..sql.selectable import _SetupJoinsElement
143 from ..sql.selectable import Alias
144 from ..sql.selectable import CTE
145 from ..sql.selectable import ExecutableReturnsRows
146 from ..sql.selectable import FromClause
147 from ..sql.selectable import ScalarSelect
148 from ..sql.selectable import Subquery
149
150
151__all__ = ["Query", "QueryContext"]
152
153_T = TypeVar("_T", bound=Any)
154
155
156@inspection._self_inspects
157@log.class_logger
158class Query(
159 _SelectFromElements,
160 SupportsCloneAnnotations,
161 HasPrefixes,
162 HasSuffixes,
163 HasHints,
164 EventTarget,
165 log.Identified,
166 Generative,
167 Executable,
168 Generic[_T],
169):
170 """ORM-level SQL construction object.
171
172 .. legacy:: The ORM :class:`.Query` object is a legacy construct
173 as of SQLAlchemy 2.0. See the notes at the top of
174 :ref:`query_api_toplevel` for an overview, including links to migration
175 documentation.
176
177 :class:`_query.Query` objects are normally initially generated using the
178 :meth:`~.Session.query` method of :class:`.Session`, and in
179 less common cases by instantiating the :class:`_query.Query` directly and
180 associating with a :class:`.Session` using the
181 :meth:`_query.Query.with_session`
182 method.
183
184 """
185
186 # elements that are in Core and can be cached in the same way
187 _where_criteria: Tuple[ColumnElement[Any], ...] = ()
188 _having_criteria: Tuple[ColumnElement[Any], ...] = ()
189
190 _order_by_clauses: Tuple[ColumnElement[Any], ...] = ()
191 _group_by_clauses: Tuple[ColumnElement[Any], ...] = ()
192 _limit_clause: Optional[ColumnElement[Any]] = None
193 _offset_clause: Optional[ColumnElement[Any]] = None
194
195 _distinct: bool = False
196 _distinct_on: Tuple[ColumnElement[Any], ...] = ()
197
198 _for_update_arg: Optional[ForUpdateArg] = None
199 _correlate: Tuple[FromClause, ...] = ()
200 _auto_correlate: bool = True
201 _from_obj: Tuple[FromClause, ...] = ()
202 _setup_joins: Tuple[_SetupJoinsElement, ...] = ()
203
204 _label_style: SelectLabelStyle = SelectLabelStyle.LABEL_STYLE_LEGACY_ORM
205
206 _memoized_select_entities = ()
207
208 _compile_options: Union[Type[CacheableOptions], CacheableOptions] = (
209 ORMCompileState.default_compile_options
210 )
211
212 _with_options: Tuple[ExecutableOption, ...]
213 load_options = QueryContext.default_load_options + {
214 "_legacy_uniquing": True
215 }
216
217 _params: util.immutabledict[str, Any] = util.EMPTY_DICT
218
219 # local Query builder state, not needed for
220 # compilation or execution
221 _enable_assertions = True
222
223 _statement: Optional[ExecutableReturnsRows] = None
224
225 session: Session
226
227 dispatch: dispatcher[Query[_T]]
228
229 # mirrors that of ClauseElement, used to propagate the "orm"
230 # plugin as well as the "subject" of the plugin, e.g. the mapper
231 # we are querying against.
232 @util.memoized_property
233 def _propagate_attrs(self) -> _PropagateAttrsType:
234 return util.EMPTY_DICT
235
236 def __init__(
237 self,
238 entities: Union[
239 _ColumnsClauseArgument[Any], Sequence[_ColumnsClauseArgument[Any]]
240 ],
241 session: Optional[Session] = None,
242 ):
243 """Construct a :class:`_query.Query` directly.
244
245 E.g.::
246
247 q = Query([User, Address], session=some_session)
248
249 The above is equivalent to::
250
251 q = some_session.query(User, Address)
252
253 :param entities: a sequence of entities and/or SQL expressions.
254
255 :param session: a :class:`.Session` with which the
256 :class:`_query.Query`
257 will be associated. Optional; a :class:`_query.Query`
258 can be associated
259 with a :class:`.Session` generatively via the
260 :meth:`_query.Query.with_session` method as well.
261
262 .. seealso::
263
264 :meth:`.Session.query`
265
266 :meth:`_query.Query.with_session`
267
268 """
269
270 # session is usually present. There's one case in subqueryloader
271 # where it stores a Query without a Session and also there are tests
272 # for the query(Entity).with_session(session) API which is likely in
273 # some old recipes, however these are legacy as select() can now be
274 # used.
275 self.session = session # type: ignore
276 self._set_entities(entities)
277
278 def _set_propagate_attrs(self, values: Mapping[str, Any]) -> Self:
279 self._propagate_attrs = util.immutabledict(values)
280 return self
281
282 def _set_entities(
283 self,
284 entities: Union[
285 _ColumnsClauseArgument[Any], Iterable[_ColumnsClauseArgument[Any]]
286 ],
287 ) -> None:
288 self._raw_columns = [
289 coercions.expect(
290 roles.ColumnsClauseRole,
291 ent,
292 apply_propagate_attrs=self,
293 post_inspect=True,
294 )
295 for ent in util.to_list(entities)
296 ]
297
298 def tuples(self: Query[_O]) -> Query[Tuple[_O]]:
299 """return a tuple-typed form of this :class:`.Query`.
300
301 This method invokes the :meth:`.Query.only_return_tuples`
302 method with a value of ``True``, which by itself ensures that this
303 :class:`.Query` will always return :class:`.Row` objects, even
304 if the query is made against a single entity. It then also
305 at the typing level will return a "typed" query, if possible,
306 that will type result rows as ``Tuple`` objects with typed
307 elements.
308
309 This method can be compared to the :meth:`.Result.tuples` method,
310 which returns "self", but from a typing perspective returns an object
311 that will yield typed ``Tuple`` objects for results. Typing
312 takes effect only if this :class:`.Query` object is a typed
313 query object already.
314
315 .. versionadded:: 2.0
316
317 .. seealso::
318
319 :meth:`.Result.tuples` - v2 equivalent method.
320
321 """
322 return self.only_return_tuples(True) # type: ignore
323
324 def _entity_from_pre_ent_zero(self) -> Optional[_InternalEntityType[Any]]:
325 if not self._raw_columns:
326 return None
327
328 ent = self._raw_columns[0]
329
330 if "parententity" in ent._annotations:
331 return ent._annotations["parententity"] # type: ignore
332 elif "bundle" in ent._annotations:
333 return ent._annotations["bundle"] # type: ignore
334 else:
335 # label, other SQL expression
336 for element in visitors.iterate(ent):
337 if "parententity" in element._annotations:
338 return element._annotations["parententity"] # type: ignore # noqa: E501
339 else:
340 return None
341
342 def _only_full_mapper_zero(self, methname: str) -> Mapper[Any]:
343 if (
344 len(self._raw_columns) != 1
345 or "parententity" not in self._raw_columns[0]._annotations
346 or not self._raw_columns[0].is_selectable
347 ):
348 raise sa_exc.InvalidRequestError(
349 "%s() can only be used against "
350 "a single mapped class." % methname
351 )
352
353 return self._raw_columns[0]._annotations["parententity"] # type: ignore # noqa: E501
354
355 def _set_select_from(
356 self, obj: Iterable[_FromClauseArgument], set_base_alias: bool
357 ) -> None:
358 fa = [
359 coercions.expect(
360 roles.StrictFromClauseRole,
361 elem,
362 allow_select=True,
363 apply_propagate_attrs=self,
364 )
365 for elem in obj
366 ]
367
368 self._compile_options += {"_set_base_alias": set_base_alias}
369 self._from_obj = tuple(fa)
370
371 @_generative
372 def _set_lazyload_from(self, state: InstanceState[Any]) -> Self:
373 self.load_options += {"_lazy_loaded_from": state}
374 return self
375
376 def _get_condition(self) -> None:
377 """used by legacy BakedQuery"""
378 self._no_criterion_condition("get", order_by=False, distinct=False)
379
380 def _get_existing_condition(self) -> None:
381 self._no_criterion_assertion("get", order_by=False, distinct=False)
382
383 def _no_criterion_assertion(
384 self, meth: str, order_by: bool = True, distinct: bool = True
385 ) -> None:
386 if not self._enable_assertions:
387 return
388 if (
389 self._where_criteria
390 or self._statement is not None
391 or self._from_obj
392 or self._setup_joins
393 or self._limit_clause is not None
394 or self._offset_clause is not None
395 or self._group_by_clauses
396 or (order_by and self._order_by_clauses)
397 or (distinct and self._distinct)
398 ):
399 raise sa_exc.InvalidRequestError(
400 "Query.%s() being called on a "
401 "Query with existing criterion. " % meth
402 )
403
404 def _no_criterion_condition(
405 self, meth: str, order_by: bool = True, distinct: bool = True
406 ) -> None:
407 self._no_criterion_assertion(meth, order_by, distinct)
408
409 self._from_obj = self._setup_joins = ()
410 if self._statement is not None:
411 self._compile_options += {"_statement": None}
412 self._where_criteria = ()
413 self._distinct = False
414
415 self._order_by_clauses = self._group_by_clauses = ()
416
417 def _no_clauseelement_condition(self, meth: str) -> None:
418 if not self._enable_assertions:
419 return
420 if self._order_by_clauses:
421 raise sa_exc.InvalidRequestError(
422 "Query.%s() being called on a "
423 "Query with existing criterion. " % meth
424 )
425 self._no_criterion_condition(meth)
426
427 def _no_statement_condition(self, meth: str) -> None:
428 if not self._enable_assertions:
429 return
430 if self._statement is not None:
431 raise sa_exc.InvalidRequestError(
432 (
433 "Query.%s() being called on a Query with an existing full "
434 "statement - can't apply criterion."
435 )
436 % meth
437 )
438
439 def _no_limit_offset(self, meth: str) -> None:
440 if not self._enable_assertions:
441 return
442 if self._limit_clause is not None or self._offset_clause is not None:
443 raise sa_exc.InvalidRequestError(
444 "Query.%s() being called on a Query which already has LIMIT "
445 "or OFFSET applied. Call %s() before limit() or offset() "
446 "are applied." % (meth, meth)
447 )
448
449 @property
450 def _has_row_limiting_clause(self) -> bool:
451 return (
452 self._limit_clause is not None or self._offset_clause is not None
453 )
454
455 def _get_options(
456 self,
457 populate_existing: Optional[bool] = None,
458 version_check: Optional[bool] = None,
459 only_load_props: Optional[Sequence[str]] = None,
460 refresh_state: Optional[InstanceState[Any]] = None,
461 identity_token: Optional[Any] = None,
462 ) -> Self:
463 load_options: Dict[str, Any] = {}
464 compile_options: Dict[str, Any] = {}
465
466 if version_check:
467 load_options["_version_check"] = version_check
468 if populate_existing:
469 load_options["_populate_existing"] = populate_existing
470 if refresh_state:
471 load_options["_refresh_state"] = refresh_state
472 compile_options["_for_refresh_state"] = True
473 if only_load_props:
474 compile_options["_only_load_props"] = frozenset(only_load_props)
475 if identity_token:
476 load_options["_identity_token"] = identity_token
477
478 if load_options:
479 self.load_options += load_options
480 if compile_options:
481 self._compile_options += compile_options
482
483 return self
484
485 def _clone(self, **kw: Any) -> Self:
486 return self._generate()
487
488 def _get_select_statement_only(self) -> Select[_T]:
489 if self._statement is not None:
490 raise sa_exc.InvalidRequestError(
491 "Can't call this method on a Query that uses from_statement()"
492 )
493 return cast("Select[_T]", self.statement)
494
495 @property
496 def statement(self) -> Union[Select[_T], FromStatement[_T], UpdateBase]:
497 """The full SELECT statement represented by this Query.
498
499 The statement by default will not have disambiguating labels
500 applied to the construct unless with_labels(True) is called
501 first.
502
503 """
504
505 # .statement can return the direct future.Select() construct here, as
506 # long as we are not using subsequent adaption features that
507 # are made against raw entities, e.g. from_self(), with_polymorphic(),
508 # select_entity_from(). If these features are being used, then
509 # the Select() we return will not have the correct .selected_columns
510 # collection and will not embed in subsequent queries correctly.
511 # We could find a way to make this collection "correct", however
512 # this would not be too different from doing the full compile as
513 # we are doing in any case, the Select() would still not have the
514 # proper state for other attributes like whereclause, order_by,
515 # and these features are all deprecated in any case.
516 #
517 # for these reasons, Query is not a Select, it remains an ORM
518 # object for which __clause_element__() must be called in order for
519 # it to provide a real expression object.
520 #
521 # from there, it starts to look much like Query itself won't be
522 # passed into the execute process and won't generate its own cache
523 # key; this will all occur in terms of the ORM-enabled Select.
524 stmt: Union[Select[_T], FromStatement[_T], UpdateBase]
525
526 if not self._compile_options._set_base_alias:
527 # if we don't have legacy top level aliasing features in use
528 # then convert to a future select() directly
529 stmt = self._statement_20(for_statement=True)
530 else:
531 stmt = self._compile_state(for_statement=True).statement
532
533 if self._params:
534 stmt = stmt.params(self._params)
535
536 return stmt
537
538 def _final_statement(self, legacy_query_style: bool = True) -> Select[Any]:
539 """Return the 'final' SELECT statement for this :class:`.Query`.
540
541 This is used by the testing suite only and is fairly inefficient.
542
543 This is the Core-only select() that will be rendered by a complete
544 compilation of this query, and is what .statement used to return
545 in 1.3.
546
547
548 """
549
550 q = self._clone()
551
552 return q._compile_state(
553 use_legacy_query_style=legacy_query_style
554 ).statement # type: ignore
555
556 def _statement_20(
557 self, for_statement: bool = False, use_legacy_query_style: bool = True
558 ) -> Union[Select[_T], FromStatement[_T]]:
559 # TODO: this event needs to be deprecated, as it currently applies
560 # only to ORM query and occurs at this spot that is now more
561 # or less an artificial spot
562 if self.dispatch.before_compile:
563 for fn in self.dispatch.before_compile:
564 new_query = fn(self)
565 if new_query is not None and new_query is not self:
566 self = new_query
567 if not fn._bake_ok: # type: ignore
568 self._compile_options += {"_bake_ok": False}
569
570 compile_options = self._compile_options
571 compile_options += {
572 "_for_statement": for_statement,
573 "_use_legacy_query_style": use_legacy_query_style,
574 }
575
576 stmt: Union[Select[_T], FromStatement[_T]]
577
578 if self._statement is not None:
579 stmt = FromStatement(self._raw_columns, self._statement)
580 stmt.__dict__.update(
581 _with_options=self._with_options,
582 _with_context_options=self._with_context_options,
583 _compile_options=compile_options,
584 _execution_options=self._execution_options,
585 _propagate_attrs=self._propagate_attrs,
586 )
587 else:
588 # Query / select() internal attributes are 99% cross-compatible
589 stmt = Select._create_raw_select(**self.__dict__)
590 stmt.__dict__.update(
591 _label_style=self._label_style,
592 _compile_options=compile_options,
593 _propagate_attrs=self._propagate_attrs,
594 )
595 stmt.__dict__.pop("session", None)
596
597 # ensure the ORM context is used to compile the statement, even
598 # if it has no ORM entities. This is so ORM-only things like
599 # _legacy_joins are picked up that wouldn't be picked up by the
600 # Core statement context
601 if "compile_state_plugin" not in stmt._propagate_attrs:
602 stmt._propagate_attrs = stmt._propagate_attrs.union(
603 {"compile_state_plugin": "orm", "plugin_subject": None}
604 )
605
606 return stmt
607
608 def subquery(
609 self,
610 name: Optional[str] = None,
611 with_labels: bool = False,
612 reduce_columns: bool = False,
613 ) -> Subquery:
614 """Return the full SELECT statement represented by
615 this :class:`_query.Query`, embedded within an
616 :class:`_expression.Alias`.
617
618 Eager JOIN generation within the query is disabled.
619
620 .. seealso::
621
622 :meth:`_sql.Select.subquery` - v2 comparable method.
623
624 :param name: string name to be assigned as the alias;
625 this is passed through to :meth:`_expression.FromClause.alias`.
626 If ``None``, a name will be deterministically generated
627 at compile time.
628
629 :param with_labels: if True, :meth:`.with_labels` will be called
630 on the :class:`_query.Query` first to apply table-qualified labels
631 to all columns.
632
633 :param reduce_columns: if True,
634 :meth:`_expression.Select.reduce_columns` will
635 be called on the resulting :func:`_expression.select` construct,
636 to remove same-named columns where one also refers to the other
637 via foreign key or WHERE clause equivalence.
638
639 """
640 q = self.enable_eagerloads(False)
641 if with_labels:
642 q = q.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
643
644 stmt = q._get_select_statement_only()
645
646 if TYPE_CHECKING:
647 assert isinstance(stmt, Select)
648
649 if reduce_columns:
650 stmt = stmt.reduce_columns()
651 return stmt.subquery(name=name)
652
653 def cte(
654 self,
655 name: Optional[str] = None,
656 recursive: bool = False,
657 nesting: bool = False,
658 ) -> CTE:
659 r"""Return the full SELECT statement represented by this
660 :class:`_query.Query` represented as a common table expression (CTE).
661
662 Parameters and usage are the same as those of the
663 :meth:`_expression.SelectBase.cte` method; see that method for
664 further details.
665
666 Here is the `PostgreSQL WITH
667 RECURSIVE example
668 <https://www.postgresql.org/docs/current/static/queries-with.html>`_.
669 Note that, in this example, the ``included_parts`` cte and the
670 ``incl_alias`` alias of it are Core selectables, which
671 means the columns are accessed via the ``.c.`` attribute. The
672 ``parts_alias`` object is an :func:`_orm.aliased` instance of the
673 ``Part`` entity, so column-mapped attributes are available
674 directly::
675
676 from sqlalchemy.orm import aliased
677
678
679 class Part(Base):
680 __tablename__ = "part"
681 part = Column(String, primary_key=True)
682 sub_part = Column(String, primary_key=True)
683 quantity = Column(Integer)
684
685
686 included_parts = (
687 session.query(Part.sub_part, Part.part, Part.quantity)
688 .filter(Part.part == "our part")
689 .cte(name="included_parts", recursive=True)
690 )
691
692 incl_alias = aliased(included_parts, name="pr")
693 parts_alias = aliased(Part, name="p")
694 included_parts = included_parts.union_all(
695 session.query(
696 parts_alias.sub_part, parts_alias.part, parts_alias.quantity
697 ).filter(parts_alias.part == incl_alias.c.sub_part)
698 )
699
700 q = session.query(
701 included_parts.c.sub_part,
702 func.sum(included_parts.c.quantity).label("total_quantity"),
703 ).group_by(included_parts.c.sub_part)
704
705 .. seealso::
706
707 :meth:`_sql.Select.cte` - v2 equivalent method.
708
709 """ # noqa: E501
710 return (
711 self.enable_eagerloads(False)
712 ._get_select_statement_only()
713 .cte(name=name, recursive=recursive, nesting=nesting)
714 )
715
716 def label(self, name: Optional[str]) -> Label[Any]:
717 """Return the full SELECT statement represented by this
718 :class:`_query.Query`, converted
719 to a scalar subquery with a label of the given name.
720
721 .. seealso::
722
723 :meth:`_sql.Select.label` - v2 comparable method.
724
725 """
726
727 return (
728 self.enable_eagerloads(False)
729 ._get_select_statement_only()
730 .label(name)
731 )
732
733 @overload
734 def as_scalar( # type: ignore[overload-overlap]
735 self: Query[Tuple[_MAYBE_ENTITY]],
736 ) -> ScalarSelect[_MAYBE_ENTITY]: ...
737
738 @overload
739 def as_scalar(
740 self: Query[Tuple[_NOT_ENTITY]],
741 ) -> ScalarSelect[_NOT_ENTITY]: ...
742
743 @overload
744 def as_scalar(self) -> ScalarSelect[Any]: ...
745
746 @util.deprecated(
747 "1.4",
748 "The :meth:`_query.Query.as_scalar` method is deprecated and will be "
749 "removed in a future release. Please refer to "
750 ":meth:`_query.Query.scalar_subquery`.",
751 )
752 def as_scalar(self) -> ScalarSelect[Any]:
753 """Return the full SELECT statement represented by this
754 :class:`_query.Query`, converted to a scalar subquery.
755
756 """
757 return self.scalar_subquery()
758
759 @overload
760 def scalar_subquery(
761 self: Query[Tuple[_MAYBE_ENTITY]],
762 ) -> ScalarSelect[Any]: ...
763
764 @overload
765 def scalar_subquery(
766 self: Query[Tuple[_NOT_ENTITY]],
767 ) -> ScalarSelect[_NOT_ENTITY]: ...
768
769 @overload
770 def scalar_subquery(self) -> ScalarSelect[Any]: ...
771
772 def scalar_subquery(self) -> ScalarSelect[Any]:
773 """Return the full SELECT statement represented by this
774 :class:`_query.Query`, converted to a scalar subquery.
775
776 Analogous to
777 :meth:`sqlalchemy.sql.expression.SelectBase.scalar_subquery`.
778
779 .. versionchanged:: 1.4 The :meth:`_query.Query.scalar_subquery`
780 method replaces the :meth:`_query.Query.as_scalar` method.
781
782 .. seealso::
783
784 :meth:`_sql.Select.scalar_subquery` - v2 comparable method.
785
786 """
787
788 return (
789 self.enable_eagerloads(False)
790 ._get_select_statement_only()
791 .scalar_subquery()
792 )
793
794 @property
795 def selectable(self) -> Union[Select[_T], FromStatement[_T], UpdateBase]:
796 """Return the :class:`_expression.Select` object emitted by this
797 :class:`_query.Query`.
798
799 Used for :func:`_sa.inspect` compatibility, this is equivalent to::
800
801 query.enable_eagerloads(False).with_labels().statement
802
803 """
804 return self.__clause_element__()
805
806 def __clause_element__(
807 self,
808 ) -> Union[Select[_T], FromStatement[_T], UpdateBase]:
809 return (
810 self._with_compile_options(
811 _enable_eagerloads=False, _render_for_subquery=True
812 )
813 .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
814 .statement
815 )
816
817 @overload
818 def only_return_tuples(
819 self: Query[_O], value: Literal[True]
820 ) -> RowReturningQuery[Tuple[_O]]: ...
821
822 @overload
823 def only_return_tuples(
824 self: Query[_O], value: Literal[False]
825 ) -> Query[_O]: ...
826
827 @_generative
828 def only_return_tuples(self, value: bool) -> Query[Any]:
829 """When set to True, the query results will always be a
830 :class:`.Row` object.
831
832 This can change a query that normally returns a single entity
833 as a scalar to return a :class:`.Row` result in all cases.
834
835 .. seealso::
836
837 :meth:`.Query.tuples` - returns tuples, but also at the typing
838 level will type results as ``Tuple``.
839
840 :meth:`_query.Query.is_single_entity`
841
842 :meth:`_engine.Result.tuples` - v2 comparable method.
843
844 """
845 self.load_options += dict(_only_return_tuples=value)
846 return self
847
848 @property
849 def is_single_entity(self) -> bool:
850 """Indicates if this :class:`_query.Query`
851 returns tuples or single entities.
852
853 Returns True if this query returns a single entity for each instance
854 in its result list, and False if this query returns a tuple of entities
855 for each result.
856
857 .. versionadded:: 1.3.11
858
859 .. seealso::
860
861 :meth:`_query.Query.only_return_tuples`
862
863 """
864 return (
865 not self.load_options._only_return_tuples
866 and len(self._raw_columns) == 1
867 and "parententity" in self._raw_columns[0]._annotations
868 and isinstance(
869 self._raw_columns[0]._annotations["parententity"],
870 ORMColumnsClauseRole,
871 )
872 )
873
874 @_generative
875 def enable_eagerloads(self, value: bool) -> Self:
876 """Control whether or not eager joins and subqueries are
877 rendered.
878
879 When set to False, the returned Query will not render
880 eager joins regardless of :func:`~sqlalchemy.orm.joinedload`,
881 :func:`~sqlalchemy.orm.subqueryload` options
882 or mapper-level ``lazy='joined'``/``lazy='subquery'``
883 configurations.
884
885 This is used primarily when nesting the Query's
886 statement into a subquery or other
887 selectable, or when using :meth:`_query.Query.yield_per`.
888
889 """
890 self._compile_options += {"_enable_eagerloads": value}
891 return self
892
893 @_generative
894 def _with_compile_options(self, **opt: Any) -> Self:
895 self._compile_options += opt
896 return self
897
898 @util.became_legacy_20(
899 ":meth:`_orm.Query.with_labels` and :meth:`_orm.Query.apply_labels`",
900 alternative="Use set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) "
901 "instead.",
902 )
903 def with_labels(self) -> Self:
904 return self.set_label_style(
905 SelectLabelStyle.LABEL_STYLE_TABLENAME_PLUS_COL
906 )
907
908 apply_labels = with_labels
909
910 @property
911 def get_label_style(self) -> SelectLabelStyle:
912 """
913 Retrieve the current label style.
914
915 .. versionadded:: 1.4
916
917 .. seealso::
918
919 :meth:`_sql.Select.get_label_style` - v2 equivalent method.
920
921 """
922 return self._label_style
923
924 def set_label_style(self, style: SelectLabelStyle) -> Self:
925 """Apply column labels to the return value of Query.statement.
926
927 Indicates that this Query's `statement` accessor should return
928 a SELECT statement that applies labels to all columns in the
929 form <tablename>_<columnname>; this is commonly used to
930 disambiguate columns from multiple tables which have the same
931 name.
932
933 When the `Query` actually issues SQL to load rows, it always
934 uses column labeling.
935
936 .. note:: The :meth:`_query.Query.set_label_style` method *only* applies
937 the output of :attr:`_query.Query.statement`, and *not* to any of
938 the result-row invoking systems of :class:`_query.Query` itself,
939 e.g.
940 :meth:`_query.Query.first`, :meth:`_query.Query.all`, etc.
941 To execute
942 a query using :meth:`_query.Query.set_label_style`, invoke the
943 :attr:`_query.Query.statement` using :meth:`.Session.execute`::
944
945 result = session.execute(
946 query.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL).statement
947 )
948
949 .. versionadded:: 1.4
950
951
952 .. seealso::
953
954 :meth:`_sql.Select.set_label_style` - v2 equivalent method.
955
956 """ # noqa
957 if self._label_style is not style:
958 self = self._generate()
959 self._label_style = style
960 return self
961
962 @_generative
963 def enable_assertions(self, value: bool) -> Self:
964 """Control whether assertions are generated.
965
966 When set to False, the returned Query will
967 not assert its state before certain operations,
968 including that LIMIT/OFFSET has not been applied
969 when filter() is called, no criterion exists
970 when get() is called, and no "from_statement()"
971 exists when filter()/order_by()/group_by() etc.
972 is called. This more permissive mode is used by
973 custom Query subclasses to specify criterion or
974 other modifiers outside of the usual usage patterns.
975
976 Care should be taken to ensure that the usage
977 pattern is even possible. A statement applied
978 by from_statement() will override any criterion
979 set by filter() or order_by(), for example.
980
981 """
982 self._enable_assertions = value
983 return self
984
985 @property
986 def whereclause(self) -> Optional[ColumnElement[bool]]:
987 """A readonly attribute which returns the current WHERE criterion for
988 this Query.
989
990 This returned value is a SQL expression construct, or ``None`` if no
991 criterion has been established.
992
993 .. seealso::
994
995 :attr:`_sql.Select.whereclause` - v2 equivalent property.
996
997 """
998 return BooleanClauseList._construct_for_whereclause(
999 self._where_criteria
1000 )
1001
1002 @_generative
1003 def _with_current_path(self, path: PathRegistry) -> Self:
1004 """indicate that this query applies to objects loaded
1005 within a certain path.
1006
1007 Used by deferred loaders (see strategies.py) which transfer
1008 query options from an originating query to a newly generated
1009 query intended for the deferred load.
1010
1011 """
1012 self._compile_options += {"_current_path": path}
1013 return self
1014
1015 @_generative
1016 def yield_per(self, count: int) -> Self:
1017 r"""Yield only ``count`` rows at a time.
1018
1019 The purpose of this method is when fetching very large result sets
1020 (> 10K rows), to batch results in sub-collections and yield them
1021 out partially, so that the Python interpreter doesn't need to declare
1022 very large areas of memory which is both time consuming and leads
1023 to excessive memory use. The performance from fetching hundreds of
1024 thousands of rows can often double when a suitable yield-per setting
1025 (e.g. approximately 1000) is used, even with DBAPIs that buffer
1026 rows (which are most).
1027
1028 As of SQLAlchemy 1.4, the :meth:`_orm.Query.yield_per` method is
1029 equivalent to using the ``yield_per`` execution option at the ORM
1030 level. See the section :ref:`orm_queryguide_yield_per` for further
1031 background on this option.
1032
1033 .. seealso::
1034
1035 :ref:`orm_queryguide_yield_per`
1036
1037 """
1038 self.load_options += {"_yield_per": count}
1039 return self
1040
1041 @util.became_legacy_20(
1042 ":meth:`_orm.Query.get`",
1043 alternative="The method is now available as :meth:`_orm.Session.get`",
1044 )
1045 def get(self, ident: _PKIdentityArgument) -> Optional[Any]:
1046 """Return an instance based on the given primary key identifier,
1047 or ``None`` if not found.
1048
1049 E.g.::
1050
1051 my_user = session.query(User).get(5)
1052
1053 some_object = session.query(VersionedFoo).get((5, 10))
1054
1055 some_object = session.query(VersionedFoo).get({"id": 5, "version_id": 10})
1056
1057 :meth:`_query.Query.get` is special in that it provides direct
1058 access to the identity map of the owning :class:`.Session`.
1059 If the given primary key identifier is present
1060 in the local identity map, the object is returned
1061 directly from this collection and no SQL is emitted,
1062 unless the object has been marked fully expired.
1063 If not present,
1064 a SELECT is performed in order to locate the object.
1065
1066 :meth:`_query.Query.get` also will perform a check if
1067 the object is present in the identity map and
1068 marked as expired - a SELECT
1069 is emitted to refresh the object as well as to
1070 ensure that the row is still present.
1071 If not, :class:`~sqlalchemy.orm.exc.ObjectDeletedError` is raised.
1072
1073 :meth:`_query.Query.get` is only used to return a single
1074 mapped instance, not multiple instances or
1075 individual column constructs, and strictly
1076 on a single primary key value. The originating
1077 :class:`_query.Query` must be constructed in this way,
1078 i.e. against a single mapped entity,
1079 with no additional filtering criterion. Loading
1080 options via :meth:`_query.Query.options` may be applied
1081 however, and will be used if the object is not
1082 yet locally present.
1083
1084 :param ident: A scalar, tuple, or dictionary representing the
1085 primary key. For a composite (e.g. multiple column) primary key,
1086 a tuple or dictionary should be passed.
1087
1088 For a single-column primary key, the scalar calling form is typically
1089 the most expedient. If the primary key of a row is the value "5",
1090 the call looks like::
1091
1092 my_object = query.get(5)
1093
1094 The tuple form contains primary key values typically in
1095 the order in which they correspond to the mapped
1096 :class:`_schema.Table`
1097 object's primary key columns, or if the
1098 :paramref:`_orm.Mapper.primary_key` configuration parameter were
1099 used, in
1100 the order used for that parameter. For example, if the primary key
1101 of a row is represented by the integer
1102 digits "5, 10" the call would look like::
1103
1104 my_object = query.get((5, 10))
1105
1106 The dictionary form should include as keys the mapped attribute names
1107 corresponding to each element of the primary key. If the mapped class
1108 has the attributes ``id``, ``version_id`` as the attributes which
1109 store the object's primary key value, the call would look like::
1110
1111 my_object = query.get({"id": 5, "version_id": 10})
1112
1113 .. versionadded:: 1.3 the :meth:`_query.Query.get`
1114 method now optionally
1115 accepts a dictionary of attribute names to values in order to
1116 indicate a primary key identifier.
1117
1118
1119 :return: The object instance, or ``None``.
1120
1121 """ # noqa: E501
1122 self._no_criterion_assertion("get", order_by=False, distinct=False)
1123
1124 # we still implement _get_impl() so that baked query can override
1125 # it
1126 return self._get_impl(ident, loading.load_on_pk_identity)
1127
1128 def _get_impl(
1129 self,
1130 primary_key_identity: _PKIdentityArgument,
1131 db_load_fn: Callable[..., Any],
1132 identity_token: Optional[Any] = None,
1133 ) -> Optional[Any]:
1134 mapper = self._only_full_mapper_zero("get")
1135 return self.session._get_impl(
1136 mapper,
1137 primary_key_identity,
1138 db_load_fn,
1139 populate_existing=self.load_options._populate_existing,
1140 with_for_update=self._for_update_arg,
1141 options=self._with_options,
1142 identity_token=identity_token,
1143 execution_options=self._execution_options,
1144 )
1145
1146 @property
1147 def lazy_loaded_from(self) -> Optional[InstanceState[Any]]:
1148 """An :class:`.InstanceState` that is using this :class:`_query.Query`
1149 for a lazy load operation.
1150
1151 .. deprecated:: 1.4 This attribute should be viewed via the
1152 :attr:`.ORMExecuteState.lazy_loaded_from` attribute, within
1153 the context of the :meth:`.SessionEvents.do_orm_execute`
1154 event.
1155
1156 .. seealso::
1157
1158 :attr:`.ORMExecuteState.lazy_loaded_from`
1159
1160 """
1161 return self.load_options._lazy_loaded_from # type: ignore
1162
1163 @property
1164 def _current_path(self) -> PathRegistry:
1165 return self._compile_options._current_path # type: ignore
1166
1167 @_generative
1168 def correlate(
1169 self,
1170 *fromclauses: Union[Literal[None, False], _FromClauseArgument],
1171 ) -> Self:
1172 """Return a :class:`.Query` construct which will correlate the given
1173 FROM clauses to that of an enclosing :class:`.Query` or
1174 :func:`~.expression.select`.
1175
1176 The method here accepts mapped classes, :func:`.aliased` constructs,
1177 and :class:`_orm.Mapper` constructs as arguments, which are resolved
1178 into expression constructs, in addition to appropriate expression
1179 constructs.
1180
1181 The correlation arguments are ultimately passed to
1182 :meth:`_expression.Select.correlate`
1183 after coercion to expression constructs.
1184
1185 The correlation arguments take effect in such cases
1186 as when :meth:`_query.Query.from_self` is used, or when
1187 a subquery as returned by :meth:`_query.Query.subquery` is
1188 embedded in another :func:`_expression.select` construct.
1189
1190 .. seealso::
1191
1192 :meth:`_sql.Select.correlate` - v2 equivalent method.
1193
1194 """
1195
1196 self._auto_correlate = False
1197 if fromclauses and fromclauses[0] in {None, False}:
1198 self._correlate = ()
1199 else:
1200 self._correlate = self._correlate + tuple(
1201 coercions.expect(roles.FromClauseRole, f) for f in fromclauses
1202 )
1203 return self
1204
1205 @_generative
1206 def autoflush(self, setting: bool) -> Self:
1207 """Return a Query with a specific 'autoflush' setting.
1208
1209 As of SQLAlchemy 1.4, the :meth:`_orm.Query.autoflush` method
1210 is equivalent to using the ``autoflush`` execution option at the
1211 ORM level. See the section :ref:`orm_queryguide_autoflush` for
1212 further background on this option.
1213
1214 """
1215 self.load_options += {"_autoflush": setting}
1216 return self
1217
1218 @_generative
1219 def populate_existing(self) -> Self:
1220 """Return a :class:`_query.Query`
1221 that will expire and refresh all instances
1222 as they are loaded, or reused from the current :class:`.Session`.
1223
1224 As of SQLAlchemy 1.4, the :meth:`_orm.Query.populate_existing` method
1225 is equivalent to using the ``populate_existing`` execution option at
1226 the ORM level. See the section :ref:`orm_queryguide_populate_existing`
1227 for further background on this option.
1228
1229 """
1230 self.load_options += {"_populate_existing": True}
1231 return self
1232
1233 @_generative
1234 def _with_invoke_all_eagers(self, value: bool) -> Self:
1235 """Set the 'invoke all eagers' flag which causes joined- and
1236 subquery loaders to traverse into already-loaded related objects
1237 and collections.
1238
1239 Default is that of :attr:`_query.Query._invoke_all_eagers`.
1240
1241 """
1242 self.load_options += {"_invoke_all_eagers": value}
1243 return self
1244
1245 @util.became_legacy_20(
1246 ":meth:`_orm.Query.with_parent`",
1247 alternative="Use the :func:`_orm.with_parent` standalone construct.",
1248 )
1249 @util.preload_module("sqlalchemy.orm.relationships")
1250 def with_parent(
1251 self,
1252 instance: object,
1253 property: Optional[ # noqa: A002
1254 attributes.QueryableAttribute[Any]
1255 ] = None,
1256 from_entity: Optional[_ExternalEntityType[Any]] = None,
1257 ) -> Self:
1258 """Add filtering criterion that relates the given instance
1259 to a child object or collection, using its attribute state
1260 as well as an established :func:`_orm.relationship()`
1261 configuration.
1262
1263 The method uses the :func:`.with_parent` function to generate
1264 the clause, the result of which is passed to
1265 :meth:`_query.Query.filter`.
1266
1267 Parameters are the same as :func:`.with_parent`, with the exception
1268 that the given property can be None, in which case a search is
1269 performed against this :class:`_query.Query` object's target mapper.
1270
1271 :param instance:
1272 An instance which has some :func:`_orm.relationship`.
1273
1274 :param property:
1275 Class bound attribute which indicates
1276 what relationship from the instance should be used to reconcile the
1277 parent/child relationship.
1278
1279 :param from_entity:
1280 Entity in which to consider as the left side. This defaults to the
1281 "zero" entity of the :class:`_query.Query` itself.
1282
1283 """
1284 relationships = util.preloaded.orm_relationships
1285
1286 if from_entity:
1287 entity_zero = inspect(from_entity)
1288 else:
1289 entity_zero = _legacy_filter_by_entity_zero(self)
1290 if property is None:
1291 # TODO: deprecate, property has to be supplied
1292 mapper = object_mapper(instance)
1293
1294 for prop in mapper.iterate_properties:
1295 if (
1296 isinstance(prop, relationships.RelationshipProperty)
1297 and prop.mapper is entity_zero.mapper # type: ignore
1298 ):
1299 property = prop # type: ignore # noqa: A001
1300 break
1301 else:
1302 raise sa_exc.InvalidRequestError(
1303 "Could not locate a property which relates instances "
1304 "of class '%s' to instances of class '%s'"
1305 % (
1306 entity_zero.mapper.class_.__name__, # type: ignore
1307 instance.__class__.__name__,
1308 )
1309 )
1310
1311 return self.filter(
1312 with_parent(
1313 instance,
1314 property, # type: ignore
1315 entity_zero.entity, # type: ignore
1316 )
1317 )
1318
1319 @_generative
1320 def add_entity(
1321 self,
1322 entity: _EntityType[Any],
1323 alias: Optional[Union[Alias, Subquery]] = None,
1324 ) -> Query[Any]:
1325 """add a mapped entity to the list of result columns
1326 to be returned.
1327
1328 .. seealso::
1329
1330 :meth:`_sql.Select.add_columns` - v2 comparable method.
1331 """
1332
1333 if alias is not None:
1334 # TODO: deprecate
1335 entity = AliasedClass(entity, alias)
1336
1337 self._raw_columns = list(self._raw_columns)
1338
1339 self._raw_columns.append(
1340 coercions.expect(
1341 roles.ColumnsClauseRole, entity, apply_propagate_attrs=self
1342 )
1343 )
1344 return self
1345
1346 @_generative
1347 def with_session(self, session: Session) -> Self:
1348 """Return a :class:`_query.Query` that will use the given
1349 :class:`.Session`.
1350
1351 While the :class:`_query.Query`
1352 object is normally instantiated using the
1353 :meth:`.Session.query` method, it is legal to build the
1354 :class:`_query.Query`
1355 directly without necessarily using a :class:`.Session`. Such a
1356 :class:`_query.Query` object, or any :class:`_query.Query`
1357 already associated
1358 with a different :class:`.Session`, can produce a new
1359 :class:`_query.Query`
1360 object associated with a target session using this method::
1361
1362 from sqlalchemy.orm import Query
1363
1364 query = Query([MyClass]).filter(MyClass.id == 5)
1365
1366 result = query.with_session(my_session).one()
1367
1368 """
1369
1370 self.session = session
1371 return self
1372
1373 def _legacy_from_self(
1374 self, *entities: _ColumnsClauseArgument[Any]
1375 ) -> Self:
1376 # used for query.count() as well as for the same
1377 # function in BakedQuery, as well as some old tests in test_baked.py.
1378
1379 fromclause = (
1380 self.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
1381 .correlate(None)
1382 .subquery()
1383 ._anonymous_fromclause()
1384 )
1385
1386 q = self._from_selectable(fromclause)
1387
1388 if entities:
1389 q._set_entities(entities)
1390 return q
1391
1392 @_generative
1393 def _set_enable_single_crit(self, val: bool) -> Self:
1394 self._compile_options += {"_enable_single_crit": val}
1395 return self
1396
1397 @_generative
1398 def _from_selectable(
1399 self, fromclause: FromClause, set_entity_from: bool = True
1400 ) -> Self:
1401 for attr in (
1402 "_where_criteria",
1403 "_order_by_clauses",
1404 "_group_by_clauses",
1405 "_limit_clause",
1406 "_offset_clause",
1407 "_last_joined_entity",
1408 "_setup_joins",
1409 "_memoized_select_entities",
1410 "_distinct",
1411 "_distinct_on",
1412 "_having_criteria",
1413 "_prefixes",
1414 "_suffixes",
1415 ):
1416 self.__dict__.pop(attr, None)
1417 self._set_select_from([fromclause], set_entity_from)
1418 self._compile_options += {
1419 "_enable_single_crit": False,
1420 }
1421
1422 return self
1423
1424 @util.deprecated(
1425 "1.4",
1426 ":meth:`_query.Query.values` "
1427 "is deprecated and will be removed in a "
1428 "future release. Please use :meth:`_query.Query.with_entities`",
1429 )
1430 def values(self, *columns: _ColumnsClauseArgument[Any]) -> Iterable[Any]:
1431 """Return an iterator yielding result tuples corresponding
1432 to the given list of columns
1433
1434 """
1435 return self._values_no_warn(*columns)
1436
1437 _values = values
1438
1439 def _values_no_warn(
1440 self, *columns: _ColumnsClauseArgument[Any]
1441 ) -> Iterable[Any]:
1442 if not columns:
1443 return iter(())
1444 q = self._clone().enable_eagerloads(False)
1445 q._set_entities(columns)
1446 if not q.load_options._yield_per:
1447 q.load_options += {"_yield_per": 10}
1448 return iter(q)
1449
1450 @util.deprecated(
1451 "1.4",
1452 ":meth:`_query.Query.value` "
1453 "is deprecated and will be removed in a "
1454 "future release. Please use :meth:`_query.Query.with_entities` "
1455 "in combination with :meth:`_query.Query.scalar`",
1456 )
1457 def value(self, column: _ColumnExpressionArgument[Any]) -> Any:
1458 """Return a scalar result corresponding to the given
1459 column expression.
1460
1461 """
1462 try:
1463 return next(self._values_no_warn(column))[0] # type: ignore
1464 except StopIteration:
1465 return None
1466
1467 @overload
1468 def with_entities(self, _entity: _EntityType[_O]) -> Query[_O]: ...
1469
1470 @overload
1471 def with_entities(
1472 self,
1473 _colexpr: roles.TypedColumnsClauseRole[_T],
1474 ) -> RowReturningQuery[Tuple[_T]]: ...
1475
1476 # START OVERLOADED FUNCTIONS self.with_entities RowReturningQuery 2-8
1477
1478 # code within this block is **programmatically,
1479 # statically generated** by tools/generate_tuple_map_overloads.py
1480
1481 @overload
1482 def with_entities(
1483 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1]
1484 ) -> RowReturningQuery[Tuple[_T0, _T1]]: ...
1485
1486 @overload
1487 def with_entities(
1488 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2]
1489 ) -> RowReturningQuery[Tuple[_T0, _T1, _T2]]: ...
1490
1491 @overload
1492 def with_entities(
1493 self,
1494 __ent0: _TCCA[_T0],
1495 __ent1: _TCCA[_T1],
1496 __ent2: _TCCA[_T2],
1497 __ent3: _TCCA[_T3],
1498 ) -> RowReturningQuery[Tuple[_T0, _T1, _T2, _T3]]: ...
1499
1500 @overload
1501 def with_entities(
1502 self,
1503 __ent0: _TCCA[_T0],
1504 __ent1: _TCCA[_T1],
1505 __ent2: _TCCA[_T2],
1506 __ent3: _TCCA[_T3],
1507 __ent4: _TCCA[_T4],
1508 ) -> RowReturningQuery[Tuple[_T0, _T1, _T2, _T3, _T4]]: ...
1509
1510 @overload
1511 def with_entities(
1512 self,
1513 __ent0: _TCCA[_T0],
1514 __ent1: _TCCA[_T1],
1515 __ent2: _TCCA[_T2],
1516 __ent3: _TCCA[_T3],
1517 __ent4: _TCCA[_T4],
1518 __ent5: _TCCA[_T5],
1519 ) -> RowReturningQuery[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ...
1520
1521 @overload
1522 def with_entities(
1523 self,
1524 __ent0: _TCCA[_T0],
1525 __ent1: _TCCA[_T1],
1526 __ent2: _TCCA[_T2],
1527 __ent3: _TCCA[_T3],
1528 __ent4: _TCCA[_T4],
1529 __ent5: _TCCA[_T5],
1530 __ent6: _TCCA[_T6],
1531 ) -> RowReturningQuery[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ...
1532
1533 @overload
1534 def with_entities(
1535 self,
1536 __ent0: _TCCA[_T0],
1537 __ent1: _TCCA[_T1],
1538 __ent2: _TCCA[_T2],
1539 __ent3: _TCCA[_T3],
1540 __ent4: _TCCA[_T4],
1541 __ent5: _TCCA[_T5],
1542 __ent6: _TCCA[_T6],
1543 __ent7: _TCCA[_T7],
1544 ) -> RowReturningQuery[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]]: ...
1545
1546 # END OVERLOADED FUNCTIONS self.with_entities
1547
1548 @overload
1549 def with_entities(
1550 self, *entities: _ColumnsClauseArgument[Any]
1551 ) -> Query[Any]: ...
1552
1553 @_generative
1554 def with_entities(
1555 self, *entities: _ColumnsClauseArgument[Any], **__kw: Any
1556 ) -> Query[Any]:
1557 r"""Return a new :class:`_query.Query`
1558 replacing the SELECT list with the
1559 given entities.
1560
1561 e.g.::
1562
1563 # Users, filtered on some arbitrary criterion
1564 # and then ordered by related email address
1565 q = (
1566 session.query(User)
1567 .join(User.address)
1568 .filter(User.name.like("%ed%"))
1569 .order_by(Address.email)
1570 )
1571
1572 # given *only* User.id==5, Address.email, and 'q', what
1573 # would the *next* User in the result be ?
1574 subq = (
1575 q.with_entities(Address.email)
1576 .order_by(None)
1577 .filter(User.id == 5)
1578 .subquery()
1579 )
1580 q = q.join((subq, subq.c.email < Address.email)).limit(1)
1581
1582 .. seealso::
1583
1584 :meth:`_sql.Select.with_only_columns` - v2 comparable method.
1585 """
1586 if __kw:
1587 raise _no_kw()
1588
1589 # Query has all the same fields as Select for this operation
1590 # this could in theory be based on a protocol but not sure if it's
1591 # worth it
1592 _MemoizedSelectEntities._generate_for_statement(self) # type: ignore
1593 self._set_entities(entities)
1594 return self
1595
1596 @_generative
1597 def add_columns(
1598 self, *column: _ColumnExpressionArgument[Any]
1599 ) -> Query[Any]:
1600 """Add one or more column expressions to the list
1601 of result columns to be returned.
1602
1603 .. seealso::
1604
1605 :meth:`_sql.Select.add_columns` - v2 comparable method.
1606 """
1607
1608 self._raw_columns = list(self._raw_columns)
1609
1610 self._raw_columns.extend(
1611 coercions.expect(
1612 roles.ColumnsClauseRole,
1613 c,
1614 apply_propagate_attrs=self,
1615 post_inspect=True,
1616 )
1617 for c in column
1618 )
1619 return self
1620
1621 @util.deprecated(
1622 "1.4",
1623 ":meth:`_query.Query.add_column` "
1624 "is deprecated and will be removed in a "
1625 "future release. Please use :meth:`_query.Query.add_columns`",
1626 )
1627 def add_column(self, column: _ColumnExpressionArgument[Any]) -> Query[Any]:
1628 """Add a column expression to the list of result columns to be
1629 returned.
1630
1631 """
1632 return self.add_columns(column)
1633
1634 @_generative
1635 def options(self, *args: ExecutableOption) -> Self:
1636 """Return a new :class:`_query.Query` object,
1637 applying the given list of
1638 mapper options.
1639
1640 Most supplied options regard changing how column- and
1641 relationship-mapped attributes are loaded.
1642
1643 .. seealso::
1644
1645 :ref:`loading_columns`
1646
1647 :ref:`relationship_loader_options`
1648
1649 """
1650
1651 opts = tuple(util.flatten_iterator(args))
1652 if self._compile_options._current_path:
1653 # opting for lower method overhead for the checks
1654 for opt in opts:
1655 if not opt._is_core and opt._is_legacy_option: # type: ignore
1656 opt.process_query_conditionally(self) # type: ignore
1657 else:
1658 for opt in opts:
1659 if not opt._is_core and opt._is_legacy_option: # type: ignore
1660 opt.process_query(self) # type: ignore
1661
1662 self._with_options += opts
1663 return self
1664
1665 def with_transformation(
1666 self, fn: Callable[[Query[Any]], Query[Any]]
1667 ) -> Query[Any]:
1668 """Return a new :class:`_query.Query` object transformed by
1669 the given function.
1670
1671 E.g.::
1672
1673 def filter_something(criterion):
1674 def transform(q):
1675 return q.filter(criterion)
1676
1677 return transform
1678
1679
1680 q = q.with_transformation(filter_something(x == 5))
1681
1682 This allows ad-hoc recipes to be created for :class:`_query.Query`
1683 objects.
1684
1685 """
1686 return fn(self)
1687
1688 def get_execution_options(self) -> _ImmutableExecuteOptions:
1689 """Get the non-SQL options which will take effect during execution.
1690
1691 .. versionadded:: 1.3
1692
1693 .. seealso::
1694
1695 :meth:`_query.Query.execution_options`
1696
1697 :meth:`_sql.Select.get_execution_options` - v2 comparable method.
1698
1699 """
1700 return self._execution_options
1701
1702 @overload
1703 def execution_options(
1704 self,
1705 *,
1706 compiled_cache: Optional[CompiledCacheType] = ...,
1707 logging_token: str = ...,
1708 isolation_level: IsolationLevel = ...,
1709 no_parameters: bool = False,
1710 stream_results: bool = False,
1711 max_row_buffer: int = ...,
1712 yield_per: int = ...,
1713 insertmanyvalues_page_size: int = ...,
1714 schema_translate_map: Optional[SchemaTranslateMapType] = ...,
1715 populate_existing: bool = False,
1716 autoflush: bool = False,
1717 preserve_rowcount: bool = False,
1718 **opt: Any,
1719 ) -> Self: ...
1720
1721 @overload
1722 def execution_options(self, **opt: Any) -> Self: ...
1723
1724 @_generative
1725 def execution_options(self, **kwargs: Any) -> Self:
1726 """Set non-SQL options which take effect during execution.
1727
1728 Options allowed here include all of those accepted by
1729 :meth:`_engine.Connection.execution_options`, as well as a series
1730 of ORM specific options:
1731
1732 ``populate_existing=True`` - equivalent to using
1733 :meth:`_orm.Query.populate_existing`
1734
1735 ``autoflush=True|False`` - equivalent to using
1736 :meth:`_orm.Query.autoflush`
1737
1738 ``yield_per=<value>`` - equivalent to using
1739 :meth:`_orm.Query.yield_per`
1740
1741 Note that the ``stream_results`` execution option is enabled
1742 automatically if the :meth:`~sqlalchemy.orm.query.Query.yield_per()`
1743 method or execution option is used.
1744
1745 .. versionadded:: 1.4 - added ORM options to
1746 :meth:`_orm.Query.execution_options`
1747
1748 The execution options may also be specified on a per execution basis
1749 when using :term:`2.0 style` queries via the
1750 :paramref:`_orm.Session.execution_options` parameter.
1751
1752 .. warning:: The
1753 :paramref:`_engine.Connection.execution_options.stream_results`
1754 parameter should not be used at the level of individual ORM
1755 statement executions, as the :class:`_orm.Session` will not track
1756 objects from different schema translate maps within a single
1757 session. For multiple schema translate maps within the scope of a
1758 single :class:`_orm.Session`, see :ref:`examples_sharding`.
1759
1760
1761 .. seealso::
1762
1763 :ref:`engine_stream_results`
1764
1765 :meth:`_query.Query.get_execution_options`
1766
1767 :meth:`_sql.Select.execution_options` - v2 equivalent method.
1768
1769 """
1770 self._execution_options = self._execution_options.union(kwargs)
1771 return self
1772
1773 @_generative
1774 def with_for_update(
1775 self,
1776 *,
1777 nowait: bool = False,
1778 read: bool = False,
1779 of: Optional[_ForUpdateOfArgument] = None,
1780 skip_locked: bool = False,
1781 key_share: bool = False,
1782 ) -> Self:
1783 """return a new :class:`_query.Query`
1784 with the specified options for the
1785 ``FOR UPDATE`` clause.
1786
1787 The behavior of this method is identical to that of
1788 :meth:`_expression.GenerativeSelect.with_for_update`.
1789 When called with no arguments,
1790 the resulting ``SELECT`` statement will have a ``FOR UPDATE`` clause
1791 appended. When additional arguments are specified, backend-specific
1792 options such as ``FOR UPDATE NOWAIT`` or ``LOCK IN SHARE MODE``
1793 can take effect.
1794
1795 E.g.::
1796
1797 q = (
1798 sess.query(User)
1799 .populate_existing()
1800 .with_for_update(nowait=True, of=User)
1801 )
1802
1803 The above query on a PostgreSQL backend will render like:
1804
1805 .. sourcecode:: sql
1806
1807 SELECT users.id AS users_id FROM users FOR UPDATE OF users NOWAIT
1808
1809 .. warning::
1810
1811 Using ``with_for_update`` in the context of eager loading
1812 relationships is not officially supported or recommended by
1813 SQLAlchemy and may not work with certain queries on various
1814 database backends. When ``with_for_update`` is successfully used
1815 with a query that involves :func:`_orm.joinedload`, SQLAlchemy will
1816 attempt to emit SQL that locks all involved tables.
1817
1818 .. note:: It is generally a good idea to combine the use of the
1819 :meth:`_orm.Query.populate_existing` method when using the
1820 :meth:`_orm.Query.with_for_update` method. The purpose of
1821 :meth:`_orm.Query.populate_existing` is to force all the data read
1822 from the SELECT to be populated into the ORM objects returned,
1823 even if these objects are already in the :term:`identity map`.
1824
1825 .. seealso::
1826
1827 :meth:`_expression.GenerativeSelect.with_for_update`
1828 - Core level method with
1829 full argument and behavioral description.
1830
1831 :meth:`_orm.Query.populate_existing` - overwrites attributes of
1832 objects already loaded in the identity map.
1833
1834 """ # noqa: E501
1835
1836 self._for_update_arg = ForUpdateArg(
1837 read=read,
1838 nowait=nowait,
1839 of=of,
1840 skip_locked=skip_locked,
1841 key_share=key_share,
1842 )
1843 return self
1844
1845 @_generative
1846 def params(
1847 self, __params: Optional[Dict[str, Any]] = None, **kw: Any
1848 ) -> Self:
1849 r"""Add values for bind parameters which may have been
1850 specified in filter().
1851
1852 Parameters may be specified using \**kwargs, or optionally a single
1853 dictionary as the first positional argument. The reason for both is
1854 that \**kwargs is convenient, however some parameter dictionaries
1855 contain unicode keys in which case \**kwargs cannot be used.
1856
1857 """
1858 if __params:
1859 kw.update(__params)
1860 self._params = self._params.union(kw)
1861 return self
1862
1863 def where(self, *criterion: _ColumnExpressionArgument[bool]) -> Self:
1864 """A synonym for :meth:`.Query.filter`.
1865
1866 .. versionadded:: 1.4
1867
1868 .. seealso::
1869
1870 :meth:`_sql.Select.where` - v2 equivalent method.
1871
1872 """
1873 return self.filter(*criterion)
1874
1875 @_generative
1876 @_assertions(_no_statement_condition, _no_limit_offset)
1877 def filter(self, *criterion: _ColumnExpressionArgument[bool]) -> Self:
1878 r"""Apply the given filtering criterion to a copy
1879 of this :class:`_query.Query`, using SQL expressions.
1880
1881 e.g.::
1882
1883 session.query(MyClass).filter(MyClass.name == "some name")
1884
1885 Multiple criteria may be specified as comma separated; the effect
1886 is that they will be joined together using the :func:`.and_`
1887 function::
1888
1889 session.query(MyClass).filter(MyClass.name == "some name", MyClass.id > 5)
1890
1891 The criterion is any SQL expression object applicable to the
1892 WHERE clause of a select. String expressions are coerced
1893 into SQL expression constructs via the :func:`_expression.text`
1894 construct.
1895
1896 .. seealso::
1897
1898 :meth:`_query.Query.filter_by` - filter on keyword expressions.
1899
1900 :meth:`_sql.Select.where` - v2 equivalent method.
1901
1902 """ # noqa: E501
1903 for crit in list(criterion):
1904 crit = coercions.expect(
1905 roles.WhereHavingRole, crit, apply_propagate_attrs=self
1906 )
1907
1908 self._where_criteria += (crit,)
1909 return self
1910
1911 @util.memoized_property
1912 def _last_joined_entity(
1913 self,
1914 ) -> Optional[Union[_InternalEntityType[Any], _JoinTargetElement]]:
1915 if self._setup_joins:
1916 return _determine_last_joined_entity(
1917 self._setup_joins,
1918 )
1919 else:
1920 return None
1921
1922 def _filter_by_zero(self) -> Any:
1923 """for the filter_by() method, return the target entity for which
1924 we will attempt to derive an expression from based on string name.
1925
1926 """
1927
1928 if self._setup_joins:
1929 _last_joined_entity = self._last_joined_entity
1930 if _last_joined_entity is not None:
1931 return _last_joined_entity
1932
1933 # discussion related to #7239
1934 # special check determines if we should try to derive attributes
1935 # for filter_by() from the "from object", i.e., if the user
1936 # called query.select_from(some selectable).filter_by(some_attr=value).
1937 # We don't want to do that in the case that methods like
1938 # from_self(), select_entity_from(), or a set op like union() were
1939 # called; while these methods also place a
1940 # selectable in the _from_obj collection, they also set up
1941 # the _set_base_alias boolean which turns on the whole "adapt the
1942 # entity to this selectable" thing, meaning the query still continues
1943 # to construct itself in terms of the lead entity that was passed
1944 # to query(), e.g. query(User).from_self() is still in terms of User,
1945 # and not the subquery that from_self() created. This feature of
1946 # "implicitly adapt all occurrences of entity X to some arbitrary
1947 # subquery" is the main thing I am trying to do away with in 2.0 as
1948 # users should now used aliased() for that, but I can't entirely get
1949 # rid of it due to query.union() and other set ops relying upon it.
1950 #
1951 # compare this to the base Select()._filter_by_zero() which can
1952 # just return self._from_obj[0] if present, because there is no
1953 # "_set_base_alias" feature.
1954 #
1955 # IOW, this conditional essentially detects if
1956 # "select_from(some_selectable)" has been called, as opposed to
1957 # "select_entity_from()", "from_self()"
1958 # or "union() / some_set_op()".
1959 if self._from_obj and not self._compile_options._set_base_alias:
1960 return self._from_obj[0]
1961
1962 return self._raw_columns[0]
1963
1964 def filter_by(self, **kwargs: Any) -> Self:
1965 r"""Apply the given filtering criterion to a copy
1966 of this :class:`_query.Query`, using keyword expressions.
1967
1968 e.g.::
1969
1970 session.query(MyClass).filter_by(name="some name")
1971
1972 Multiple criteria may be specified as comma separated; the effect
1973 is that they will be joined together using the :func:`.and_`
1974 function::
1975
1976 session.query(MyClass).filter_by(name="some name", id=5)
1977
1978 The keyword expressions are extracted from the primary
1979 entity of the query, or the last entity that was the
1980 target of a call to :meth:`_query.Query.join`.
1981
1982 .. seealso::
1983
1984 :meth:`_query.Query.filter` - filter on SQL expressions.
1985
1986 :meth:`_sql.Select.filter_by` - v2 comparable method.
1987
1988 """
1989 from_entity = self._filter_by_zero()
1990
1991 clauses = [
1992 _entity_namespace_key(from_entity, key) == value
1993 for key, value in kwargs.items()
1994 ]
1995 return self.filter(*clauses)
1996
1997 @_generative
1998 def order_by(
1999 self,
2000 __first: Union[
2001 Literal[None, False, _NoArg.NO_ARG],
2002 _ColumnExpressionOrStrLabelArgument[Any],
2003 ] = _NoArg.NO_ARG,
2004 *clauses: _ColumnExpressionOrStrLabelArgument[Any],
2005 ) -> Self:
2006 """Apply one or more ORDER BY criteria to the query and return
2007 the newly resulting :class:`_query.Query`.
2008
2009 e.g.::
2010
2011 q = session.query(Entity).order_by(Entity.id, Entity.name)
2012
2013 Calling this method multiple times is equivalent to calling it once
2014 with all the clauses concatenated. All existing ORDER BY criteria may
2015 be cancelled by passing ``None`` by itself. New ORDER BY criteria may
2016 then be added by invoking :meth:`_orm.Query.order_by` again, e.g.::
2017
2018 # will erase all ORDER BY and ORDER BY new_col alone
2019 q = q.order_by(None).order_by(new_col)
2020
2021 .. seealso::
2022
2023 These sections describe ORDER BY in terms of :term:`2.0 style`
2024 invocation but apply to :class:`_orm.Query` as well:
2025
2026 :ref:`tutorial_order_by` - in the :ref:`unified_tutorial`
2027
2028 :ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial`
2029
2030 :meth:`_sql.Select.order_by` - v2 equivalent method.
2031
2032 """
2033
2034 for assertion in (self._no_statement_condition, self._no_limit_offset):
2035 assertion("order_by")
2036
2037 if not clauses and (__first is None or __first is False):
2038 self._order_by_clauses = ()
2039 elif __first is not _NoArg.NO_ARG:
2040 criterion = tuple(
2041 coercions.expect(roles.OrderByRole, clause)
2042 for clause in (__first,) + clauses
2043 )
2044 self._order_by_clauses += criterion
2045
2046 return self
2047
2048 @_generative
2049 def group_by(
2050 self,
2051 __first: Union[
2052 Literal[None, False, _NoArg.NO_ARG],
2053 _ColumnExpressionOrStrLabelArgument[Any],
2054 ] = _NoArg.NO_ARG,
2055 *clauses: _ColumnExpressionOrStrLabelArgument[Any],
2056 ) -> Self:
2057 """Apply one or more GROUP BY criterion to the query and return
2058 the newly resulting :class:`_query.Query`.
2059
2060 All existing GROUP BY settings can be suppressed by
2061 passing ``None`` - this will suppress any GROUP BY configured
2062 on mappers as well.
2063
2064 .. seealso::
2065
2066 These sections describe GROUP BY in terms of :term:`2.0 style`
2067 invocation but apply to :class:`_orm.Query` as well:
2068
2069 :ref:`tutorial_group_by_w_aggregates` - in the
2070 :ref:`unified_tutorial`
2071
2072 :ref:`tutorial_order_by_label` - in the :ref:`unified_tutorial`
2073
2074 :meth:`_sql.Select.group_by` - v2 equivalent method.
2075
2076 """
2077
2078 for assertion in (self._no_statement_condition, self._no_limit_offset):
2079 assertion("group_by")
2080
2081 if not clauses and (__first is None or __first is False):
2082 self._group_by_clauses = ()
2083 elif __first is not _NoArg.NO_ARG:
2084 criterion = tuple(
2085 coercions.expect(roles.GroupByRole, clause)
2086 for clause in (__first,) + clauses
2087 )
2088 self._group_by_clauses += criterion
2089 return self
2090
2091 @_generative
2092 @_assertions(_no_statement_condition, _no_limit_offset)
2093 def having(self, *having: _ColumnExpressionArgument[bool]) -> Self:
2094 r"""Apply a HAVING criterion to the query and return the
2095 newly resulting :class:`_query.Query`.
2096
2097 :meth:`_query.Query.having` is used in conjunction with
2098 :meth:`_query.Query.group_by`.
2099
2100 HAVING criterion makes it possible to use filters on aggregate
2101 functions like COUNT, SUM, AVG, MAX, and MIN, eg.::
2102
2103 q = (
2104 session.query(User.id)
2105 .join(User.addresses)
2106 .group_by(User.id)
2107 .having(func.count(Address.id) > 2)
2108 )
2109
2110 .. seealso::
2111
2112 :meth:`_sql.Select.having` - v2 equivalent method.
2113
2114 """
2115
2116 for criterion in having:
2117 having_criteria = coercions.expect(
2118 roles.WhereHavingRole, criterion
2119 )
2120 self._having_criteria += (having_criteria,)
2121 return self
2122
2123 def _set_op(self, expr_fn: Any, *q: Query[Any]) -> Self:
2124 list_of_queries = (self,) + q
2125 return self._from_selectable(expr_fn(*(list_of_queries)).subquery())
2126
2127 def union(self, *q: Query[Any]) -> Self:
2128 """Produce a UNION of this Query against one or more queries.
2129
2130 e.g.::
2131
2132 q1 = sess.query(SomeClass).filter(SomeClass.foo == "bar")
2133 q2 = sess.query(SomeClass).filter(SomeClass.bar == "foo")
2134
2135 q3 = q1.union(q2)
2136
2137 The method accepts multiple Query objects so as to control
2138 the level of nesting. A series of ``union()`` calls such as::
2139
2140 x.union(y).union(z).all()
2141
2142 will nest on each ``union()``, and produces:
2143
2144 .. sourcecode:: sql
2145
2146 SELECT * FROM (SELECT * FROM (SELECT * FROM X UNION
2147 SELECT * FROM y) UNION SELECT * FROM Z)
2148
2149 Whereas::
2150
2151 x.union(y, z).all()
2152
2153 produces:
2154
2155 .. sourcecode:: sql
2156
2157 SELECT * FROM (SELECT * FROM X UNION SELECT * FROM y UNION
2158 SELECT * FROM Z)
2159
2160 Note that many database backends do not allow ORDER BY to
2161 be rendered on a query called within UNION, EXCEPT, etc.
2162 To disable all ORDER BY clauses including those configured
2163 on mappers, issue ``query.order_by(None)`` - the resulting
2164 :class:`_query.Query` object will not render ORDER BY within
2165 its SELECT statement.
2166
2167 .. seealso::
2168
2169 :meth:`_sql.Select.union` - v2 equivalent method.
2170
2171 """
2172 return self._set_op(expression.union, *q)
2173
2174 def union_all(self, *q: Query[Any]) -> Self:
2175 """Produce a UNION ALL of this Query against one or more queries.
2176
2177 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
2178 that method for usage examples.
2179
2180 .. seealso::
2181
2182 :meth:`_sql.Select.union_all` - v2 equivalent method.
2183
2184 """
2185 return self._set_op(expression.union_all, *q)
2186
2187 def intersect(self, *q: Query[Any]) -> Self:
2188 """Produce an INTERSECT of this Query against one or more queries.
2189
2190 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
2191 that method for usage examples.
2192
2193 .. seealso::
2194
2195 :meth:`_sql.Select.intersect` - v2 equivalent method.
2196
2197 """
2198 return self._set_op(expression.intersect, *q)
2199
2200 def intersect_all(self, *q: Query[Any]) -> Self:
2201 """Produce an INTERSECT ALL of this Query against one or more queries.
2202
2203 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
2204 that method for usage examples.
2205
2206 .. seealso::
2207
2208 :meth:`_sql.Select.intersect_all` - v2 equivalent method.
2209
2210 """
2211 return self._set_op(expression.intersect_all, *q)
2212
2213 def except_(self, *q: Query[Any]) -> Self:
2214 """Produce an EXCEPT of this Query against one or more queries.
2215
2216 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
2217 that method for usage examples.
2218
2219 .. seealso::
2220
2221 :meth:`_sql.Select.except_` - v2 equivalent method.
2222
2223 """
2224 return self._set_op(expression.except_, *q)
2225
2226 def except_all(self, *q: Query[Any]) -> Self:
2227 """Produce an EXCEPT ALL of this Query against one or more queries.
2228
2229 Works the same way as :meth:`~sqlalchemy.orm.query.Query.union`. See
2230 that method for usage examples.
2231
2232 .. seealso::
2233
2234 :meth:`_sql.Select.except_all` - v2 equivalent method.
2235
2236 """
2237 return self._set_op(expression.except_all, *q)
2238
2239 @_generative
2240 @_assertions(_no_statement_condition, _no_limit_offset)
2241 def join(
2242 self,
2243 target: _JoinTargetArgument,
2244 onclause: Optional[_OnClauseArgument] = None,
2245 *,
2246 isouter: bool = False,
2247 full: bool = False,
2248 ) -> Self:
2249 r"""Create a SQL JOIN against this :class:`_query.Query`
2250 object's criterion
2251 and apply generatively, returning the newly resulting
2252 :class:`_query.Query`.
2253
2254 **Simple Relationship Joins**
2255
2256 Consider a mapping between two classes ``User`` and ``Address``,
2257 with a relationship ``User.addresses`` representing a collection
2258 of ``Address`` objects associated with each ``User``. The most
2259 common usage of :meth:`_query.Query.join`
2260 is to create a JOIN along this
2261 relationship, using the ``User.addresses`` attribute as an indicator
2262 for how this should occur::
2263
2264 q = session.query(User).join(User.addresses)
2265
2266 Where above, the call to :meth:`_query.Query.join` along
2267 ``User.addresses`` will result in SQL approximately equivalent to:
2268
2269 .. sourcecode:: sql
2270
2271 SELECT user.id, user.name
2272 FROM user JOIN address ON user.id = address.user_id
2273
2274 In the above example we refer to ``User.addresses`` as passed to
2275 :meth:`_query.Query.join` as the "on clause", that is, it indicates
2276 how the "ON" portion of the JOIN should be constructed.
2277
2278 To construct a chain of joins, multiple :meth:`_query.Query.join`
2279 calls may be used. The relationship-bound attribute implies both
2280 the left and right side of the join at once::
2281
2282 q = (
2283 session.query(User)
2284 .join(User.orders)
2285 .join(Order.items)
2286 .join(Item.keywords)
2287 )
2288
2289 .. note:: as seen in the above example, **the order in which each
2290 call to the join() method occurs is important**. Query would not,
2291 for example, know how to join correctly if we were to specify
2292 ``User``, then ``Item``, then ``Order``, in our chain of joins; in
2293 such a case, depending on the arguments passed, it may raise an
2294 error that it doesn't know how to join, or it may produce invalid
2295 SQL in which case the database will raise an error. In correct
2296 practice, the
2297 :meth:`_query.Query.join` method is invoked in such a way that lines
2298 up with how we would want the JOIN clauses in SQL to be
2299 rendered, and each call should represent a clear link from what
2300 precedes it.
2301
2302 **Joins to a Target Entity or Selectable**
2303
2304 A second form of :meth:`_query.Query.join` allows any mapped entity or
2305 core selectable construct as a target. In this usage,
2306 :meth:`_query.Query.join` will attempt to create a JOIN along the
2307 natural foreign key relationship between two entities::
2308
2309 q = session.query(User).join(Address)
2310
2311 In the above calling form, :meth:`_query.Query.join` is called upon to
2312 create the "on clause" automatically for us. This calling form will
2313 ultimately raise an error if either there are no foreign keys between
2314 the two entities, or if there are multiple foreign key linkages between
2315 the target entity and the entity or entities already present on the
2316 left side such that creating a join requires more information. Note
2317 that when indicating a join to a target without any ON clause, ORM
2318 configured relationships are not taken into account.
2319
2320 **Joins to a Target with an ON Clause**
2321
2322 The third calling form allows both the target entity as well
2323 as the ON clause to be passed explicitly. A example that includes
2324 a SQL expression as the ON clause is as follows::
2325
2326 q = session.query(User).join(Address, User.id == Address.user_id)
2327
2328 The above form may also use a relationship-bound attribute as the
2329 ON clause as well::
2330
2331 q = session.query(User).join(Address, User.addresses)
2332
2333 The above syntax can be useful for the case where we wish
2334 to join to an alias of a particular target entity. If we wanted
2335 to join to ``Address`` twice, it could be achieved using two
2336 aliases set up using the :func:`~sqlalchemy.orm.aliased` function::
2337
2338 a1 = aliased(Address)
2339 a2 = aliased(Address)
2340
2341 q = (
2342 session.query(User)
2343 .join(a1, User.addresses)
2344 .join(a2, User.addresses)
2345 .filter(a1.email_address == "ed@foo.com")
2346 .filter(a2.email_address == "ed@bar.com")
2347 )
2348
2349 The relationship-bound calling form can also specify a target entity
2350 using the :meth:`_orm.PropComparator.of_type` method; a query
2351 equivalent to the one above would be::
2352
2353 a1 = aliased(Address)
2354 a2 = aliased(Address)
2355
2356 q = (
2357 session.query(User)
2358 .join(User.addresses.of_type(a1))
2359 .join(User.addresses.of_type(a2))
2360 .filter(a1.email_address == "ed@foo.com")
2361 .filter(a2.email_address == "ed@bar.com")
2362 )
2363
2364 **Augmenting Built-in ON Clauses**
2365
2366 As a substitute for providing a full custom ON condition for an
2367 existing relationship, the :meth:`_orm.PropComparator.and_` function
2368 may be applied to a relationship attribute to augment additional
2369 criteria into the ON clause; the additional criteria will be combined
2370 with the default criteria using AND::
2371
2372 q = session.query(User).join(
2373 User.addresses.and_(Address.email_address != "foo@bar.com")
2374 )
2375
2376 .. versionadded:: 1.4
2377
2378 **Joining to Tables and Subqueries**
2379
2380
2381 The target of a join may also be any table or SELECT statement,
2382 which may be related to a target entity or not. Use the
2383 appropriate ``.subquery()`` method in order to make a subquery
2384 out of a query::
2385
2386 subq = (
2387 session.query(Address)
2388 .filter(Address.email_address == "ed@foo.com")
2389 .subquery()
2390 )
2391
2392
2393 q = session.query(User).join(subq, User.id == subq.c.user_id)
2394
2395 Joining to a subquery in terms of a specific relationship and/or
2396 target entity may be achieved by linking the subquery to the
2397 entity using :func:`_orm.aliased`::
2398
2399 subq = (
2400 session.query(Address)
2401 .filter(Address.email_address == "ed@foo.com")
2402 .subquery()
2403 )
2404
2405 address_subq = aliased(Address, subq)
2406
2407 q = session.query(User).join(User.addresses.of_type(address_subq))
2408
2409 **Controlling what to Join From**
2410
2411 In cases where the left side of the current state of
2412 :class:`_query.Query` is not in line with what we want to join from,
2413 the :meth:`_query.Query.select_from` method may be used::
2414
2415 q = (
2416 session.query(Address)
2417 .select_from(User)
2418 .join(User.addresses)
2419 .filter(User.name == "ed")
2420 )
2421
2422 Which will produce SQL similar to:
2423
2424 .. sourcecode:: sql
2425
2426 SELECT address.* FROM user
2427 JOIN address ON user.id=address.user_id
2428 WHERE user.name = :name_1
2429
2430 .. seealso::
2431
2432 :meth:`_sql.Select.join` - v2 equivalent method.
2433
2434 :param \*props: Incoming arguments for :meth:`_query.Query.join`,
2435 the props collection in modern use should be considered to be a one
2436 or two argument form, either as a single "target" entity or ORM
2437 attribute-bound relationship, or as a target entity plus an "on
2438 clause" which may be a SQL expression or ORM attribute-bound
2439 relationship.
2440
2441 :param isouter=False: If True, the join used will be a left outer join,
2442 just as if the :meth:`_query.Query.outerjoin` method were called.
2443
2444 :param full=False: render FULL OUTER JOIN; implies ``isouter``.
2445
2446 """
2447
2448 join_target = coercions.expect(
2449 roles.JoinTargetRole,
2450 target,
2451 apply_propagate_attrs=self,
2452 legacy=True,
2453 )
2454 if onclause is not None:
2455 onclause_element = coercions.expect(
2456 roles.OnClauseRole, onclause, legacy=True
2457 )
2458 else:
2459 onclause_element = None
2460
2461 self._setup_joins += (
2462 (
2463 join_target,
2464 onclause_element,
2465 None,
2466 {
2467 "isouter": isouter,
2468 "full": full,
2469 },
2470 ),
2471 )
2472
2473 self.__dict__.pop("_last_joined_entity", None)
2474 return self
2475
2476 def outerjoin(
2477 self,
2478 target: _JoinTargetArgument,
2479 onclause: Optional[_OnClauseArgument] = None,
2480 *,
2481 full: bool = False,
2482 ) -> Self:
2483 """Create a left outer join against this ``Query`` object's criterion
2484 and apply generatively, returning the newly resulting ``Query``.
2485
2486 Usage is the same as the ``join()`` method.
2487
2488 .. seealso::
2489
2490 :meth:`_sql.Select.outerjoin` - v2 equivalent method.
2491
2492 """
2493 return self.join(target, onclause=onclause, isouter=True, full=full)
2494
2495 @_generative
2496 @_assertions(_no_statement_condition)
2497 def reset_joinpoint(self) -> Self:
2498 """Return a new :class:`.Query`, where the "join point" has
2499 been reset back to the base FROM entities of the query.
2500
2501 This method is usually used in conjunction with the
2502 ``aliased=True`` feature of the :meth:`~.Query.join`
2503 method. See the example in :meth:`~.Query.join` for how
2504 this is used.
2505
2506 """
2507 self._last_joined_entity = None
2508
2509 return self
2510
2511 @_generative
2512 @_assertions(_no_clauseelement_condition)
2513 def select_from(self, *from_obj: _FromClauseArgument) -> Self:
2514 r"""Set the FROM clause of this :class:`.Query` explicitly.
2515
2516 :meth:`.Query.select_from` is often used in conjunction with
2517 :meth:`.Query.join` in order to control which entity is selected
2518 from on the "left" side of the join.
2519
2520 The entity or selectable object here effectively replaces the
2521 "left edge" of any calls to :meth:`~.Query.join`, when no
2522 joinpoint is otherwise established - usually, the default "join
2523 point" is the leftmost entity in the :class:`~.Query` object's
2524 list of entities to be selected.
2525
2526 A typical example::
2527
2528 q = (
2529 session.query(Address)
2530 .select_from(User)
2531 .join(User.addresses)
2532 .filter(User.name == "ed")
2533 )
2534
2535 Which produces SQL equivalent to:
2536
2537 .. sourcecode:: sql
2538
2539 SELECT address.* FROM user
2540 JOIN address ON user.id=address.user_id
2541 WHERE user.name = :name_1
2542
2543 :param \*from_obj: collection of one or more entities to apply
2544 to the FROM clause. Entities can be mapped classes,
2545 :class:`.AliasedClass` objects, :class:`.Mapper` objects
2546 as well as core :class:`.FromClause` elements like subqueries.
2547
2548 .. seealso::
2549
2550 :meth:`~.Query.join`
2551
2552 :meth:`.Query.select_entity_from`
2553
2554 :meth:`_sql.Select.select_from` - v2 equivalent method.
2555
2556 """
2557
2558 self._set_select_from(from_obj, False)
2559 return self
2560
2561 def __getitem__(self, item: Any) -> Any:
2562 return orm_util._getitem(
2563 self,
2564 item,
2565 )
2566
2567 @_generative
2568 @_assertions(_no_statement_condition)
2569 def slice(
2570 self,
2571 start: int,
2572 stop: int,
2573 ) -> Self:
2574 """Computes the "slice" of the :class:`_query.Query` represented by
2575 the given indices and returns the resulting :class:`_query.Query`.
2576
2577 The start and stop indices behave like the argument to Python's
2578 built-in :func:`range` function. This method provides an
2579 alternative to using ``LIMIT``/``OFFSET`` to get a slice of the
2580 query.
2581
2582 For example, ::
2583
2584 session.query(User).order_by(User.id).slice(1, 3)
2585
2586 renders as
2587
2588 .. sourcecode:: sql
2589
2590 SELECT users.id AS users_id,
2591 users.name AS users_name
2592 FROM users ORDER BY users.id
2593 LIMIT ? OFFSET ?
2594 (2, 1)
2595
2596 .. seealso::
2597
2598 :meth:`_query.Query.limit`
2599
2600 :meth:`_query.Query.offset`
2601
2602 :meth:`_sql.Select.slice` - v2 equivalent method.
2603
2604 """
2605
2606 self._limit_clause, self._offset_clause = sql_util._make_slice(
2607 self._limit_clause, self._offset_clause, start, stop
2608 )
2609 return self
2610
2611 @_generative
2612 @_assertions(_no_statement_condition)
2613 def limit(self, limit: _LimitOffsetType) -> Self:
2614 """Apply a ``LIMIT`` to the query and return the newly resulting
2615 ``Query``.
2616
2617 .. seealso::
2618
2619 :meth:`_sql.Select.limit` - v2 equivalent method.
2620
2621 """
2622 self._limit_clause = sql_util._offset_or_limit_clause(limit)
2623 return self
2624
2625 @_generative
2626 @_assertions(_no_statement_condition)
2627 def offset(self, offset: _LimitOffsetType) -> Self:
2628 """Apply an ``OFFSET`` to the query and return the newly resulting
2629 ``Query``.
2630
2631 .. seealso::
2632
2633 :meth:`_sql.Select.offset` - v2 equivalent method.
2634 """
2635 self._offset_clause = sql_util._offset_or_limit_clause(offset)
2636 return self
2637
2638 @_generative
2639 @_assertions(_no_statement_condition)
2640 def distinct(self, *expr: _ColumnExpressionArgument[Any]) -> Self:
2641 r"""Apply a ``DISTINCT`` to the query and return the newly resulting
2642 ``Query``.
2643
2644
2645 .. note::
2646
2647 The ORM-level :meth:`.distinct` call includes logic that will
2648 automatically add columns from the ORDER BY of the query to the
2649 columns clause of the SELECT statement, to satisfy the common need
2650 of the database backend that ORDER BY columns be part of the SELECT
2651 list when DISTINCT is used. These columns *are not* added to the
2652 list of columns actually fetched by the :class:`_query.Query`,
2653 however,
2654 so would not affect results. The columns are passed through when
2655 using the :attr:`_query.Query.statement` accessor, however.
2656
2657 .. deprecated:: 2.0 This logic is deprecated and will be removed
2658 in SQLAlchemy 2.0. See :ref:`migration_20_query_distinct`
2659 for a description of this use case in 2.0.
2660
2661 .. seealso::
2662
2663 :meth:`_sql.Select.distinct` - v2 equivalent method.
2664
2665 :param \*expr: optional column expressions. When present,
2666 the PostgreSQL dialect will render a ``DISTINCT ON (<expressions>)``
2667 construct.
2668
2669 .. deprecated:: 1.4 Using \*expr in other dialects is deprecated
2670 and will raise :class:`_exc.CompileError` in a future version.
2671
2672 """
2673 if expr:
2674 self._distinct = True
2675 self._distinct_on = self._distinct_on + tuple(
2676 coercions.expect(roles.ByOfRole, e) for e in expr
2677 )
2678 else:
2679 self._distinct = True
2680 return self
2681
2682 def all(self) -> List[_T]:
2683 """Return the results represented by this :class:`_query.Query`
2684 as a list.
2685
2686 This results in an execution of the underlying SQL statement.
2687
2688 .. warning:: The :class:`_query.Query` object,
2689 when asked to return either
2690 a sequence or iterator that consists of full ORM-mapped entities,
2691 will **deduplicate entries based on primary key**. See the FAQ for
2692 more details.
2693
2694 .. seealso::
2695
2696 :ref:`faq_query_deduplicating`
2697
2698 .. seealso::
2699
2700 :meth:`_engine.Result.all` - v2 comparable method.
2701
2702 :meth:`_engine.Result.scalars` - v2 comparable method.
2703 """
2704 return self._iter().all() # type: ignore
2705
2706 @_generative
2707 @_assertions(_no_clauseelement_condition)
2708 def from_statement(self, statement: ExecutableReturnsRows) -> Self:
2709 """Execute the given SELECT statement and return results.
2710
2711 This method bypasses all internal statement compilation, and the
2712 statement is executed without modification.
2713
2714 The statement is typically either a :func:`_expression.text`
2715 or :func:`_expression.select` construct, and should return the set
2716 of columns
2717 appropriate to the entity class represented by this
2718 :class:`_query.Query`.
2719
2720 .. seealso::
2721
2722 :meth:`_sql.Select.from_statement` - v2 comparable method.
2723
2724 """
2725 statement = coercions.expect(
2726 roles.SelectStatementRole, statement, apply_propagate_attrs=self
2727 )
2728 self._statement = statement
2729 return self
2730
2731 def first(self) -> Optional[_T]:
2732 """Return the first result of this ``Query`` or
2733 None if the result doesn't contain any row.
2734
2735 first() applies a limit of one within the generated SQL, so that
2736 only one primary entity row is generated on the server side
2737 (note this may consist of multiple result rows if join-loaded
2738 collections are present).
2739
2740 Calling :meth:`_query.Query.first`
2741 results in an execution of the underlying
2742 query.
2743
2744 .. seealso::
2745
2746 :meth:`_query.Query.one`
2747
2748 :meth:`_query.Query.one_or_none`
2749
2750 :meth:`_engine.Result.first` - v2 comparable method.
2751
2752 :meth:`_engine.Result.scalars` - v2 comparable method.
2753
2754 """
2755 # replicates limit(1) behavior
2756 if self._statement is not None:
2757 return self._iter().first() # type: ignore
2758 else:
2759 return self.limit(1)._iter().first() # type: ignore
2760
2761 def one_or_none(self) -> Optional[_T]:
2762 """Return at most one result or raise an exception.
2763
2764 Returns ``None`` if the query selects
2765 no rows. Raises ``sqlalchemy.orm.exc.MultipleResultsFound``
2766 if multiple object identities are returned, or if multiple
2767 rows are returned for a query that returns only scalar values
2768 as opposed to full identity-mapped entities.
2769
2770 Calling :meth:`_query.Query.one_or_none`
2771 results in an execution of the
2772 underlying query.
2773
2774 .. seealso::
2775
2776 :meth:`_query.Query.first`
2777
2778 :meth:`_query.Query.one`
2779
2780 :meth:`_engine.Result.one_or_none` - v2 comparable method.
2781
2782 :meth:`_engine.Result.scalar_one_or_none` - v2 comparable method.
2783
2784 """
2785 return self._iter().one_or_none() # type: ignore
2786
2787 def one(self) -> _T:
2788 """Return exactly one result or raise an exception.
2789
2790 Raises :class:`_exc.NoResultFound` if the query selects no rows.
2791 Raises :class:`_exc.MultipleResultsFound` if multiple object identities
2792 are returned, or if multiple rows are returned for a query that returns
2793 only scalar values as opposed to full identity-mapped entities.
2794
2795 Calling :meth:`.one` results in an execution of the underlying query.
2796
2797 .. seealso::
2798
2799 :meth:`_query.Query.first`
2800
2801 :meth:`_query.Query.one_or_none`
2802
2803 :meth:`_engine.Result.one` - v2 comparable method.
2804
2805 :meth:`_engine.Result.scalar_one` - v2 comparable method.
2806
2807 """
2808 return self._iter().one() # type: ignore
2809
2810 def scalar(self) -> Any:
2811 """Return the first element of the first result or None
2812 if no rows present. If multiple rows are returned,
2813 raises :class:`_exc.MultipleResultsFound`.
2814
2815 >>> session.query(Item).scalar()
2816 <Item>
2817 >>> session.query(Item.id).scalar()
2818 1
2819 >>> session.query(Item.id).filter(Item.id < 0).scalar()
2820 None
2821 >>> session.query(Item.id, Item.name).scalar()
2822 1
2823 >>> session.query(func.count(Parent.id)).scalar()
2824 20
2825
2826 This results in an execution of the underlying query.
2827
2828 .. seealso::
2829
2830 :meth:`_engine.Result.scalar` - v2 comparable method.
2831
2832 """
2833 # TODO: not sure why we can't use result.scalar() here
2834 try:
2835 ret = self.one()
2836 if not isinstance(ret, collections_abc.Sequence):
2837 return ret
2838 return ret[0]
2839 except sa_exc.NoResultFound:
2840 return None
2841
2842 def __iter__(self) -> Iterator[_T]:
2843 result = self._iter()
2844 try:
2845 yield from result # type: ignore
2846 except GeneratorExit:
2847 # issue #8710 - direct iteration is not re-usable after
2848 # an iterable block is broken, so close the result
2849 result._soft_close()
2850 raise
2851
2852 def _iter(self) -> Union[ScalarResult[_T], Result[_T]]:
2853 # new style execution.
2854 params = self._params
2855
2856 statement = self._statement_20()
2857 result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
2858 statement,
2859 params,
2860 execution_options={"_sa_orm_load_options": self.load_options},
2861 )
2862
2863 # legacy: automatically set scalars, unique
2864 if result._attributes.get("is_single_entity", False):
2865 result = cast("Result[_T]", result).scalars()
2866
2867 if (
2868 result._attributes.get("filtered", False)
2869 and not self.load_options._yield_per
2870 ):
2871 result = result.unique()
2872
2873 return result
2874
2875 def __str__(self) -> str:
2876 statement = self._statement_20()
2877
2878 try:
2879 bind = (
2880 self._get_bind_args(statement, self.session.get_bind)
2881 if self.session
2882 else None
2883 )
2884 except sa_exc.UnboundExecutionError:
2885 bind = None
2886
2887 return str(statement.compile(bind))
2888
2889 def _get_bind_args(self, statement: Any, fn: Any, **kw: Any) -> Any:
2890 return fn(clause=statement, **kw)
2891
2892 @property
2893 def column_descriptions(self) -> List[ORMColumnDescription]:
2894 """Return metadata about the columns which would be
2895 returned by this :class:`_query.Query`.
2896
2897 Format is a list of dictionaries::
2898
2899 user_alias = aliased(User, name="user2")
2900 q = sess.query(User, User.id, user_alias)
2901
2902 # this expression:
2903 q.column_descriptions
2904
2905 # would return:
2906 [
2907 {
2908 "name": "User",
2909 "type": User,
2910 "aliased": False,
2911 "expr": User,
2912 "entity": User,
2913 },
2914 {
2915 "name": "id",
2916 "type": Integer(),
2917 "aliased": False,
2918 "expr": User.id,
2919 "entity": User,
2920 },
2921 {
2922 "name": "user2",
2923 "type": User,
2924 "aliased": True,
2925 "expr": user_alias,
2926 "entity": user_alias,
2927 },
2928 ]
2929
2930 .. seealso::
2931
2932 This API is available using :term:`2.0 style` queries as well,
2933 documented at:
2934
2935 * :ref:`queryguide_inspection`
2936
2937 * :attr:`.Select.column_descriptions`
2938
2939 """
2940
2941 return _column_descriptions(self, legacy=True)
2942
2943 @util.deprecated(
2944 "2.0",
2945 "The :meth:`_orm.Query.instances` method is deprecated and will "
2946 "be removed in a future release. "
2947 "Use the Select.from_statement() method or aliased() construct in "
2948 "conjunction with Session.execute() instead.",
2949 )
2950 def instances(
2951 self,
2952 result_proxy: CursorResult[Any],
2953 context: Optional[QueryContext] = None,
2954 ) -> Any:
2955 """Return an ORM result given a :class:`_engine.CursorResult` and
2956 :class:`.QueryContext`.
2957
2958 """
2959 if context is None:
2960 util.warn_deprecated(
2961 "Using the Query.instances() method without a context "
2962 "is deprecated and will be disallowed in a future release. "
2963 "Please make use of :meth:`_query.Query.from_statement` "
2964 "for linking ORM results to arbitrary select constructs.",
2965 version="1.4",
2966 )
2967 compile_state = self._compile_state(for_statement=False)
2968
2969 context = QueryContext(
2970 compile_state,
2971 compile_state.statement,
2972 compile_state.statement,
2973 self._params,
2974 self.session,
2975 self.load_options,
2976 )
2977
2978 result = loading.instances(result_proxy, context)
2979
2980 # legacy: automatically set scalars, unique
2981 if result._attributes.get("is_single_entity", False):
2982 result = result.scalars() # type: ignore
2983
2984 if result._attributes.get("filtered", False):
2985 result = result.unique()
2986
2987 # TODO: isn't this supposed to be a list?
2988 return result
2989
2990 @util.became_legacy_20(
2991 ":meth:`_orm.Query.merge_result`",
2992 alternative="The method is superseded by the "
2993 ":func:`_orm.merge_frozen_result` function.",
2994 enable_warnings=False, # warnings occur via loading.merge_result
2995 )
2996 def merge_result(
2997 self,
2998 iterator: Union[
2999 FrozenResult[Any], Iterable[Sequence[Any]], Iterable[object]
3000 ],
3001 load: bool = True,
3002 ) -> Union[FrozenResult[Any], Iterable[Any]]:
3003 """Merge a result into this :class:`_query.Query` object's Session.
3004
3005 Given an iterator returned by a :class:`_query.Query`
3006 of the same structure
3007 as this one, return an identical iterator of results, with all mapped
3008 instances merged into the session using :meth:`.Session.merge`. This
3009 is an optimized method which will merge all mapped instances,
3010 preserving the structure of the result rows and unmapped columns with
3011 less method overhead than that of calling :meth:`.Session.merge`
3012 explicitly for each value.
3013
3014 The structure of the results is determined based on the column list of
3015 this :class:`_query.Query` - if these do not correspond,
3016 unchecked errors
3017 will occur.
3018
3019 The 'load' argument is the same as that of :meth:`.Session.merge`.
3020
3021 For an example of how :meth:`_query.Query.merge_result` is used, see
3022 the source code for the example :ref:`examples_caching`, where
3023 :meth:`_query.Query.merge_result` is used to efficiently restore state
3024 from a cache back into a target :class:`.Session`.
3025
3026 """
3027
3028 return loading.merge_result(self, iterator, load)
3029
3030 def exists(self) -> Exists:
3031 """A convenience method that turns a query into an EXISTS subquery
3032 of the form EXISTS (SELECT 1 FROM ... WHERE ...).
3033
3034 e.g.::
3035
3036 q = session.query(User).filter(User.name == "fred")
3037 session.query(q.exists())
3038
3039 Producing SQL similar to:
3040
3041 .. sourcecode:: sql
3042
3043 SELECT EXISTS (
3044 SELECT 1 FROM users WHERE users.name = :name_1
3045 ) AS anon_1
3046
3047 The EXISTS construct is usually used in the WHERE clause::
3048
3049 session.query(User.id).filter(q.exists()).scalar()
3050
3051 Note that some databases such as SQL Server don't allow an
3052 EXISTS expression to be present in the columns clause of a
3053 SELECT. To select a simple boolean value based on the exists
3054 as a WHERE, use :func:`.literal`::
3055
3056 from sqlalchemy import literal
3057
3058 session.query(literal(True)).filter(q.exists()).scalar()
3059
3060 .. seealso::
3061
3062 :meth:`_sql.Select.exists` - v2 comparable method.
3063
3064 """
3065
3066 # .add_columns() for the case that we are a query().select_from(X),
3067 # so that ".statement" can be produced (#2995) but also without
3068 # omitting the FROM clause from a query(X) (#2818);
3069 # .with_only_columns() after we have a core select() so that
3070 # we get just "SELECT 1" without any entities.
3071
3072 inner = (
3073 self.enable_eagerloads(False)
3074 .add_columns(sql.literal_column("1"))
3075 .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
3076 ._get_select_statement_only()
3077 .with_only_columns(1)
3078 )
3079
3080 ezero = self._entity_from_pre_ent_zero()
3081 if ezero is not None:
3082 inner = inner.select_from(ezero)
3083
3084 return sql.exists(inner)
3085
3086 def count(self) -> int:
3087 r"""Return a count of rows this the SQL formed by this :class:`Query`
3088 would return.
3089
3090 This generates the SQL for this Query as follows:
3091
3092 .. sourcecode:: sql
3093
3094 SELECT count(1) AS count_1 FROM (
3095 SELECT <rest of query follows...>
3096 ) AS anon_1
3097
3098 The above SQL returns a single row, which is the aggregate value
3099 of the count function; the :meth:`_query.Query.count`
3100 method then returns
3101 that single integer value.
3102
3103 .. warning::
3104
3105 It is important to note that the value returned by
3106 count() is **not the same as the number of ORM objects that this
3107 Query would return from a method such as the .all() method**.
3108 The :class:`_query.Query` object,
3109 when asked to return full entities,
3110 will **deduplicate entries based on primary key**, meaning if the
3111 same primary key value would appear in the results more than once,
3112 only one object of that primary key would be present. This does
3113 not apply to a query that is against individual columns.
3114
3115 .. seealso::
3116
3117 :ref:`faq_query_deduplicating`
3118
3119 For fine grained control over specific columns to count, to skip the
3120 usage of a subquery or otherwise control of the FROM clause, or to use
3121 other aggregate functions, use :attr:`~sqlalchemy.sql.expression.func`
3122 expressions in conjunction with :meth:`~.Session.query`, i.e.::
3123
3124 from sqlalchemy import func
3125
3126 # count User records, without
3127 # using a subquery.
3128 session.query(func.count(User.id))
3129
3130 # return count of user "id" grouped
3131 # by "name"
3132 session.query(func.count(User.id)).group_by(User.name)
3133
3134 from sqlalchemy import distinct
3135
3136 # count distinct "name" values
3137 session.query(func.count(distinct(User.name)))
3138
3139 .. seealso::
3140
3141 :ref:`migration_20_query_usage`
3142
3143 """
3144 col = sql.func.count(sql.literal_column("*"))
3145 return ( # type: ignore
3146 self._legacy_from_self(col).enable_eagerloads(False).scalar()
3147 )
3148
3149 def delete(
3150 self,
3151 synchronize_session: SynchronizeSessionArgument = "auto",
3152 delete_args: Optional[Dict[Any, Any]] = None,
3153 ) -> int:
3154 r"""Perform a DELETE with an arbitrary WHERE clause.
3155
3156 Deletes rows matched by this query from the database.
3157
3158 E.g.::
3159
3160 sess.query(User).filter(User.age == 25).delete(synchronize_session=False)
3161
3162 sess.query(User).filter(User.age == 25).delete(
3163 synchronize_session="evaluate"
3164 )
3165
3166 .. warning::
3167
3168 See the section :ref:`orm_expression_update_delete` for important
3169 caveats and warnings, including limitations when using bulk UPDATE
3170 and DELETE with mapper inheritance configurations.
3171
3172 :param synchronize_session: chooses the strategy to update the
3173 attributes on objects in the session. See the section
3174 :ref:`orm_expression_update_delete` for a discussion of these
3175 strategies.
3176
3177 :param delete_args: Optional dictionary, if present will be passed
3178 to the underlying :func:`_expression.delete` construct as the ``**kw``
3179 for the object. May be used to pass dialect-specific arguments such
3180 as ``mysql_limit``.
3181
3182 .. versionadded:: 2.0.37
3183
3184 :return: the count of rows matched as returned by the database's
3185 "row count" feature.
3186
3187 .. seealso::
3188
3189 :ref:`orm_expression_update_delete`
3190
3191 """ # noqa: E501
3192
3193 bulk_del = BulkDelete(self, delete_args)
3194 if self.dispatch.before_compile_delete:
3195 for fn in self.dispatch.before_compile_delete:
3196 new_query = fn(bulk_del.query, bulk_del)
3197 if new_query is not None:
3198 bulk_del.query = new_query
3199
3200 self = bulk_del.query
3201
3202 delete_ = sql.delete(*self._raw_columns) # type: ignore
3203
3204 if delete_args:
3205 delete_ = delete_.with_dialect_options(**delete_args)
3206
3207 delete_._where_criteria = self._where_criteria
3208 result: CursorResult[Any] = self.session.execute(
3209 delete_,
3210 self._params,
3211 execution_options=self._execution_options.union(
3212 {"synchronize_session": synchronize_session}
3213 ),
3214 )
3215 bulk_del.result = result # type: ignore
3216 self.session.dispatch.after_bulk_delete(bulk_del)
3217 result.close()
3218
3219 return result.rowcount
3220
3221 def update(
3222 self,
3223 values: Dict[_DMLColumnArgument, Any],
3224 synchronize_session: SynchronizeSessionArgument = "auto",
3225 update_args: Optional[Dict[Any, Any]] = None,
3226 ) -> int:
3227 r"""Perform an UPDATE with an arbitrary WHERE clause.
3228
3229 Updates rows matched by this query in the database.
3230
3231 E.g.::
3232
3233 sess.query(User).filter(User.age == 25).update(
3234 {User.age: User.age - 10}, synchronize_session=False
3235 )
3236
3237 sess.query(User).filter(User.age == 25).update(
3238 {"age": User.age - 10}, synchronize_session="evaluate"
3239 )
3240
3241 .. warning::
3242
3243 See the section :ref:`orm_expression_update_delete` for important
3244 caveats and warnings, including limitations when using arbitrary
3245 UPDATE and DELETE with mapper inheritance configurations.
3246
3247 :param values: a dictionary with attributes names, or alternatively
3248 mapped attributes or SQL expressions, as keys, and literal
3249 values or sql expressions as values. If :ref:`parameter-ordered
3250 mode <tutorial_parameter_ordered_updates>` is desired, the values can
3251 be passed as a list of 2-tuples; this requires that the
3252 :paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order`
3253 flag is passed to the :paramref:`.Query.update.update_args` dictionary
3254 as well.
3255
3256 :param synchronize_session: chooses the strategy to update the
3257 attributes on objects in the session. See the section
3258 :ref:`orm_expression_update_delete` for a discussion of these
3259 strategies.
3260
3261 :param update_args: Optional dictionary, if present will be passed
3262 to the underlying :func:`_expression.update` construct as the ``**kw``
3263 for the object. May be used to pass dialect-specific arguments such
3264 as ``mysql_limit``, as well as other special arguments such as
3265 :paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order`.
3266
3267 :return: the count of rows matched as returned by the database's
3268 "row count" feature.
3269
3270
3271 .. seealso::
3272
3273 :ref:`orm_expression_update_delete`
3274
3275 """
3276
3277 update_args = update_args or {}
3278
3279 bulk_ud = BulkUpdate(self, values, update_args)
3280
3281 if self.dispatch.before_compile_update:
3282 for fn in self.dispatch.before_compile_update:
3283 new_query = fn(bulk_ud.query, bulk_ud)
3284 if new_query is not None:
3285 bulk_ud.query = new_query
3286 self = bulk_ud.query
3287
3288 upd = sql.update(*self._raw_columns) # type: ignore
3289
3290 ppo = update_args.pop("preserve_parameter_order", False)
3291 if ppo:
3292 upd = upd.ordered_values(*values) # type: ignore
3293 else:
3294 upd = upd.values(values)
3295 if update_args:
3296 upd = upd.with_dialect_options(**update_args)
3297
3298 upd._where_criteria = self._where_criteria
3299 result: CursorResult[Any] = self.session.execute(
3300 upd,
3301 self._params,
3302 execution_options=self._execution_options.union(
3303 {"synchronize_session": synchronize_session}
3304 ),
3305 )
3306 bulk_ud.result = result # type: ignore
3307 self.session.dispatch.after_bulk_update(bulk_ud)
3308 result.close()
3309 return result.rowcount
3310
3311 def _compile_state(
3312 self, for_statement: bool = False, **kw: Any
3313 ) -> ORMCompileState:
3314 """Create an out-of-compiler ORMCompileState object.
3315
3316 The ORMCompileState object is normally created directly as a result
3317 of the SQLCompiler.process() method being handed a Select()
3318 or FromStatement() object that uses the "orm" plugin. This method
3319 provides a means of creating this ORMCompileState object directly
3320 without using the compiler.
3321
3322 This method is used only for deprecated cases, which include
3323 the .from_self() method for a Query that has multiple levels
3324 of .from_self() in use, as well as the instances() method. It is
3325 also used within the test suite to generate ORMCompileState objects
3326 for test purposes.
3327
3328 """
3329
3330 stmt = self._statement_20(for_statement=for_statement, **kw)
3331 assert for_statement == stmt._compile_options._for_statement
3332
3333 # this chooses between ORMFromStatementCompileState and
3334 # ORMSelectCompileState. We could also base this on
3335 # query._statement is not None as we have the ORM Query here
3336 # however this is the more general path.
3337 compile_state_cls = cast(
3338 ORMCompileState,
3339 ORMCompileState._get_plugin_class_for_plugin(stmt, "orm"),
3340 )
3341
3342 return compile_state_cls._create_orm_context(
3343 stmt, toplevel=True, compiler=None
3344 )
3345
3346 def _compile_context(self, for_statement: bool = False) -> QueryContext:
3347 compile_state = self._compile_state(for_statement=for_statement)
3348 context = QueryContext(
3349 compile_state,
3350 compile_state.statement,
3351 compile_state.statement,
3352 self._params,
3353 self.session,
3354 self.load_options,
3355 )
3356
3357 return context
3358
3359
3360class AliasOption(interfaces.LoaderOption):
3361 inherit_cache = False
3362
3363 @util.deprecated(
3364 "1.4",
3365 "The :class:`.AliasOption` object is not necessary "
3366 "for entities to be matched up to a query that is established "
3367 "via :meth:`.Query.from_statement` and now does nothing.",
3368 )
3369 def __init__(self, alias: Union[Alias, Subquery]):
3370 r"""Return a :class:`.MapperOption` that will indicate to the
3371 :class:`_query.Query`
3372 that the main table has been aliased.
3373
3374 """
3375
3376 def process_compile_state(self, compile_state: ORMCompileState) -> None:
3377 pass
3378
3379
3380class BulkUD:
3381 """State used for the orm.Query version of update() / delete().
3382
3383 This object is now specific to Query only.
3384
3385 """
3386
3387 def __init__(self, query: Query[Any]):
3388 self.query = query.enable_eagerloads(False)
3389 self._validate_query_state()
3390 self.mapper = self.query._entity_from_pre_ent_zero()
3391
3392 def _validate_query_state(self) -> None:
3393 for attr, methname, notset, op in (
3394 ("_limit_clause", "limit()", None, operator.is_),
3395 ("_offset_clause", "offset()", None, operator.is_),
3396 ("_order_by_clauses", "order_by()", (), operator.eq),
3397 ("_group_by_clauses", "group_by()", (), operator.eq),
3398 ("_distinct", "distinct()", False, operator.is_),
3399 (
3400 "_from_obj",
3401 "join(), outerjoin(), select_from(), or from_self()",
3402 (),
3403 operator.eq,
3404 ),
3405 (
3406 "_setup_joins",
3407 "join(), outerjoin(), select_from(), or from_self()",
3408 (),
3409 operator.eq,
3410 ),
3411 ):
3412 if not op(getattr(self.query, attr), notset):
3413 raise sa_exc.InvalidRequestError(
3414 "Can't call Query.update() or Query.delete() "
3415 "when %s has been called" % (methname,)
3416 )
3417
3418 @property
3419 def session(self) -> Session:
3420 return self.query.session
3421
3422
3423class BulkUpdate(BulkUD):
3424 """BulkUD which handles UPDATEs."""
3425
3426 def __init__(
3427 self,
3428 query: Query[Any],
3429 values: Dict[_DMLColumnArgument, Any],
3430 update_kwargs: Optional[Dict[Any, Any]],
3431 ):
3432 super().__init__(query)
3433 self.values = values
3434 self.update_kwargs = update_kwargs
3435
3436
3437class BulkDelete(BulkUD):
3438 """BulkUD which handles DELETEs."""
3439
3440 def __init__(
3441 self,
3442 query: Query[Any],
3443 delete_kwargs: Optional[Dict[Any, Any]],
3444 ):
3445 super().__init__(query)
3446 self.delete_kwargs = delete_kwargs
3447
3448
3449class RowReturningQuery(Query[Row[_TP]]):
3450 if TYPE_CHECKING:
3451
3452 def tuples(self) -> Query[_TP]: # type: ignore
3453 ...