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