Plain is headed towards 1.0! Subscribe for development updates →

   1"""
   2Create SQL statements for QuerySets.
   3
   4The code in here encapsulates all of the SQL construction so that QuerySets
   5themselves do not have to (and could be backed by things other than SQL
   6databases). The abstraction barrier only works one way: this module has to know
   7all about the internals of models in order to get the information it needs.
   8"""
   9
  10from __future__ import annotations
  11
  12import copy
  13import difflib
  14import functools
  15import sys
  16from collections import Counter, namedtuple
  17from collections.abc import Iterator, Mapping
  18from collections.abc import Iterator as TypingIterator
  19from functools import cached_property
  20from itertools import chain, count, product
  21from string import ascii_uppercase
  22from typing import TYPE_CHECKING, Any
  23
  24from plain.models.aggregates import Count
  25from plain.models.constants import LOOKUP_SEP
  26from plain.models.db import NotSupportedError, db_connection
  27from plain.models.exceptions import FieldDoesNotExist, FieldError
  28from plain.models.expressions import (
  29    BaseExpression,
  30    Col,
  31    Exists,
  32    F,
  33    OuterRef,
  34    Ref,
  35    ResolvedOuterRef,
  36    Value,
  37)
  38from plain.models.fields import Field
  39from plain.models.fields.related_lookups import MultiColSource
  40from plain.models.lookups import Lookup
  41from plain.models.query_utils import (
  42    Q,
  43    check_rel_lookup_compatibility,
  44    refs_expression,
  45)
  46from plain.models.sql.constants import INNER, LOUTER, ORDER_DIR, SINGLE
  47from plain.models.sql.datastructures import BaseTable, Empty, Join, MultiJoin
  48from plain.models.sql.where import AND, OR, ExtraWhere, NothingNode, WhereNode
  49from plain.utils.regex_helper import _lazy_re_compile
  50from plain.utils.tree import Node
  51
  52if TYPE_CHECKING:
  53    from plain.models import Model
  54    from plain.models.backends.base.base import BaseDatabaseWrapper
  55    from plain.models.meta import Meta
  56    from plain.models.sql.compiler import SQLCompiler
  57
  58
  59__all__ = ["Query", "RawQuery"]
  60
  61# Quotation marks ('"`[]), whitespace characters, semicolons, or inline
  62# SQL comments are forbidden in column aliases.
  63FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|--|/\*|\*/")
  64
  65# Inspired from
  66# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
  67EXPLAIN_OPTIONS_PATTERN = _lazy_re_compile(r"[\w\-]+")
  68
  69
  70def get_field_names_from_opts(meta: Meta | None) -> set[str]:
  71    if meta is None:
  72        return set()
  73    return set(
  74        chain.from_iterable(
  75            (f.name, f.attname) if f.concrete else (f.name,) for f in meta.get_fields()
  76        )
  77    )
  78
  79
  80def get_children_from_q(q: Q) -> TypingIterator[tuple[str, Any]]:
  81    for child in q.children:
  82        if isinstance(child, Node):
  83            yield from get_children_from_q(child)
  84        else:
  85            yield child
  86
  87
  88JoinInfo = namedtuple(
  89    "JoinInfo",
  90    ("final_field", "targets", "meta", "joins", "path", "transform_function"),
  91)
  92
  93
  94class RawQuery:
  95    """A single raw SQL query."""
  96
  97    def __init__(self, sql: str, params: tuple[Any, ...] | dict[str, Any] = ()):
  98        self.params = params
  99        self.sql = sql
 100        self.cursor = None
 101
 102        # Mirror some properties of a normal query so that
 103        # the compiler can be used to process results.
 104        self.low_mark, self.high_mark = 0, None  # Used for offset/limit
 105        self.extra_select = {}
 106        self.annotation_select = {}
 107
 108    def chain(self) -> RawQuery:
 109        return self.clone()
 110
 111    def clone(self) -> RawQuery:
 112        return RawQuery(self.sql, params=self.params)
 113
 114    def get_columns(self) -> list[str]:
 115        if self.cursor is None:
 116            self._execute_query()
 117        converter = db_connection.introspection.identifier_converter
 118        return [
 119            converter(column_model_meta[0])
 120            for column_model_meta in self.cursor.description
 121        ]
 122
 123    def __iter__(self) -> TypingIterator[Any]:
 124        # Always execute a new query for a new iterator.
 125        # This could be optimized with a cache at the expense of RAM.
 126        self._execute_query()
 127        if not db_connection.features.can_use_chunked_reads:
 128            # If the database can't use chunked reads we need to make sure we
 129            # evaluate the entire query up front.
 130            result = list(self.cursor)
 131        else:
 132            result = self.cursor
 133        return iter(result)
 134
 135    def __repr__(self) -> str:
 136        return f"<{self.__class__.__name__}: {self}>"
 137
 138    @property
 139    def params_type(self) -> type[dict] | type[tuple] | None:
 140        if self.params is None:
 141            return None
 142        return dict if isinstance(self.params, Mapping) else tuple
 143
 144    def __str__(self) -> str:
 145        if self.params_type is None:
 146            return self.sql
 147        return self.sql % self.params_type(self.params)
 148
 149    def _execute_query(self) -> None:
 150        # Adapt parameters to the database, as much as possible considering
 151        # that the target type isn't known. See #17755.
 152        params_type = self.params_type
 153        adapter = db_connection.ops.adapt_unknown_value
 154        if params_type is tuple:
 155            params = tuple(adapter(val) for val in self.params)
 156        elif params_type is dict:
 157            params = {key: adapter(val) for key, val in self.params.items()}
 158        elif params_type is None:
 159            params = None
 160        else:
 161            raise RuntimeError(f"Unexpected params type: {params_type}")
 162
 163        self.cursor = db_connection.cursor()
 164        self.cursor.execute(self.sql, params)
 165
 166
 167ExplainInfo = namedtuple("ExplainInfo", ("format", "options"))
 168
 169
 170class Query(BaseExpression):
 171    """A single SQL query."""
 172
 173    alias_prefix = "T"
 174    empty_result_set_value = None
 175    subq_aliases = frozenset([alias_prefix])
 176
 177    compiler = "SQLCompiler"
 178
 179    base_table_class = BaseTable
 180    join_class = Join
 181
 182    default_cols = True
 183    default_ordering = True
 184    standard_ordering = True
 185
 186    filter_is_sticky = False
 187    subquery = False
 188
 189    # SQL-related attributes.
 190    # Select and related select clauses are expressions to use in the SELECT
 191    # clause of the query. The select is used for cases where we want to set up
 192    # the select clause to contain other than default fields (values(),
 193    # subqueries...). Note that annotations go to annotations dictionary.
 194    select = ()
 195    # The group_by attribute can have one of the following forms:
 196    #  - None: no group by at all in the query
 197    #  - A tuple of expressions: group by (at least) those expressions.
 198    #    String refs are also allowed for now.
 199    #  - True: group by all select fields of the model
 200    # See compiler.get_group_by() for details.
 201    group_by = None
 202    order_by = ()
 203    low_mark = 0  # Used for offset/limit.
 204    high_mark = None  # Used for offset/limit.
 205    distinct = False
 206    distinct_fields = ()
 207    select_for_update = False
 208    select_for_update_nowait = False
 209    select_for_update_skip_locked = False
 210    select_for_update_of = ()
 211    select_for_no_key_update = False
 212    select_related = False
 213    has_select_fields = False
 214    # Arbitrary limit for select_related to prevents infinite recursion.
 215    max_depth = 5
 216    # Holds the selects defined by a call to values() or values_list()
 217    # excluding annotation_select and extra_select.
 218    values_select = ()
 219
 220    # SQL annotation-related attributes.
 221    annotation_select_mask = None
 222    _annotation_select_cache = None
 223
 224    # Set combination attributes.
 225    combinator = None
 226    combinator_all = False
 227    combined_queries = ()
 228
 229    # These are for extensions. The contents are more or less appended verbatim
 230    # to the appropriate clause.
 231    extra_select_mask = None
 232    _extra_select_cache = None
 233
 234    extra_tables = ()
 235    extra_order_by = ()
 236
 237    # A tuple that is a set of model field names and either True, if these are
 238    # the fields to defer, or False if these are the only fields to load.
 239    deferred_loading = (frozenset(), True)
 240
 241    explain_info = None
 242
 243    def __init__(self, model: type[Model], alias_cols: bool = True):
 244        self.model = model
 245        self.alias_refcount = {}
 246        # alias_map is the most important data structure regarding joins.
 247        # It's used for recording which joins exist in the query and what
 248        # types they are. The key is the alias of the joined table (possibly
 249        # the table name) and the value is a Join-like object (see
 250        # sql.datastructures.Join for more information).
 251        self.alias_map = {}
 252        # Whether to provide alias to columns during reference resolving.
 253        self.alias_cols = alias_cols
 254        # Sometimes the query contains references to aliases in outer queries (as
 255        # a result of split_exclude). Correct alias quoting needs to know these
 256        # aliases too.
 257        # Map external tables to whether they are aliased.
 258        self.external_aliases = {}
 259        self.table_map = {}  # Maps table names to list of aliases.
 260        self.used_aliases = set()
 261
 262        self.where = WhereNode()
 263        # Maps alias -> Annotation Expression.
 264        self.annotations = {}
 265        # These are for extensions. The contents are more or less appended
 266        # verbatim to the appropriate clause.
 267        self.extra = {}  # Maps col_alias -> (col_sql, params).
 268
 269        self._filtered_relations = {}
 270
 271    @property
 272    def output_field(self) -> Field | None:  # type: ignore[return]
 273        if len(self.select) == 1:
 274            select = self.select[0]
 275            return getattr(select, "target", None) or select.field
 276        elif len(self.annotation_select) == 1:
 277            return next(iter(self.annotation_select.values())).output_field
 278
 279    @cached_property
 280    def base_table(self) -> str | None:
 281        for alias in self.alias_map:
 282            return alias
 283
 284    def __str__(self) -> str:
 285        """
 286        Return the query as a string of SQL with the parameter values
 287        substituted in (use sql_with_params() to see the unsubstituted string).
 288
 289        Parameter values won't necessarily be quoted correctly, since that is
 290        done by the database interface at execution time.
 291        """
 292        sql, params = self.sql_with_params()
 293        return sql % params
 294
 295    def sql_with_params(self) -> tuple[str, tuple[Any, ...]]:
 296        """
 297        Return the query as an SQL string and the parameters that will be
 298        substituted into the query.
 299        """
 300        return self.get_compiler().as_sql()
 301
 302    def __deepcopy__(self, memo: dict[int, Any]) -> Query:
 303        """Limit the amount of work when a Query is deepcopied."""
 304        result = self.clone()
 305        memo[id(self)] = result
 306        return result
 307
 308    def get_compiler(self, *, elide_empty: bool = True) -> Any:
 309        return db_connection.ops.compiler(self.compiler)(
 310            self, db_connection, elide_empty
 311        )
 312
 313    def get_model_meta(self) -> Meta:
 314        """
 315        Return the Meta instance (the model._model_meta) from which to start
 316        processing. Normally, this is self.model._model_meta, but it can be changed
 317        by subclasses.
 318        """
 319        return self.model._model_meta
 320
 321    def clone(self) -> Query:
 322        """
 323        Return a copy of the current Query. A lightweight alternative to
 324        deepcopy().
 325        """
 326        obj = Empty()  # type: ignore[misc]
 327        obj.__class__ = self.__class__  # type: ignore[misc]
 328        # Copy references to everything.
 329        obj.__dict__ = self.__dict__.copy()  # type: ignore[attr-defined]
 330        # Clone attributes that can't use shallow copy.
 331        obj.alias_refcount = self.alias_refcount.copy()  # type: ignore[attr-defined]
 332        obj.alias_map = self.alias_map.copy()  # type: ignore[attr-defined]
 333        obj.external_aliases = self.external_aliases.copy()  # type: ignore[attr-defined]
 334        obj.table_map = self.table_map.copy()  # type: ignore[attr-defined]
 335        obj.where = self.where.clone()  # type: ignore[attr-defined]
 336        obj.annotations = self.annotations.copy()  # type: ignore[attr-defined]
 337        if self.annotation_select_mask is not None:
 338            obj.annotation_select_mask = self.annotation_select_mask.copy()  # type: ignore[attr-defined]
 339        if self.combined_queries:
 340            obj.combined_queries = tuple(  # type: ignore[attr-defined]
 341                [query.clone() for query in self.combined_queries]
 342            )
 343        # _annotation_select_cache cannot be copied, as doing so breaks the
 344        # (necessary) state in which both annotations and
 345        # _annotation_select_cache point to the same underlying objects.
 346        # It will get re-populated in the cloned queryset the next time it's
 347        # used.
 348        obj._annotation_select_cache = None  # type: ignore[attr-defined]
 349        obj.extra = self.extra.copy()  # type: ignore[attr-defined]
 350        if self.extra_select_mask is not None:
 351            obj.extra_select_mask = self.extra_select_mask.copy()  # type: ignore[attr-defined]
 352        if self._extra_select_cache is not None:
 353            obj._extra_select_cache = self._extra_select_cache.copy()  # type: ignore[attr-defined]
 354        if self.select_related is not False:
 355            # Use deepcopy because select_related stores fields in nested
 356            # dicts.
 357            obj.select_related = copy.deepcopy(obj.select_related)  # type: ignore[attr-defined]
 358        if "subq_aliases" in self.__dict__:
 359            obj.subq_aliases = self.subq_aliases.copy()  # type: ignore[attr-defined]
 360        obj.used_aliases = self.used_aliases.copy()  # type: ignore[attr-defined]
 361        obj._filtered_relations = self._filtered_relations.copy()  # type: ignore[attr-defined]
 362        # Clear the cached_property, if it exists.
 363        obj.__dict__.pop("base_table", None)
 364        return obj  # type: ignore[return-value]
 365
 366    def chain(self, klass: type[Query] | None = None) -> Query:
 367        """
 368        Return a copy of the current Query that's ready for another operation.
 369        The klass argument changes the type of the Query, e.g. UpdateQuery.
 370        """
 371        obj = self.clone()
 372        if klass and obj.__class__ != klass:
 373            obj.__class__ = klass  # type: ignore[misc]
 374        if not obj.filter_is_sticky:
 375            obj.used_aliases = set()  # type: ignore[attr-defined]
 376        obj.filter_is_sticky = False
 377        if hasattr(obj, "_setup_query"):
 378            obj._setup_query()  # type: ignore[attr-defined]
 379        return obj  # type: ignore[return-value]
 380
 381    def relabeled_clone(self, change_map: dict[str, str]) -> Query:
 382        clone = self.clone()
 383        clone.change_aliases(change_map)
 384        return clone
 385
 386    def _get_col(self, target: Any, field: Field, alias: str | None) -> Col:
 387        if not self.alias_cols:
 388            alias = None
 389        return target.get_col(alias, field)
 390
 391    def get_aggregation(self, aggregate_exprs: dict[str, Any]) -> dict[str, Any]:
 392        """
 393        Return the dictionary with the values of the existing aggregations.
 394        """
 395        if not aggregate_exprs:
 396            return {}
 397        aggregates = {}
 398        for alias, aggregate_expr in aggregate_exprs.items():
 399            self.check_alias(alias)
 400            aggregate = aggregate_expr.resolve_expression(
 401                self, allow_joins=True, reuse=None, summarize=True
 402            )
 403            if not aggregate.contains_aggregate:
 404                raise TypeError(f"{alias} is not an aggregate expression")
 405            aggregates[alias] = aggregate
 406        # Existing usage of aggregation can be determined by the presence of
 407        # selected aggregates but also by filters against aliased aggregates.
 408        _, having, qualify = self.where.split_having_qualify()
 409        has_existing_aggregation = (
 410            any(
 411                getattr(annotation, "contains_aggregate", True)
 412                for annotation in self.annotations.values()
 413            )
 414            or having
 415        )
 416        # Decide if we need to use a subquery.
 417        #
 418        # Existing aggregations would cause incorrect results as
 419        # get_aggregation() must produce just one result and thus must not use
 420        # GROUP BY.
 421        #
 422        # If the query has limit or distinct, or uses set operations, then
 423        # those operations must be done in a subquery so that the query
 424        # aggregates on the limit and/or distinct results instead of applying
 425        # the distinct and limit after the aggregation.
 426        if (
 427            isinstance(self.group_by, tuple)
 428            or self.is_sliced
 429            or has_existing_aggregation
 430            or qualify
 431            or self.distinct
 432            or self.combinator
 433        ):
 434            from plain.models.sql.subqueries import AggregateQuery
 435
 436            inner_query = self.clone()
 437            inner_query.subquery = True
 438            outer_query = AggregateQuery(self.model, inner_query)
 439            inner_query.select_for_update = False
 440            inner_query.select_related = False
 441            inner_query.set_annotation_mask(self.annotation_select)
 442            # Queries with distinct_fields need ordering and when a limit is
 443            # applied we must take the slice from the ordered query. Otherwise
 444            # no need for ordering.
 445            inner_query.clear_ordering(force=False)
 446            if not inner_query.distinct:
 447                # If the inner query uses default select and it has some
 448                # aggregate annotations, then we must make sure the inner
 449                # query is grouped by the main model's primary key. However,
 450                # clearing the select clause can alter results if distinct is
 451                # used.
 452                if inner_query.default_cols and has_existing_aggregation:
 453                    inner_query.group_by = (
 454                        self.model._model_meta.get_field("id").get_col(
 455                            inner_query.get_initial_alias()
 456                        ),
 457                    )
 458                inner_query.default_cols = False
 459                if not qualify:
 460                    # Mask existing annotations that are not referenced by
 461                    # aggregates to be pushed to the outer query unless
 462                    # filtering against window functions is involved as it
 463                    # requires complex realising.
 464                    annotation_mask = set()
 465                    for aggregate in aggregates.values():
 466                        annotation_mask |= aggregate.get_refs()
 467                    inner_query.set_annotation_mask(annotation_mask)
 468
 469            # Add aggregates to the outer AggregateQuery. This requires making
 470            # sure all columns referenced by the aggregates are selected in the
 471            # inner query. It is achieved by retrieving all column references
 472            # by the aggregates, explicitly selecting them in the inner query,
 473            # and making sure the aggregates are repointed to them.
 474            col_refs = {}
 475            for alias, aggregate in aggregates.items():
 476                replacements = {}
 477                for col in self._gen_cols([aggregate], resolve_refs=False):
 478                    if not (col_ref := col_refs.get(col)):
 479                        index = len(col_refs) + 1
 480                        col_alias = f"__col{index}"
 481                        col_ref = Ref(col_alias, col)
 482                        col_refs[col] = col_ref
 483                        inner_query.annotations[col_alias] = col
 484                        inner_query.append_annotation_mask([col_alias])
 485                    replacements[col] = col_ref
 486                outer_query.annotations[alias] = aggregate.replace_expressions(
 487                    replacements
 488                )
 489            if (
 490                inner_query.select == ()
 491                and not inner_query.default_cols
 492                and not inner_query.annotation_select_mask
 493            ):
 494                # In case of Model.objects[0:3].count(), there would be no
 495                # field selected in the inner query, yet we must use a subquery.
 496                # So, make sure at least one field is selected.
 497                inner_query.select = (
 498                    self.model._model_meta.get_field("id").get_col(
 499                        inner_query.get_initial_alias()
 500                    ),
 501                )
 502        else:
 503            outer_query = self
 504            self.select = ()
 505            self.default_cols = False
 506            self.extra = {}
 507            if self.annotations:
 508                # Inline reference to existing annotations and mask them as
 509                # they are unnecessary given only the summarized aggregations
 510                # are requested.
 511                replacements = {
 512                    Ref(alias, annotation): annotation
 513                    for alias, annotation in self.annotations.items()
 514                }
 515                self.annotations = {
 516                    alias: aggregate.replace_expressions(replacements)
 517                    for alias, aggregate in aggregates.items()
 518                }
 519            else:
 520                self.annotations = aggregates
 521            self.set_annotation_mask(aggregates)
 522
 523        empty_set_result = [
 524            expression.empty_result_set_value
 525            for expression in outer_query.annotation_select.values()
 526        ]
 527        elide_empty = not any(result is NotImplemented for result in empty_set_result)
 528        outer_query.clear_ordering(force=True)
 529        outer_query.clear_limits()
 530        outer_query.select_for_update = False
 531        outer_query.select_related = False
 532        compiler = outer_query.get_compiler(elide_empty=elide_empty)
 533        result = compiler.execute_sql(SINGLE)
 534        if result is None:
 535            result = empty_set_result
 536        else:
 537            converters = compiler.get_converters(outer_query.annotation_select.values())
 538            result = next(compiler.apply_converters((result,), converters))
 539
 540        return dict(zip(outer_query.annotation_select, result))
 541
 542    def get_count(self) -> int:
 543        """
 544        Perform a COUNT() query using the current filter constraints.
 545        """
 546        obj = self.clone()
 547        return obj.get_aggregation({"__count": Count("*")})["__count"]
 548
 549    def has_filters(self) -> bool:
 550        return self.where
 551
 552    def exists(self, limit: bool = True) -> Query:
 553        q = self.clone()
 554        if not (q.distinct and q.is_sliced):
 555            if q.group_by is True:
 556                q.add_fields(
 557                    (f.attname for f in self.model._model_meta.concrete_fields), False
 558                )
 559                # Disable GROUP BY aliases to avoid orphaning references to the
 560                # SELECT clause which is about to be cleared.
 561                q.set_group_by(allow_aliases=False)
 562            q.clear_select_clause()
 563        if q.combined_queries and q.combinator == "union":
 564            q.combined_queries = tuple(
 565                combined_query.exists(limit=False)
 566                for combined_query in q.combined_queries
 567            )
 568        q.clear_ordering(force=True)
 569        if limit:
 570            q.set_limits(high=1)
 571        q.add_annotation(Value(1), "a")
 572        return q
 573
 574    def has_results(self) -> bool:
 575        q = self.exists()
 576        compiler = q.get_compiler()
 577        return compiler.has_results()
 578
 579    def explain(self, format: str | None = None, **options: Any) -> str:
 580        q = self.clone()
 581        for option_name in options:
 582            if (
 583                not EXPLAIN_OPTIONS_PATTERN.fullmatch(option_name)
 584                or "--" in option_name
 585            ):
 586                raise ValueError(f"Invalid option name: {option_name!r}.")
 587        q.explain_info = ExplainInfo(format, options)
 588        compiler = q.get_compiler()
 589        return "\n".join(compiler.explain_query())
 590
 591    def combine(self, rhs: Query, connector: str) -> None:
 592        """
 593        Merge the 'rhs' query into the current one (with any 'rhs' effects
 594        being applied *after* (that is, "to the right of") anything in the
 595        current query. 'rhs' is not modified during a call to this function.
 596
 597        The 'connector' parameter describes how to connect filters from the
 598        'rhs' query.
 599        """
 600        if self.model != rhs.model:
 601            raise TypeError("Cannot combine queries on two different base models.")
 602        if self.is_sliced:
 603            raise TypeError("Cannot combine queries once a slice has been taken.")
 604        if self.distinct != rhs.distinct:
 605            raise TypeError("Cannot combine a unique query with a non-unique query.")
 606        if self.distinct_fields != rhs.distinct_fields:
 607            raise TypeError("Cannot combine queries with different distinct fields.")
 608
 609        # If lhs and rhs shares the same alias prefix, it is possible to have
 610        # conflicting alias changes like T4 -> T5, T5 -> T6, which might end up
 611        # as T4 -> T6 while combining two querysets. To prevent this, change an
 612        # alias prefix of the rhs and update current aliases accordingly,
 613        # except if the alias is the base table since it must be present in the
 614        # query on both sides.
 615        initial_alias = self.get_initial_alias()
 616        rhs.bump_prefix(self, exclude={initial_alias})
 617
 618        # Work out how to relabel the rhs aliases, if necessary.
 619        change_map = {}
 620        conjunction = connector == AND
 621
 622        # Determine which existing joins can be reused. When combining the
 623        # query with AND we must recreate all joins for m2m filters. When
 624        # combining with OR we can reuse joins. The reason is that in AND
 625        # case a single row can't fulfill a condition like:
 626        #     revrel__col=1 & revrel__col=2
 627        # But, there might be two different related rows matching this
 628        # condition. In OR case a single True is enough, so single row is
 629        # enough, too.
 630        #
 631        # Note that we will be creating duplicate joins for non-m2m joins in
 632        # the AND case. The results will be correct but this creates too many
 633        # joins. This is something that could be fixed later on.
 634        reuse = set() if conjunction else set(self.alias_map)
 635        joinpromoter = JoinPromoter(connector, 2, False)
 636        joinpromoter.add_votes(
 637            j for j in self.alias_map if self.alias_map[j].join_type == INNER
 638        )
 639        rhs_votes = set()
 640        # Now, add the joins from rhs query into the new query (skipping base
 641        # table).
 642        rhs_tables = list(rhs.alias_map)[1:]
 643        for alias in rhs_tables:
 644            join = rhs.alias_map[alias]
 645            # If the left side of the join was already relabeled, use the
 646            # updated alias.
 647            join = join.relabeled_clone(change_map)
 648            new_alias = self.join(join, reuse=reuse)
 649            if join.join_type == INNER:
 650                rhs_votes.add(new_alias)
 651            # We can't reuse the same join again in the query. If we have two
 652            # distinct joins for the same connection in rhs query, then the
 653            # combined query must have two joins, too.
 654            reuse.discard(new_alias)
 655            if alias != new_alias:
 656                change_map[alias] = new_alias
 657            if not rhs.alias_refcount[alias]:
 658                # The alias was unused in the rhs query. Unref it so that it
 659                # will be unused in the new query, too. We have to add and
 660                # unref the alias so that join promotion has information of
 661                # the join type for the unused alias.
 662                self.unref_alias(new_alias)
 663        joinpromoter.add_votes(rhs_votes)
 664        joinpromoter.update_join_types(self)
 665
 666        # Combine subqueries aliases to ensure aliases relabelling properly
 667        # handle subqueries when combining where and select clauses.
 668        self.subq_aliases |= rhs.subq_aliases
 669
 670        # Now relabel a copy of the rhs where-clause and add it to the current
 671        # one.
 672        w = rhs.where.clone()
 673        w.relabel_aliases(change_map)
 674        self.where.add(w, connector)
 675
 676        # Selection columns and extra extensions are those provided by 'rhs'.
 677        if rhs.select:
 678            self.set_select([col.relabeled_clone(change_map) for col in rhs.select])
 679        else:
 680            self.select = ()
 681
 682        if connector == OR:
 683            # It would be nice to be able to handle this, but the queries don't
 684            # really make sense (or return consistent value sets). Not worth
 685            # the extra complexity when you can write a real query instead.
 686            if self.extra and rhs.extra:
 687                raise ValueError(
 688                    "When merging querysets using 'or', you cannot have "
 689                    "extra(select=...) on both sides."
 690                )
 691        self.extra.update(rhs.extra)
 692        extra_select_mask = set()
 693        if self.extra_select_mask is not None:
 694            extra_select_mask.update(self.extra_select_mask)
 695        if rhs.extra_select_mask is not None:
 696            extra_select_mask.update(rhs.extra_select_mask)
 697        if extra_select_mask:
 698            self.set_extra_mask(extra_select_mask)
 699        self.extra_tables += rhs.extra_tables
 700
 701        # Ordering uses the 'rhs' ordering, unless it has none, in which case
 702        # the current ordering is used.
 703        self.order_by = rhs.order_by or self.order_by
 704        self.extra_order_by = rhs.extra_order_by or self.extra_order_by
 705
 706    def _get_defer_select_mask(
 707        self,
 708        meta: Meta,
 709        mask: dict[str, Any],
 710        select_mask: dict[Any, Any] | None = None,
 711    ) -> dict[Any, Any]:
 712        if select_mask is None:
 713            select_mask = {}
 714        select_mask[meta.get_field("id")] = {}
 715        # All concrete fields that are not part of the defer mask must be
 716        # loaded. If a relational field is encountered it gets added to the
 717        # mask for it be considered if `select_related` and the cycle continues
 718        # by recursively calling this function.
 719        for field in meta.concrete_fields:
 720            field_mask = mask.pop(field.name, None)
 721            if field_mask is None:
 722                select_mask.setdefault(field, {})
 723            elif field_mask:
 724                if not field.is_relation:
 725                    raise FieldError(next(iter(field_mask)))
 726                field_select_mask = select_mask.setdefault(field, {})
 727                related_model = field.remote_field.model
 728                self._get_defer_select_mask(
 729                    related_model._model_meta, field_mask, field_select_mask
 730                )
 731        # Remaining defer entries must be references to reverse relationships.
 732        # The following code is expected to raise FieldError if it encounters
 733        # a malformed defer entry.
 734        for field_name, field_mask in mask.items():
 735            if filtered_relation := self._filtered_relations.get(field_name):
 736                relation = meta.get_field(filtered_relation.relation_name)
 737                field_select_mask = select_mask.setdefault((field_name, relation), {})
 738                field = relation.field
 739            else:
 740                field = meta.get_field(field_name).field
 741                field_select_mask = select_mask.setdefault(field, {})
 742            related_model = field.model
 743            self._get_defer_select_mask(
 744                related_model._model_meta, field_mask, field_select_mask
 745            )
 746        return select_mask
 747
 748    def _get_only_select_mask(
 749        self,
 750        meta: Meta,
 751        mask: dict[str, Any],
 752        select_mask: dict[Any, Any] | None = None,
 753    ) -> dict[Any, Any]:
 754        if select_mask is None:
 755            select_mask = {}
 756        select_mask[meta.get_field("id")] = {}
 757        # Only include fields mentioned in the mask.
 758        for field_name, field_mask in mask.items():
 759            field = meta.get_field(field_name)
 760            field_select_mask = select_mask.setdefault(field, {})
 761            if field_mask:
 762                if not field.is_relation:
 763                    raise FieldError(next(iter(field_mask)))
 764                related_model = field.remote_field.model
 765                self._get_only_select_mask(
 766                    related_model._model_meta, field_mask, field_select_mask
 767                )
 768        return select_mask
 769
 770    def get_select_mask(self) -> dict[Any, Any]:
 771        """
 772        Convert the self.deferred_loading data structure to an alternate data
 773        structure, describing the field that *will* be loaded. This is used to
 774        compute the columns to select from the database and also by the
 775        QuerySet class to work out which fields are being initialized on each
 776        model. Models that have all their fields included aren't mentioned in
 777        the result, only those that have field restrictions in place.
 778        """
 779        field_names, defer = self.deferred_loading
 780        if not field_names:
 781            return {}
 782        mask = {}
 783        for field_name in field_names:
 784            part_mask = mask
 785            for part in field_name.split(LOOKUP_SEP):
 786                part_mask = part_mask.setdefault(part, {})
 787        meta = self.get_model_meta()
 788        if defer:
 789            return self._get_defer_select_mask(meta, mask)
 790        return self._get_only_select_mask(meta, mask)
 791
 792    def table_alias(
 793        self, table_name: str, create: bool = False, filtered_relation: Any = None
 794    ) -> tuple[str, bool]:
 795        """
 796        Return a table alias for the given table_name and whether this is a
 797        new alias or not.
 798
 799        If 'create' is true, a new alias is always created. Otherwise, the
 800        most recently created alias for the table (if one exists) is reused.
 801        """
 802        alias_list = self.table_map.get(table_name)
 803        if not create and alias_list:
 804            alias = alias_list[0]
 805            self.alias_refcount[alias] += 1
 806            return alias, False
 807
 808        # Create a new alias for this table.
 809        if alias_list:
 810            alias = "%s%d" % (self.alias_prefix, len(self.alias_map) + 1)  # noqa: UP031
 811            alias_list.append(alias)
 812        else:
 813            # The first occurrence of a table uses the table name directly.
 814            alias = (
 815                filtered_relation.alias if filtered_relation is not None else table_name
 816            )
 817            self.table_map[table_name] = [alias]
 818        self.alias_refcount[alias] = 1
 819        return alias, True
 820
 821    def ref_alias(self, alias: str) -> None:
 822        """Increases the reference count for this alias."""
 823        self.alias_refcount[alias] += 1
 824
 825    def unref_alias(self, alias: str, amount: int = 1) -> None:
 826        """Decreases the reference count for this alias."""
 827        self.alias_refcount[alias] -= amount
 828
 829    def promote_joins(self, aliases: set[str] | list[str]) -> None:
 830        """
 831        Promote recursively the join type of given aliases and its children to
 832        an outer join. If 'unconditional' is False, only promote the join if
 833        it is nullable or the parent join is an outer join.
 834
 835        The children promotion is done to avoid join chains that contain a LOUTER
 836        b INNER c. So, if we have currently a INNER b INNER c and a->b is promoted,
 837        then we must also promote b->c automatically, or otherwise the promotion
 838        of a->b doesn't actually change anything in the query results.
 839        """
 840        aliases = list(aliases)
 841        while aliases:
 842            alias = aliases.pop(0)
 843            if self.alias_map[alias].join_type is None:
 844                # This is the base table (first FROM entry) - this table
 845                # isn't really joined at all in the query, so we should not
 846                # alter its join type.
 847                continue
 848            # Only the first alias (skipped above) should have None join_type
 849            assert self.alias_map[alias].join_type is not None
 850            parent_alias = self.alias_map[alias].parent_alias
 851            parent_louter = (
 852                parent_alias and self.alias_map[parent_alias].join_type == LOUTER
 853            )
 854            already_louter = self.alias_map[alias].join_type == LOUTER
 855            if (self.alias_map[alias].nullable or parent_louter) and not already_louter:
 856                self.alias_map[alias] = self.alias_map[alias].promote()
 857                # Join type of 'alias' changed, so re-examine all aliases that
 858                # refer to this one.
 859                aliases.extend(
 860                    join
 861                    for join in self.alias_map
 862                    if self.alias_map[join].parent_alias == alias
 863                    and join not in aliases
 864                )
 865
 866    def demote_joins(self, aliases: set[str] | list[str]) -> None:
 867        """
 868        Change join type from LOUTER to INNER for all joins in aliases.
 869
 870        Similarly to promote_joins(), this method must ensure no join chains
 871        containing first an outer, then an inner join are generated. If we
 872        are demoting b->c join in chain a LOUTER b LOUTER c then we must
 873        demote a->b automatically, or otherwise the demotion of b->c doesn't
 874        actually change anything in the query results. .
 875        """
 876        aliases = list(aliases)
 877        while aliases:
 878            alias = aliases.pop(0)
 879            if self.alias_map[alias].join_type == LOUTER:
 880                self.alias_map[alias] = self.alias_map[alias].demote()
 881                parent_alias = self.alias_map[alias].parent_alias
 882                if self.alias_map[parent_alias].join_type == INNER:
 883                    aliases.append(parent_alias)
 884
 885    def reset_refcounts(self, to_counts: dict[str, int]) -> None:
 886        """
 887        Reset reference counts for aliases so that they match the value passed
 888        in `to_counts`.
 889        """
 890        for alias, cur_refcount in self.alias_refcount.copy().items():
 891            unref_amount = cur_refcount - to_counts.get(alias, 0)
 892            self.unref_alias(alias, unref_amount)
 893
 894    def change_aliases(self, change_map: dict[str, str]) -> None:
 895        """
 896        Change the aliases in change_map (which maps old-alias -> new-alias),
 897        relabelling any references to them in select columns and the where
 898        clause.
 899        """
 900        # If keys and values of change_map were to intersect, an alias might be
 901        # updated twice (e.g. T4 -> T5, T5 -> T6, so also T4 -> T6) depending
 902        # on their order in change_map.
 903        assert set(change_map).isdisjoint(change_map.values())
 904
 905        # 1. Update references in "select" (normal columns plus aliases),
 906        # "group by" and "where".
 907        self.where.relabel_aliases(change_map)
 908        if isinstance(self.group_by, tuple):
 909            self.group_by = tuple(
 910                [col.relabeled_clone(change_map) for col in self.group_by]
 911            )
 912        self.select = tuple([col.relabeled_clone(change_map) for col in self.select])
 913        self.annotations = self.annotations and {
 914            key: col.relabeled_clone(change_map)
 915            for key, col in self.annotations.items()
 916        }
 917
 918        # 2. Rename the alias in the internal table/alias datastructures.
 919        for old_alias, new_alias in change_map.items():
 920            if old_alias not in self.alias_map:
 921                continue
 922            alias_data = self.alias_map[old_alias].relabeled_clone(change_map)
 923            self.alias_map[new_alias] = alias_data
 924            self.alias_refcount[new_alias] = self.alias_refcount[old_alias]
 925            del self.alias_refcount[old_alias]
 926            del self.alias_map[old_alias]
 927
 928            table_aliases = self.table_map[alias_data.table_name]
 929            for pos, alias in enumerate(table_aliases):
 930                if alias == old_alias:
 931                    table_aliases[pos] = new_alias
 932                    break
 933        self.external_aliases = {
 934            # Table is aliased or it's being changed and thus is aliased.
 935            change_map.get(alias, alias): (aliased or alias in change_map)
 936            for alias, aliased in self.external_aliases.items()
 937        }
 938
 939    def bump_prefix(
 940        self, other_query: Query, exclude: set[str] | dict[str, str] | None = None
 941    ) -> None:
 942        """
 943        Change the alias prefix to the next letter in the alphabet in a way
 944        that the other query's aliases and this query's aliases will not
 945        conflict. Even tables that previously had no alias will get an alias
 946        after this call. To prevent changing aliases use the exclude parameter.
 947        """
 948
 949        def prefix_gen() -> TypingIterator[str]:
 950            """
 951            Generate a sequence of characters in alphabetical order:
 952                -> 'A', 'B', 'C', ...
 953
 954            When the alphabet is finished, the sequence will continue with the
 955            Cartesian product:
 956                -> 'AA', 'AB', 'AC', ...
 957            """
 958            alphabet = ascii_uppercase
 959            prefix = chr(ord(self.alias_prefix) + 1)
 960            yield prefix
 961            for n in count(1):
 962                seq = alphabet[alphabet.index(prefix) :] if prefix else alphabet
 963                for s in product(seq, repeat=n):
 964                    yield "".join(s)
 965                prefix = None
 966
 967        if self.alias_prefix != other_query.alias_prefix:
 968            # No clashes between self and outer query should be possible.
 969            return
 970
 971        # Explicitly avoid infinite loop. The constant divider is based on how
 972        # much depth recursive subquery references add to the stack. This value
 973        # might need to be adjusted when adding or removing function calls from
 974        # the code path in charge of performing these operations.
 975        local_recursion_limit = sys.getrecursionlimit() // 16
 976        for pos, prefix in enumerate(prefix_gen()):
 977            if prefix not in self.subq_aliases:
 978                self.alias_prefix = prefix
 979                break
 980            if pos > local_recursion_limit:
 981                raise RecursionError(
 982                    "Maximum recursion depth exceeded: too many subqueries."
 983                )
 984        self.subq_aliases = self.subq_aliases.union([self.alias_prefix])
 985        other_query.subq_aliases = other_query.subq_aliases.union(self.subq_aliases)
 986        if exclude is None:
 987            exclude = {}
 988        self.change_aliases(
 989            {
 990                alias: "%s%d" % (self.alias_prefix, pos)  # noqa: UP031
 991                for pos, alias in enumerate(self.alias_map)
 992                if alias not in exclude
 993            }
 994        )
 995
 996    def get_initial_alias(self) -> str | None:
 997        """
 998        Return the first alias for this query, after increasing its reference
 999        count.
1000        """
1001        if self.alias_map:
1002            alias = self.base_table
1003            self.ref_alias(alias)
1004        elif self.model:
1005            alias = self.join(
1006                self.base_table_class(self.model.model_options.db_table, None)
1007            )
1008        else:
1009            alias = None
1010        return alias
1011
1012    def count_active_tables(self) -> int:
1013        """
1014        Return the number of tables in this query with a non-zero reference
1015        count. After execution, the reference counts are zeroed, so tables
1016        added in compiler will not be seen by this method.
1017        """
1018        return len([1 for count in self.alias_refcount.values() if count])
1019
1020    def join(
1021        self,
1022        join: BaseTable | Join,
1023        reuse: set[str] | None = None,
1024        reuse_with_filtered_relation: bool = False,
1025    ) -> str:
1026        """
1027        Return an alias for the 'join', either reusing an existing alias for
1028        that join or creating a new one. 'join' is either a base_table_class or
1029        join_class.
1030
1031        The 'reuse' parameter can be either None which means all joins are
1032        reusable, or it can be a set containing the aliases that can be reused.
1033
1034        The 'reuse_with_filtered_relation' parameter is used when computing
1035        FilteredRelation instances.
1036
1037        A join is always created as LOUTER if the lhs alias is LOUTER to make
1038        sure chains like t1 LOUTER t2 INNER t3 aren't generated. All new
1039        joins are created as LOUTER if the join is nullable.
1040        """
1041        if reuse_with_filtered_relation and reuse:
1042            reuse_aliases = [
1043                a for a, j in self.alias_map.items() if a in reuse and j.equals(join)
1044            ]
1045        else:
1046            reuse_aliases = [
1047                a
1048                for a, j in self.alias_map.items()
1049                if (reuse is None or a in reuse) and j == join
1050            ]
1051        if reuse_aliases:
1052            if join.table_alias in reuse_aliases:
1053                reuse_alias = join.table_alias
1054            else:
1055                # Reuse the most recent alias of the joined table
1056                # (a many-to-many relation may be joined multiple times).
1057                reuse_alias = reuse_aliases[-1]
1058            self.ref_alias(reuse_alias)
1059            return reuse_alias
1060
1061        # No reuse is possible, so we need a new alias.
1062        alias, _ = self.table_alias(
1063            join.table_name, create=True, filtered_relation=join.filtered_relation
1064        )
1065        if join.join_type:
1066            if self.alias_map[join.parent_alias].join_type == LOUTER or join.nullable:  # type: ignore[attr-defined]
1067                join_type = LOUTER
1068            else:
1069                join_type = INNER
1070            join.join_type = join_type
1071        join.table_alias = alias
1072        self.alias_map[alias] = join
1073        return alias
1074
1075    def check_alias(self, alias: str) -> None:
1076        if FORBIDDEN_ALIAS_PATTERN.search(alias):
1077            raise ValueError(
1078                "Column aliases cannot contain whitespace characters, quotation marks, "
1079                "semicolons, or SQL comments."
1080            )
1081
1082    def add_annotation(
1083        self, annotation: BaseExpression, alias: str, select: bool = True
1084    ) -> None:
1085        """Add a single annotation expression to the Query."""
1086        self.check_alias(alias)
1087        annotation = annotation.resolve_expression(self, allow_joins=True, reuse=None)
1088        if select:
1089            self.append_annotation_mask([alias])
1090        else:
1091            self.set_annotation_mask(set(self.annotation_select).difference({alias}))
1092        self.annotations[alias] = annotation
1093
1094    def resolve_expression(self, query: Query, *args: Any, **kwargs: Any) -> Query:
1095        clone = self.clone()
1096        # Subqueries need to use a different set of aliases than the outer query.
1097        clone.bump_prefix(query)
1098        clone.subquery = True
1099        clone.where.resolve_expression(query, *args, **kwargs)
1100        # Resolve combined queries.
1101        if clone.combinator:
1102            clone.combined_queries = tuple(
1103                [
1104                    combined_query.resolve_expression(query, *args, **kwargs)
1105                    for combined_query in clone.combined_queries
1106                ]
1107            )
1108        for key, value in clone.annotations.items():
1109            resolved = value.resolve_expression(query, *args, **kwargs)
1110            if hasattr(resolved, "external_aliases"):
1111                resolved.external_aliases.update(clone.external_aliases)
1112            clone.annotations[key] = resolved
1113        # Outer query's aliases are considered external.
1114        for alias, table in query.alias_map.items():
1115            clone.external_aliases[alias] = (
1116                isinstance(table, Join)
1117                and table.join_field.related_model.model_options.db_table != alias
1118            ) or (
1119                isinstance(table, BaseTable) and table.table_name != table.table_alias
1120            )
1121        return clone
1122
1123    def get_external_cols(self) -> list[Col]:
1124        exprs = chain(self.annotations.values(), self.where.children)
1125        return [
1126            col
1127            for col in self._gen_cols(exprs, include_external=True)
1128            if col.alias in self.external_aliases
1129        ]
1130
1131    def get_group_by_cols(
1132        self, wrapper: BaseExpression | None = None
1133    ) -> list[Col] | list[BaseExpression]:
1134        # If wrapper is referenced by an alias for an explicit GROUP BY through
1135        # values() a reference to this expression and not the self must be
1136        # returned to ensure external column references are not grouped against
1137        # as well.
1138        external_cols = self.get_external_cols()
1139        if any(col.possibly_multivalued for col in external_cols):
1140            return [wrapper or self]
1141        return external_cols
1142
1143    def as_sql(
1144        self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1145    ) -> tuple[str, tuple[Any, ...]]:
1146        # Some backends (e.g. Oracle) raise an error when a subquery contains
1147        # unnecessary ORDER BY clause.
1148        if (
1149            self.subquery
1150            and not db_connection.features.ignores_unnecessary_order_by_in_subqueries
1151        ):
1152            self.clear_ordering(force=False)
1153            for query in self.combined_queries:
1154                query.clear_ordering(force=False)
1155        sql, params = self.get_compiler().as_sql()
1156        if self.subquery:
1157            sql = f"({sql})"
1158        return sql, params
1159
1160    def resolve_lookup_value(
1161        self, value: Any, can_reuse: set[str] | None, allow_joins: bool
1162    ) -> Any:
1163        if hasattr(value, "resolve_expression"):
1164            value = value.resolve_expression(
1165                self,
1166                reuse=can_reuse,
1167                allow_joins=allow_joins,
1168            )
1169        elif isinstance(value, list | tuple):
1170            # The items of the iterable may be expressions and therefore need
1171            # to be resolved independently.
1172            values = (
1173                self.resolve_lookup_value(sub_value, can_reuse, allow_joins)
1174                for sub_value in value
1175            )
1176            type_ = type(value)
1177            if hasattr(type_, "_make"):  # namedtuple
1178                return type_(*values)
1179            return type_(values)
1180        return value
1181
1182    def solve_lookup_type(
1183        self, lookup: str, summarize: bool = False
1184    ) -> tuple[list[str] | tuple[str, ...], tuple[str, ...], BaseExpression | bool]:
1185        """
1186        Solve the lookup type from the lookup (e.g.: 'foobar__id__icontains').
1187        """
1188        lookup_splitted = lookup.split(LOOKUP_SEP)
1189        if self.annotations:
1190            annotation, expression_lookups = refs_expression(
1191                lookup_splitted, self.annotations
1192            )
1193            if annotation:
1194                expression = self.annotations[annotation]
1195                if summarize:
1196                    expression = Ref(annotation, expression)
1197                return expression_lookups, (), expression
1198        _, field, _, lookup_parts = self.names_to_path(
1199            lookup_splitted, self.get_model_meta()
1200        )
1201        field_parts = lookup_splitted[0 : len(lookup_splitted) - len(lookup_parts)]
1202        if len(lookup_parts) > 1 and not field_parts:
1203            raise FieldError(
1204                f'Invalid lookup "{lookup}" for model {self.get_model_meta().model.__name__}".'
1205            )
1206        return lookup_parts, field_parts, False  # type: ignore[return-value]
1207
1208    def check_query_object_type(self, value: Any, meta: Meta, field: Field) -> None:
1209        """
1210        Check whether the object passed while querying is of the correct type.
1211        If not, raise a ValueError specifying the wrong object.
1212        """
1213        if hasattr(value, "_model_meta"):
1214            if not check_rel_lookup_compatibility(value._model_meta.model, meta, field):
1215                raise ValueError(
1216                    f'Cannot query "{value}": Must be "{meta.model.model_options.object_name}" instance.'
1217                )
1218
1219    def check_related_objects(self, field: Field, value: Any, meta: Meta) -> None:
1220        """Check the type of object passed to query relations."""
1221        if field.is_relation:
1222            # Check that the field and the queryset use the same model in a
1223            # query like .filter(author=Author.query.all()). For example, the
1224            # meta would be Author's (from the author field) and value.model
1225            # would be Author.query.all() queryset's .model (Author also).
1226            # The field is the related field on the lhs side.
1227            if (
1228                isinstance(value, Query)
1229                and not value.has_select_fields
1230                and not check_rel_lookup_compatibility(value.model, meta, field)
1231            ):
1232                raise ValueError(
1233                    f'Cannot use QuerySet for "{value.model.model_options.object_name}": Use a QuerySet for "{meta.model.model_options.object_name}".'
1234                )
1235            elif hasattr(value, "_model_meta"):
1236                self.check_query_object_type(value, meta, field)
1237            elif hasattr(value, "__iter__"):
1238                for v in value:
1239                    self.check_query_object_type(v, meta, field)
1240
1241    def check_filterable(self, expression: Any) -> None:
1242        """Raise an error if expression cannot be used in a WHERE clause."""
1243        if hasattr(expression, "resolve_expression") and not getattr(
1244            expression, "filterable", True
1245        ):
1246            raise NotSupportedError(
1247                expression.__class__.__name__ + " is disallowed in the filter clause."
1248            )
1249        if hasattr(expression, "get_source_expressions"):
1250            for expr in expression.get_source_expressions():
1251                self.check_filterable(expr)
1252
1253    def build_lookup(
1254        self, lookups: list[str], lhs: BaseExpression, rhs: Any
1255    ) -> Lookup | None:
1256        """
1257        Try to extract transforms and lookup from given lhs.
1258
1259        The lhs value is something that works like SQLExpression.
1260        The rhs value is what the lookup is going to compare against.
1261        The lookups is a list of names to extract using get_lookup()
1262        and get_transform().
1263        """
1264        # __exact is the default lookup if one isn't given.
1265        *transforms, lookup_name = lookups or ["exact"]
1266        for name in transforms:
1267            lhs = self.try_transform(lhs, name)
1268        # First try get_lookup() so that the lookup takes precedence if the lhs
1269        # supports both transform and lookup for the name.
1270        lookup_class = lhs.get_lookup(lookup_name)
1271        if not lookup_class:
1272            # A lookup wasn't found. Try to interpret the name as a transform
1273            # and do an Exact lookup against it.
1274            lhs = self.try_transform(lhs, lookup_name)
1275            lookup_name = "exact"
1276            lookup_class = lhs.get_lookup(lookup_name)
1277            if not lookup_class:
1278                return
1279
1280        lookup = lookup_class(lhs, rhs)
1281        # Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all
1282        # uses of None as a query value unless the lookup supports it.
1283        if lookup.rhs is None and not lookup.can_use_none_as_rhs:
1284            if lookup_name not in ("exact", "iexact"):
1285                raise ValueError("Cannot use None as a query value")
1286            return lhs.get_lookup("isnull")(lhs, True)  # type: ignore[return-value]
1287
1288        return lookup
1289
1290    def try_transform(self, lhs: BaseExpression, name: str) -> BaseExpression:
1291        """
1292        Helper method for build_lookup(). Try to fetch and initialize
1293        a transform for name parameter from lhs.
1294        """
1295        transform_class = lhs.get_transform(name)
1296        if transform_class:
1297            return transform_class(lhs)
1298        else:
1299            output_field = lhs.output_field.__class__
1300            suggested_lookups = difflib.get_close_matches(
1301                name, output_field.get_lookups()
1302            )
1303            if suggested_lookups:
1304                suggestion = ", perhaps you meant {}?".format(
1305                    " or ".join(suggested_lookups)
1306                )
1307            else:
1308                suggestion = "."
1309            raise FieldError(
1310                f"Unsupported lookup '{name}' for {output_field.__name__} or join on the field not "
1311                f"permitted{suggestion}"
1312            )
1313
1314    def build_filter(
1315        self,
1316        filter_expr: tuple[str, Any] | Q | BaseExpression,
1317        branch_negated: bool = False,
1318        current_negated: bool = False,
1319        can_reuse: set[str] | None = None,
1320        allow_joins: bool = True,
1321        split_subq: bool = True,
1322        reuse_with_filtered_relation: bool = False,
1323        check_filterable: bool = True,
1324        summarize: bool = False,
1325    ) -> tuple[WhereNode, set[str] | tuple[()]]:
1326        """
1327        Build a WhereNode for a single filter clause but don't add it
1328        to this Query. Query.add_q() will then add this filter to the where
1329        Node.
1330
1331        The 'branch_negated' tells us if the current branch contains any
1332        negations. This will be used to determine if subqueries are needed.
1333
1334        The 'current_negated' is used to determine if the current filter is
1335        negated or not and this will be used to determine if IS NULL filtering
1336        is needed.
1337
1338        The difference between current_negated and branch_negated is that
1339        branch_negated is set on first negation, but current_negated is
1340        flipped for each negation.
1341
1342        Note that add_filter will not do any negating itself, that is done
1343        upper in the code by add_q().
1344
1345        The 'can_reuse' is a set of reusable joins for multijoins.
1346
1347        If 'reuse_with_filtered_relation' is True, then only joins in can_reuse
1348        will be reused.
1349
1350        The method will create a filter clause that can be added to the current
1351        query. However, if the filter isn't added to the query then the caller
1352        is responsible for unreffing the joins used.
1353        """
1354        if isinstance(filter_expr, dict):
1355            raise FieldError("Cannot parse keyword query as dict")
1356        if isinstance(filter_expr, Q):
1357            return self._add_q(
1358                filter_expr,
1359                branch_negated=branch_negated,
1360                current_negated=current_negated,
1361                used_aliases=can_reuse,
1362                allow_joins=allow_joins,
1363                split_subq=split_subq,
1364                check_filterable=check_filterable,
1365                summarize=summarize,
1366            )
1367        if hasattr(filter_expr, "resolve_expression"):
1368            if not getattr(filter_expr, "conditional", False):
1369                raise TypeError("Cannot filter against a non-conditional expression.")
1370            condition = filter_expr.resolve_expression(
1371                self, allow_joins=allow_joins, summarize=summarize
1372            )  # type: ignore[attr-defined]
1373            if not isinstance(condition, Lookup):
1374                condition = self.build_lookup(["exact"], condition, True)
1375            return WhereNode([condition], connector=AND), []  # type: ignore[return-value]
1376        arg, value = filter_expr
1377        if not arg:
1378            raise FieldError(f"Cannot parse keyword query {arg!r}")
1379        lookups, parts, reffed_expression = self.solve_lookup_type(arg, summarize)
1380
1381        if check_filterable:
1382            self.check_filterable(reffed_expression)
1383
1384        if not allow_joins and len(parts) > 1:
1385            raise FieldError("Joined field references are not permitted in this query")
1386
1387        pre_joins = self.alias_refcount.copy()
1388        value = self.resolve_lookup_value(value, can_reuse, allow_joins)
1389        used_joins = {
1390            k for k, v in self.alias_refcount.items() if v > pre_joins.get(k, 0)
1391        }
1392
1393        if check_filterable:
1394            self.check_filterable(value)
1395
1396        if reffed_expression:
1397            condition = self.build_lookup(lookups, reffed_expression, value)
1398            return WhereNode([condition], connector=AND), []  # type: ignore[return-value]
1399
1400        meta = self.get_model_meta()
1401        alias = self.get_initial_alias()
1402        allow_many = not branch_negated or not split_subq
1403
1404        try:
1405            join_info = self.setup_joins(
1406                parts,
1407                meta,
1408                alias,
1409                can_reuse=can_reuse,
1410                allow_many=allow_many,
1411                reuse_with_filtered_relation=reuse_with_filtered_relation,
1412            )
1413
1414            # Prevent iterator from being consumed by check_related_objects()
1415            if isinstance(value, Iterator):
1416                value = list(value)
1417            self.check_related_objects(join_info.final_field, value, join_info.meta)
1418
1419            # split_exclude() needs to know which joins were generated for the
1420            # lookup parts
1421            self._lookup_joins = join_info.joins
1422        except MultiJoin as e:
1423            return self.split_exclude(filter_expr, can_reuse, e.names_with_path)
1424
1425        # Update used_joins before trimming since they are reused to determine
1426        # which joins could be later promoted to INNER.
1427        used_joins.update(join_info.joins)
1428        targets, alias, join_list = self.trim_joins(
1429            join_info.targets, join_info.joins, join_info.path
1430        )
1431        if can_reuse is not None:
1432            can_reuse.update(join_list)
1433
1434        if join_info.final_field.is_relation:
1435            if len(targets) == 1:
1436                col = self._get_col(targets[0], join_info.final_field, alias)
1437            else:
1438                col = MultiColSource(
1439                    alias, targets, join_info.targets, join_info.final_field
1440                )
1441        else:
1442            col = self._get_col(targets[0], join_info.final_field, alias)
1443
1444        condition = self.build_lookup(lookups, col, value)
1445        lookup_type = condition.lookup_name
1446        clause = WhereNode([condition], connector=AND)
1447
1448        require_outer = (
1449            lookup_type == "isnull" and condition.rhs is True and not current_negated
1450        )
1451        if (
1452            current_negated
1453            and (lookup_type != "isnull" or condition.rhs is False)
1454            and condition.rhs is not None
1455        ):
1456            require_outer = True
1457            if lookup_type != "isnull":
1458                # The condition added here will be SQL like this:
1459                # NOT (col IS NOT NULL), where the first NOT is added in
1460                # upper layers of code. The reason for addition is that if col
1461                # is null, then col != someval will result in SQL "unknown"
1462                # which isn't the same as in Python. The Python None handling
1463                # is wanted, and it can be gotten by
1464                # (col IS NULL OR col != someval)
1465                #   <=>
1466                # NOT (col IS NOT NULL AND col = someval).
1467                if (
1468                    self.is_nullable(targets[0])
1469                    or self.alias_map[join_list[-1]].join_type == LOUTER
1470                ):
1471                    lookup_class = targets[0].get_lookup("isnull")
1472                    col = self._get_col(targets[0], join_info.targets[0], alias)
1473                    clause.add(lookup_class(col, False), AND)
1474                # If someval is a nullable column, someval IS NOT NULL is
1475                # added.
1476                if isinstance(value, Col) and self.is_nullable(value.target):
1477                    lookup_class = value.target.get_lookup("isnull")
1478                    clause.add(lookup_class(value, False), AND)
1479        return clause, used_joins if not require_outer else ()
1480
1481    def add_filter(self, filter_lhs: str, filter_rhs: Any) -> None:
1482        self.add_q(Q((filter_lhs, filter_rhs)))
1483
1484    def add_q(self, q_object: Q) -> None:  # type: ignore[unsupported-operator]
1485        """
1486        A preprocessor for the internal _add_q(). Responsible for doing final
1487        join promotion.
1488        """
1489        # For join promotion this case is doing an AND for the added q_object
1490        # and existing conditions. So, any existing inner join forces the join
1491        # type to remain inner. Existing outer joins can however be demoted.
1492        # (Consider case where rel_a is LOUTER and rel_a__col=1 is added - if
1493        # rel_a doesn't produce any rows, then the whole condition must fail.
1494        # So, demotion is OK.
1495        existing_inner = {
1496            a for a in self.alias_map if self.alias_map[a].join_type == INNER
1497        }
1498        clause, _ = self._add_q(q_object, self.used_aliases)
1499        if clause:
1500            self.where.add(clause, AND)
1501        self.demote_joins(existing_inner)
1502
1503    def build_where(self, filter_expr: tuple[str, Any]) -> WhereNode:
1504        return self.build_filter(filter_expr, allow_joins=False)[0]
1505
1506    def clear_where(self) -> None:
1507        self.where = WhereNode()
1508
1509    def _add_q(
1510        self,
1511        q_object: Q,
1512        used_aliases: set[str] | None,
1513        branch_negated: bool = False,
1514        current_negated: bool = False,
1515        allow_joins: bool = True,
1516        split_subq: bool = True,
1517        check_filterable: bool = True,
1518        summarize: bool = False,
1519    ) -> tuple[WhereNode, set[str] | tuple[()]]:  # type: ignore[unsupported-operator]
1520        """Add a Q-object to the current filter."""
1521        connector = q_object.connector
1522        current_negated ^= q_object.negated
1523        branch_negated = branch_negated or q_object.negated
1524        target_clause = WhereNode(connector=connector, negated=q_object.negated)
1525        joinpromoter = JoinPromoter(
1526            q_object.connector, len(q_object.children), current_negated
1527        )
1528        for child in q_object.children:
1529            child_clause, needed_inner = self.build_filter(
1530                child,
1531                can_reuse=used_aliases,
1532                branch_negated=branch_negated,
1533                current_negated=current_negated,
1534                allow_joins=allow_joins,
1535                split_subq=split_subq,
1536                check_filterable=check_filterable,
1537                summarize=summarize,
1538            )
1539            joinpromoter.add_votes(needed_inner)
1540            if child_clause:
1541                target_clause.add(child_clause, connector)
1542        needed_inner = joinpromoter.update_join_types(self)
1543        return target_clause, needed_inner
1544
1545    def build_filtered_relation_q(
1546        self,
1547        q_object: Q,
1548        reuse: set[str],
1549        branch_negated: bool = False,
1550        current_negated: bool = False,
1551    ) -> WhereNode:  # type: ignore[unsupported-operator]
1552        """Add a FilteredRelation object to the current filter."""
1553        connector = q_object.connector
1554        current_negated ^= q_object.negated
1555        branch_negated = branch_negated or q_object.negated
1556        target_clause = WhereNode(connector=connector, negated=q_object.negated)
1557        for child in q_object.children:
1558            if isinstance(child, Node):
1559                child_clause = self.build_filtered_relation_q(
1560                    child,
1561                    reuse=reuse,
1562                    branch_negated=branch_negated,
1563                    current_negated=current_negated,
1564                )
1565            else:
1566                child_clause, _ = self.build_filter(
1567                    child,
1568                    can_reuse=reuse,
1569                    branch_negated=branch_negated,
1570                    current_negated=current_negated,
1571                    allow_joins=True,
1572                    split_subq=False,
1573                    reuse_with_filtered_relation=True,
1574                )
1575            target_clause.add(child_clause, connector)
1576        return target_clause
1577
1578    def add_filtered_relation(self, filtered_relation: Any, alias: str) -> None:
1579        filtered_relation.alias = alias
1580        lookups = dict(get_children_from_q(filtered_relation.condition))
1581        relation_lookup_parts, relation_field_parts, _ = self.solve_lookup_type(
1582            filtered_relation.relation_name
1583        )
1584        if relation_lookup_parts:
1585            raise ValueError(
1586                "FilteredRelation's relation_name cannot contain lookups "
1587                f"(got {filtered_relation.relation_name!r})."
1588            )
1589        for lookup in chain(lookups):
1590            lookup_parts, lookup_field_parts, _ = self.solve_lookup_type(lookup)
1591            shift = 2 if not lookup_parts else 1
1592            lookup_field_path = lookup_field_parts[:-shift]
1593            for idx, lookup_field_part in enumerate(lookup_field_path):
1594                if len(relation_field_parts) > idx:
1595                    if relation_field_parts[idx] != lookup_field_part:
1596                        raise ValueError(
1597                            "FilteredRelation's condition doesn't support "
1598                            f"relations outside the {filtered_relation.relation_name!r} (got {lookup!r})."
1599                        )
1600                else:
1601                    raise ValueError(
1602                        "FilteredRelation's condition doesn't support nested "
1603                        f"relations deeper than the relation_name (got {lookup!r} for "
1604                        f"{filtered_relation.relation_name!r})."
1605                    )
1606        self._filtered_relations[filtered_relation.alias] = filtered_relation
1607
1608    def names_to_path(
1609        self,
1610        names: list[str],
1611        meta: Meta,
1612        allow_many: bool = True,
1613        fail_on_missing: bool = False,
1614    ) -> tuple[list[Any], Field, tuple[Field, ...], list[str]]:
1615        """
1616        Walk the list of names and turns them into PathInfo tuples. A single
1617        name in 'names' can generate multiple PathInfos (m2m, for example).
1618
1619        'names' is the path of names to travel, 'meta' is the Meta we
1620        start the name resolving from, 'allow_many' is as for setup_joins().
1621        If fail_on_missing is set to True, then a name that can't be resolved
1622        will generate a FieldError.
1623
1624        Return a list of PathInfo tuples. In addition return the final field
1625        (the last used join field) and target (which is a field guaranteed to
1626        contain the same value as the final field). Finally, return those names
1627        that weren't found (which are likely transforms and the final lookup).
1628        """
1629        path, names_with_path = [], []
1630        for pos, name in enumerate(names):
1631            cur_names_with_path = (name, [])
1632
1633            field = None
1634            filtered_relation = None
1635            try:
1636                if meta is None:
1637                    raise FieldDoesNotExist
1638                field = meta.get_field(name)
1639            except FieldDoesNotExist:
1640                if name in self.annotation_select:
1641                    field = self.annotation_select[name].output_field
1642                elif name in self._filtered_relations and pos == 0:
1643                    filtered_relation = self._filtered_relations[name]
1644                    if LOOKUP_SEP in filtered_relation.relation_name:
1645                        parts = filtered_relation.relation_name.split(LOOKUP_SEP)
1646                        filtered_relation_path, field, _, _ = self.names_to_path(
1647                            parts,
1648                            meta,
1649                            allow_many,
1650                            fail_on_missing,
1651                        )
1652                        path.extend(filtered_relation_path[:-1])
1653                    else:
1654                        field = meta.get_field(filtered_relation.relation_name)  # type: ignore[attr-defined]
1655            if field is not None:
1656                # Fields that contain one-to-many relations with a generic
1657                # model (like a GenericForeignKey) cannot generate reverse
1658                # relations and therefore cannot be used for reverse querying.
1659                if field.is_relation and not field.related_model:
1660                    raise FieldError(
1661                        f"Field {name!r} does not generate an automatic reverse "
1662                        "relation and therefore cannot be used for reverse "
1663                        "querying. If it is a GenericForeignKey, consider "
1664                        "adding a GenericRelation."
1665                    )
1666            else:
1667                # We didn't find the current field, so move position back
1668                # one step.
1669                pos -= 1
1670                if pos == -1 or fail_on_missing:
1671                    available = sorted(
1672                        [
1673                            *get_field_names_from_opts(meta),
1674                            *self.annotation_select,
1675                            *self._filtered_relations,
1676                        ]
1677                    )
1678                    raise FieldError(
1679                        "Cannot resolve keyword '{}' into field. "
1680                        "Choices are: {}".format(name, ", ".join(available))
1681                    )
1682                break
1683
1684            if hasattr(field, "path_infos"):
1685                if filtered_relation:
1686                    pathinfos = field.get_path_info(filtered_relation)
1687                else:
1688                    pathinfos = field.path_infos
1689                if not allow_many:
1690                    for inner_pos, p in enumerate(pathinfos):
1691                        if p.m2m:
1692                            cur_names_with_path[1].extend(pathinfos[0 : inner_pos + 1])
1693                            names_with_path.append(cur_names_with_path)
1694                            raise MultiJoin(pos + 1, names_with_path)
1695                last = pathinfos[-1]
1696                path.extend(pathinfos)
1697                final_field = last.join_field
1698                meta = last.to_meta
1699                targets = last.target_fields
1700                cur_names_with_path[1].extend(pathinfos)
1701                names_with_path.append(cur_names_with_path)
1702            else:
1703                # Local non-relational field.
1704                final_field = field
1705                targets = (field,)
1706                if fail_on_missing and pos + 1 != len(names):
1707                    raise FieldError(
1708                        f"Cannot resolve keyword {names[pos + 1]!r} into field. Join on '{name}'"
1709                        " not permitted."
1710                    )
1711                break
1712        return path, final_field, targets, names[pos + 1 :]
1713
1714    def setup_joins(
1715        self,
1716        names: list[str],
1717        meta: Meta,
1718        alias: str,
1719        can_reuse: set[str] | None = None,
1720        allow_many: bool = True,
1721        reuse_with_filtered_relation: bool = False,
1722    ) -> JoinInfo:
1723        """
1724        Compute the necessary table joins for the passage through the fields
1725        given in 'names'. 'meta' is the Meta for the current model
1726        (which gives the table we are starting from), 'alias' is the alias for
1727        the table to start the joining from.
1728
1729        The 'can_reuse' defines the reverse foreign key joins we can reuse. It
1730        can be None in which case all joins are reusable or a set of aliases
1731        that can be reused. Note that non-reverse foreign keys are always
1732        reusable when using setup_joins().
1733
1734        The 'reuse_with_filtered_relation' can be used to force 'can_reuse'
1735        parameter and force the relation on the given connections.
1736
1737        If 'allow_many' is False, then any reverse foreign key seen will
1738        generate a MultiJoin exception.
1739
1740        Return the final field involved in the joins, the target field (used
1741        for any 'where' constraint), the final 'opts' value, the joins, the
1742        field path traveled to generate the joins, and a transform function
1743        that takes a field and alias and is equivalent to `field.get_col(alias)`
1744        in the simple case but wraps field transforms if they were included in
1745        names.
1746
1747        The target field is the field containing the concrete value. Final
1748        field can be something different, for example foreign key pointing to
1749        that value. Final field is needed for example in some value
1750        conversions (convert 'obj' in fk__id=obj to pk val using the foreign
1751        key field for example).
1752        """
1753        joins = [alias]
1754        # The transform can't be applied yet, as joins must be trimmed later.
1755        # To avoid making every caller of this method look up transforms
1756        # directly, compute transforms here and create a partial that converts
1757        # fields to the appropriate wrapped version.
1758
1759        def final_transformer(field: Field, alias: str | None) -> Col:
1760            if not self.alias_cols:
1761                alias = None
1762            return field.get_col(alias)  # type: ignore[arg-type]
1763
1764        # Try resolving all the names as fields first. If there's an error,
1765        # treat trailing names as lookups until a field can be resolved.
1766        last_field_exception = None
1767        for pivot in range(len(names), 0, -1):
1768            try:
1769                path, final_field, targets, rest = self.names_to_path(
1770                    names[:pivot],
1771                    meta,
1772                    allow_many,
1773                    fail_on_missing=True,
1774                )
1775            except FieldError as exc:
1776                if pivot == 1:
1777                    # The first item cannot be a lookup, so it's safe
1778                    # to raise the field error here.
1779                    raise
1780                else:
1781                    last_field_exception = exc
1782            else:
1783                # The transforms are the remaining items that couldn't be
1784                # resolved into fields.
1785                transforms = names[pivot:]
1786                break
1787        for name in transforms:
1788
1789            def transform(
1790                field: Field, alias: str | None, *, name: str, previous: Any
1791            ) -> BaseExpression:
1792                try:
1793                    wrapped = previous(field, alias)
1794                    return self.try_transform(wrapped, name)
1795                except FieldError:
1796                    # FieldError is raised if the transform doesn't exist.
1797                    if isinstance(final_field, Field) and last_field_exception:
1798                        raise last_field_exception
1799                    else:
1800                        raise
1801
1802            final_transformer = functools.partial(  # type: ignore[misc]
1803                transform, name=name, previous=final_transformer
1804            )
1805            final_transformer.has_transforms = True  # type: ignore[attr-defined]
1806        # Then, add the path to the query's joins. Note that we can't trim
1807        # joins at this stage - we will need the information about join type
1808        # of the trimmed joins.
1809        for join in path:
1810            if join.filtered_relation:
1811                filtered_relation = join.filtered_relation.clone()
1812                table_alias = filtered_relation.alias
1813            else:
1814                filtered_relation = None
1815                table_alias = None
1816            meta = join.to_meta
1817            if join.direct:
1818                nullable = self.is_nullable(join.join_field)
1819            else:
1820                nullable = True
1821            connection = self.join_class(
1822                meta.model.model_options.db_table,
1823                alias,
1824                table_alias,
1825                INNER,
1826                join.join_field,
1827                nullable,
1828                filtered_relation=filtered_relation,
1829            )
1830            reuse = can_reuse if join.m2m or reuse_with_filtered_relation else None
1831            alias = self.join(
1832                connection,
1833                reuse=reuse,
1834                reuse_with_filtered_relation=reuse_with_filtered_relation,
1835            )
1836            joins.append(alias)
1837            if filtered_relation:
1838                filtered_relation.path = joins[:]
1839        return JoinInfo(final_field, targets, meta, joins, path, final_transformer)
1840
1841    def trim_joins(
1842        self, targets: tuple[Field, ...], joins: list[str], path: list[Any]
1843    ) -> tuple[tuple[Field, ...], str, list[str]]:
1844        """
1845        The 'target' parameter is the final field being joined to, 'joins'
1846        is the full list of join aliases. The 'path' contain the PathInfos
1847        used to create the joins.
1848
1849        Return the final target field and table alias and the new active
1850        joins.
1851
1852        Always trim any direct join if the target column is already in the
1853        previous table. Can't trim reverse joins as it's unknown if there's
1854        anything on the other side of the join.
1855        """
1856        joins = joins[:]
1857        for pos, info in enumerate(reversed(path)):
1858            if len(joins) == 1 or not info.direct:
1859                break
1860            if info.filtered_relation:
1861                break
1862            join_targets = {t.column for t in info.join_field.foreign_related_fields}
1863            cur_targets = {t.column for t in targets}
1864            if not cur_targets.issubset(join_targets):
1865                break
1866            targets_dict = {
1867                r[1].column: r[0]
1868                for r in info.join_field.related_fields
1869                if r[1].column in cur_targets
1870            }
1871            targets = tuple(targets_dict[t.column] for t in targets)
1872            self.unref_alias(joins.pop())
1873        return targets, joins[-1], joins
1874
1875    @classmethod
1876    def _gen_cols(
1877        cls,
1878        exprs: TypingIterator[Any],
1879        include_external: bool = False,
1880        resolve_refs: bool = True,
1881    ) -> TypingIterator[Col]:
1882        for expr in exprs:
1883            if isinstance(expr, Col):
1884                yield expr
1885            elif include_external and callable(
1886                getattr(expr, "get_external_cols", None)
1887            ):
1888                yield from expr.get_external_cols()
1889            elif hasattr(expr, "get_source_expressions"):
1890                if not resolve_refs and isinstance(expr, Ref):
1891                    continue
1892                yield from cls._gen_cols(
1893                    expr.get_source_expressions(),
1894                    include_external=include_external,
1895                    resolve_refs=resolve_refs,
1896                )
1897
1898    @classmethod
1899    def _gen_col_aliases(cls, exprs: TypingIterator[Any]) -> TypingIterator[str]:
1900        yield from (expr.alias for expr in cls._gen_cols(exprs))
1901
1902    def resolve_ref(
1903        self,
1904        name: str,
1905        allow_joins: bool = True,
1906        reuse: set[str] | None = None,
1907        summarize: bool = False,
1908    ) -> BaseExpression:
1909        annotation = self.annotations.get(name)
1910        if annotation is not None:
1911            if not allow_joins:
1912                for alias in self._gen_col_aliases([annotation]):
1913                    if isinstance(self.alias_map[alias], Join):
1914                        raise FieldError(
1915                            "Joined field references are not permitted in this query"
1916                        )
1917            if summarize:
1918                # Summarize currently means we are doing an aggregate() query
1919                # which is executed as a wrapped subquery if any of the
1920                # aggregate() elements reference an existing annotation. In
1921                # that case we need to return a Ref to the subquery's annotation.
1922                if name not in self.annotation_select:
1923                    raise FieldError(
1924                        f"Cannot aggregate over the '{name}' alias. Use annotate() "
1925                        "to promote it."
1926                    )
1927                return Ref(name, self.annotation_select[name])
1928            else:
1929                return annotation
1930        else:
1931            field_list = name.split(LOOKUP_SEP)
1932            annotation = self.annotations.get(field_list[0])
1933            if annotation is not None:
1934                for transform in field_list[1:]:
1935                    annotation = self.try_transform(annotation, transform)
1936                return annotation
1937            join_info = self.setup_joins(
1938                field_list,
1939                self.get_model_meta(),
1940                self.get_initial_alias(),
1941                can_reuse=reuse,
1942            )
1943            targets, final_alias, join_list = self.trim_joins(
1944                join_info.targets, join_info.joins, join_info.path
1945            )
1946            if not allow_joins and len(join_list) > 1:
1947                raise FieldError(
1948                    "Joined field references are not permitted in this query"
1949                )
1950            if len(targets) > 1:
1951                raise FieldError(
1952                    "Referencing multicolumn fields with F() objects isn't supported"
1953                )
1954            # Verify that the last lookup in name is a field or a transform:
1955            # transform_function() raises FieldError if not.
1956            transform = join_info.transform_function(targets[0], final_alias)
1957            if reuse is not None:
1958                reuse.update(join_list)
1959            return transform
1960
1961    def split_exclude(
1962        self,
1963        filter_expr: tuple[str, Any],
1964        can_reuse: set[str],
1965        names_with_path: list[tuple[str, list[Any]]],
1966    ) -> tuple[WhereNode, set[str] | tuple[()]]:
1967        """
1968        When doing an exclude against any kind of N-to-many relation, we need
1969        to use a subquery. This method constructs the nested query, given the
1970        original exclude filter (filter_expr) and the portion up to the first
1971        N-to-many relation field.
1972
1973        For example, if the origin filter is ~Q(child__name='foo'), filter_expr
1974        is ('child__name', 'foo') and can_reuse is a set of joins usable for
1975        filters in the original query.
1976
1977        We will turn this into equivalent of:
1978            WHERE NOT EXISTS(
1979                SELECT 1
1980                FROM child
1981                WHERE name = 'foo' AND child.parent_id = parent.id
1982                LIMIT 1
1983            )
1984        """
1985        # Generate the inner query.
1986        query = self.__class__(self.model)
1987        query._filtered_relations = self._filtered_relations
1988        filter_lhs, filter_rhs = filter_expr
1989        if isinstance(filter_rhs, OuterRef):
1990            filter_rhs = OuterRef(filter_rhs)
1991        elif isinstance(filter_rhs, F):
1992            filter_rhs = OuterRef(filter_rhs.name)
1993        query.add_filter(filter_lhs, filter_rhs)
1994        query.clear_ordering(force=True)
1995        # Try to have as simple as possible subquery -> trim leading joins from
1996        # the subquery.
1997        trimmed_prefix, contains_louter = query.trim_start(names_with_path)
1998
1999        col = query.select[0]
2000        select_field = col.target
2001        alias = col.alias
2002        if alias in can_reuse:
2003            id_field = select_field.model._model_meta.get_field("id")
2004            # Need to add a restriction so that outer query's filters are in effect for
2005            # the subquery, too.
2006            query.bump_prefix(self)
2007            lookup_class = select_field.get_lookup("exact")
2008            # Note that the query.select[0].alias is different from alias
2009            # due to bump_prefix above.
2010            lookup = lookup_class(
2011                id_field.get_col(query.select[0].alias), id_field.get_col(alias)
2012            )
2013            query.where.add(lookup, AND)
2014            query.external_aliases[alias] = True
2015
2016        lookup_class = select_field.get_lookup("exact")
2017        lookup = lookup_class(col, ResolvedOuterRef(trimmed_prefix))
2018        query.where.add(lookup, AND)
2019        condition, needed_inner = self.build_filter(Exists(query))
2020
2021        if contains_louter:
2022            or_null_condition, _ = self.build_filter(
2023                (f"{trimmed_prefix}__isnull", True),
2024                current_negated=True,
2025                branch_negated=True,
2026                can_reuse=can_reuse,
2027            )
2028            condition.add(or_null_condition, OR)
2029            # Note that the end result will be:
2030            # (outercol NOT IN innerq AND outercol IS NOT NULL) OR outercol IS NULL.
2031            # This might look crazy but due to how IN works, this seems to be
2032            # correct. If the IS NOT NULL check is removed then outercol NOT
2033            # IN will return UNKNOWN. If the IS NULL check is removed, then if
2034            # outercol IS NULL we will not match the row.
2035        return condition, needed_inner
2036
2037    def set_empty(self) -> None:
2038        self.where.add(NothingNode(), AND)
2039        for query in self.combined_queries:
2040            query.set_empty()
2041
2042    def is_empty(self) -> bool:
2043        return any(isinstance(c, NothingNode) for c in self.where.children)
2044
2045    def set_limits(self, low: int | None = None, high: int | None = None) -> None:
2046        """
2047        Adjust the limits on the rows retrieved. Use low/high to set these,
2048        as it makes it more Pythonic to read and write. When the SQL query is
2049        created, convert them to the appropriate offset and limit values.
2050
2051        Apply any limits passed in here to the existing constraints. Add low
2052        to the current low value and clamp both to any existing high value.
2053        """
2054        if high is not None:
2055            if self.high_mark is not None:
2056                self.high_mark = min(self.high_mark, self.low_mark + high)
2057            else:
2058                self.high_mark = self.low_mark + high
2059        if low is not None:
2060            if self.high_mark is not None:
2061                self.low_mark = min(self.high_mark, self.low_mark + low)
2062            else:
2063                self.low_mark = self.low_mark + low
2064
2065        if self.low_mark == self.high_mark:
2066            self.set_empty()
2067
2068    def clear_limits(self) -> None:
2069        """Clear any existing limits."""
2070        self.low_mark, self.high_mark = 0, None
2071
2072    @property
2073    def is_sliced(self) -> bool:
2074        return self.low_mark != 0 or self.high_mark is not None
2075
2076    def has_limit_one(self) -> bool:
2077        return self.high_mark is not None and (self.high_mark - self.low_mark) == 1
2078
2079    def can_filter(self) -> bool:
2080        """
2081        Return True if adding filters to this instance is still possible.
2082
2083        Typically, this means no limits or offsets have been put on the results.
2084        """
2085        return not self.is_sliced
2086
2087    def clear_select_clause(self) -> None:
2088        """Remove all fields from SELECT clause."""
2089        self.select = ()
2090        self.default_cols = False
2091        self.select_related = False
2092        self.set_extra_mask(())
2093        self.set_annotation_mask(())
2094
2095    def clear_select_fields(self) -> None:
2096        """
2097        Clear the list of fields to select (but not extra_select columns).
2098        Some queryset types completely replace any existing list of select
2099        columns.
2100        """
2101        self.select = ()
2102        self.values_select = ()
2103
2104    def add_select_col(self, col: Col, name: str) -> None:
2105        self.select += (col,)
2106        self.values_select += (name,)
2107
2108    def set_select(self, cols: list[Col] | tuple[Col, ...]) -> None:
2109        self.default_cols = False
2110        self.select = tuple(cols)
2111
2112    def add_distinct_fields(self, *field_names: str) -> None:
2113        """
2114        Add and resolve the given fields to the query's "distinct on" clause.
2115        """
2116        self.distinct_fields = field_names
2117        self.distinct = True
2118
2119    def add_fields(
2120        self, field_names: list[str] | TypingIterator[str], allow_m2m: bool = True
2121    ) -> None:
2122        """
2123        Add the given (model) fields to the select set. Add the field names in
2124        the order specified.
2125        """
2126        alias = self.get_initial_alias()
2127        meta = self.get_model_meta()
2128
2129        try:
2130            cols = []
2131            for name in field_names:
2132                # Join promotion note - we must not remove any rows here, so
2133                # if there is no existing joins, use outer join.
2134                join_info = self.setup_joins(
2135                    name.split(LOOKUP_SEP), meta, alias, allow_many=allow_m2m
2136                )
2137                targets, final_alias, joins = self.trim_joins(
2138                    join_info.targets,
2139                    join_info.joins,
2140                    join_info.path,
2141                )
2142                for target in targets:
2143                    cols.append(join_info.transform_function(target, final_alias))
2144            if cols:
2145                self.set_select(cols)
2146        except MultiJoin:
2147            raise FieldError(f"Invalid field name: '{name}'")
2148        except FieldError:
2149            if LOOKUP_SEP in name:
2150                # For lookups spanning over relationships, show the error
2151                # from the model on which the lookup failed.
2152                raise
2153            elif name in self.annotations:
2154                raise FieldError(
2155                    f"Cannot select the '{name}' alias. Use annotate() to promote it."
2156                )
2157            else:
2158                names = sorted(
2159                    [
2160                        *get_field_names_from_opts(meta),
2161                        *self.extra,
2162                        *self.annotation_select,
2163                        *self._filtered_relations,
2164                    ]
2165                )
2166                raise FieldError(
2167                    "Cannot resolve keyword {!r} into field. Choices are: {}".format(
2168                        name, ", ".join(names)
2169                    )
2170                )
2171
2172    def add_ordering(self, *ordering: str | BaseExpression) -> None:
2173        """
2174        Add items from the 'ordering' sequence to the query's "order by"
2175        clause. These items are either field names (not column names) --
2176        possibly with a direction prefix ('-' or '?') -- or OrderBy
2177        expressions.
2178
2179        If 'ordering' is empty, clear all ordering from the query.
2180        """
2181        errors = []
2182        for item in ordering:
2183            if isinstance(item, str):
2184                if item == "?":
2185                    continue
2186                item = item.removeprefix("-")
2187                if item in self.annotations:
2188                    continue
2189                if self.extra and item in self.extra:
2190                    continue
2191                # names_to_path() validates the lookup. A descriptive
2192                # FieldError will be raise if it's not.
2193                self.names_to_path(item.split(LOOKUP_SEP), self.model._model_meta)
2194            elif not hasattr(item, "resolve_expression"):
2195                errors.append(item)
2196            if getattr(item, "contains_aggregate", False):
2197                raise FieldError(
2198                    "Using an aggregate in order_by() without also including "
2199                    f"it in annotate() is not allowed: {item}"
2200                )
2201        if errors:
2202            raise FieldError(f"Invalid order_by arguments: {errors}")
2203        if ordering:
2204            self.order_by += ordering
2205        else:
2206            self.default_ordering = False
2207
2208    def clear_ordering(self, force: bool = False, clear_default: bool = True) -> None:
2209        """
2210        Remove any ordering settings if the current query allows it without
2211        side effects, set 'force' to True to clear the ordering regardless.
2212        If 'clear_default' is True, there will be no ordering in the resulting
2213        query (not even the model's default).
2214        """
2215        if not force and (
2216            self.is_sliced or self.distinct_fields or self.select_for_update
2217        ):
2218            return
2219        self.order_by = ()
2220        self.extra_order_by = ()
2221        if clear_default:
2222            self.default_ordering = False
2223
2224    def set_group_by(self, allow_aliases: bool = True) -> None:
2225        """
2226        Expand the GROUP BY clause required by the query.
2227
2228        This will usually be the set of all non-aggregate fields in the
2229        return data. If the database backend supports grouping by the
2230        primary key, and the query would be equivalent, the optimization
2231        will be made automatically.
2232        """
2233        if allow_aliases and self.values_select:
2234            # If grouping by aliases is allowed assign selected value aliases
2235            # by moving them to annotations.
2236            group_by_annotations = {}
2237            values_select = {}
2238            for alias, expr in zip(self.values_select, self.select):
2239                if isinstance(expr, Col):
2240                    values_select[alias] = expr
2241                else:
2242                    group_by_annotations[alias] = expr
2243            self.annotations = {**group_by_annotations, **self.annotations}
2244            self.append_annotation_mask(group_by_annotations)
2245            self.select = tuple(values_select.values())
2246            self.values_select = tuple(values_select)
2247        group_by = list(self.select)
2248        for alias, annotation in self.annotation_select.items():
2249            if not (group_by_cols := annotation.get_group_by_cols()):
2250                continue
2251            if allow_aliases and not annotation.contains_aggregate:
2252                group_by.append(Ref(alias, annotation))
2253            else:
2254                group_by.extend(group_by_cols)
2255        self.group_by = tuple(group_by)
2256
2257    def add_select_related(self, fields: list[str]) -> None:
2258        """
2259        Set up the select_related data structure so that we only select
2260        certain related models (as opposed to all models, when
2261        self.select_related=True).
2262        """
2263        if isinstance(self.select_related, bool):
2264            field_dict = {}
2265        else:
2266            field_dict = self.select_related
2267        for field in fields:
2268            d = field_dict
2269            for part in field.split(LOOKUP_SEP):
2270                d = d.setdefault(part, {})
2271        self.select_related = field_dict
2272
2273    def add_extra(
2274        self,
2275        select: dict[str, str],
2276        select_params: list[Any] | None,
2277        where: list[str],
2278        params: list[Any],
2279        tables: list[str],
2280        order_by: tuple[str, ...],
2281    ) -> None:
2282        """
2283        Add data to the various extra_* attributes for user-created additions
2284        to the query.
2285        """
2286        if select:
2287            # We need to pair any placeholder markers in the 'select'
2288            # dictionary with their parameters in 'select_params' so that
2289            # subsequent updates to the select dictionary also adjust the
2290            # parameters appropriately.
2291            select_pairs = {}
2292            if select_params:
2293                param_iter = iter(select_params)
2294            else:
2295                param_iter = iter([])
2296            for name, entry in select.items():
2297                self.check_alias(name)
2298                entry = str(entry)
2299                entry_params = []
2300                pos = entry.find("%s")
2301                while pos != -1:
2302                    if pos == 0 or entry[pos - 1] != "%":
2303                        entry_params.append(next(param_iter))
2304                    pos = entry.find("%s", pos + 2)
2305                select_pairs[name] = (entry, entry_params)
2306            self.extra.update(select_pairs)
2307        if where or params:
2308            self.where.add(ExtraWhere(where, params), AND)
2309        if tables:
2310            self.extra_tables += tuple(tables)
2311        if order_by:
2312            self.extra_order_by = order_by
2313
2314    def clear_deferred_loading(self) -> None:
2315        """Remove any fields from the deferred loading set."""
2316        self.deferred_loading = (frozenset(), True)
2317
2318    def add_deferred_loading(self, field_names: frozenset[str]) -> None:
2319        """
2320        Add the given list of model field names to the set of fields to
2321        exclude from loading from the database when automatic column selection
2322        is done. Add the new field names to any existing field names that
2323        are deferred (or removed from any existing field names that are marked
2324        as the only ones for immediate loading).
2325        """
2326        # Fields on related models are stored in the literal double-underscore
2327        # format, so that we can use a set datastructure. We do the foo__bar
2328        # splitting and handling when computing the SQL column names (as part of
2329        # get_columns()).
2330        existing, defer = self.deferred_loading
2331        if defer:
2332            # Add to existing deferred names.
2333            self.deferred_loading = existing.union(field_names), True
2334        else:
2335            # Remove names from the set of any existing "immediate load" names.
2336            if new_existing := existing.difference(field_names):
2337                self.deferred_loading = new_existing, False
2338            else:
2339                self.clear_deferred_loading()
2340                if new_only := set(field_names).difference(existing):
2341                    self.deferred_loading = new_only, True
2342
2343    def add_immediate_loading(self, field_names: list[str] | set[str]) -> None:
2344        """
2345        Add the given list of model field names to the set of fields to
2346        retrieve when the SQL is executed ("immediate loading" fields). The
2347        field names replace any existing immediate loading field names. If
2348        there are field names already specified for deferred loading, remove
2349        those names from the new field_names before storing the new names
2350        for immediate loading. (That is, immediate loading overrides any
2351        existing immediate values, but respects existing deferrals.)
2352        """
2353        existing, defer = self.deferred_loading
2354        field_names = set(field_names)
2355
2356        if defer:
2357            # Remove any existing deferred names from the current set before
2358            # setting the new names.
2359            self.deferred_loading = field_names.difference(existing), False
2360        else:
2361            # Replace any existing "immediate load" field names.
2362            self.deferred_loading = frozenset(field_names), False
2363
2364    def set_annotation_mask(
2365        self, names: set[str] | frozenset[str] | list[str] | dict[str, Any] | None
2366    ) -> None:  # type: ignore[misc]
2367        """Set the mask of annotations that will be returned by the SELECT."""
2368        if names is None:
2369            self.annotation_select_mask = None
2370        else:
2371            self.annotation_select_mask = set(names)
2372        self._annotation_select_cache = None
2373
2374    def append_annotation_mask(self, names: list[str] | dict[str, Any]) -> None:
2375        if self.annotation_select_mask is not None:
2376            self.set_annotation_mask(self.annotation_select_mask.union(names))
2377
2378    def set_extra_mask(self, names: set[str] | tuple[str, ...] | None) -> None:
2379        """
2380        Set the mask of extra select items that will be returned by SELECT.
2381        Don't remove them from the Query since they might be used later.
2382        """
2383        if names is None:
2384            self.extra_select_mask = None
2385        else:
2386            self.extra_select_mask = set(names)
2387        self._extra_select_cache = None
2388
2389    def set_values(self, fields: list[str]) -> None:
2390        self.select_related = False
2391        self.clear_deferred_loading()
2392        self.clear_select_fields()
2393        self.has_select_fields = True
2394
2395        if fields:
2396            field_names = []
2397            extra_names = []
2398            annotation_names = []
2399            if not self.extra and not self.annotations:
2400                # Shortcut - if there are no extra or annotations, then
2401                # the values() clause must be just field names.
2402                field_names = list(fields)
2403            else:
2404                self.default_cols = False
2405                for f in fields:
2406                    if f in self.extra_select:
2407                        extra_names.append(f)
2408                    elif f in self.annotation_select:
2409                        annotation_names.append(f)
2410                    else:
2411                        field_names.append(f)
2412            self.set_extra_mask(extra_names)
2413            self.set_annotation_mask(annotation_names)
2414            selected = frozenset(field_names + extra_names + annotation_names)
2415        else:
2416            field_names = [f.attname for f in self.model._model_meta.concrete_fields]
2417            selected = frozenset(field_names)
2418        # Selected annotations must be known before setting the GROUP BY
2419        # clause.
2420        if self.group_by is True:
2421            self.add_fields(
2422                (f.attname for f in self.model._model_meta.concrete_fields), False
2423            )
2424            # Disable GROUP BY aliases to avoid orphaning references to the
2425            # SELECT clause which is about to be cleared.
2426            self.set_group_by(allow_aliases=False)
2427            self.clear_select_fields()
2428        elif self.group_by:
2429            # Resolve GROUP BY annotation references if they are not part of
2430            # the selected fields anymore.
2431            group_by = []
2432            for expr in self.group_by:
2433                if isinstance(expr, Ref) and expr.refs not in selected:
2434                    expr = self.annotations[expr.refs]
2435                group_by.append(expr)
2436            self.group_by = tuple(group_by)
2437
2438        self.values_select = tuple(field_names)
2439        self.add_fields(field_names, True)
2440
2441    @property
2442    def annotation_select(self) -> dict[str, BaseExpression]:
2443        """
2444        Return the dictionary of aggregate columns that are not masked and
2445        should be used in the SELECT clause. Cache this result for performance.
2446        """
2447        if self._annotation_select_cache is not None:
2448            return self._annotation_select_cache
2449        elif not self.annotations:
2450            return {}
2451        elif self.annotation_select_mask is not None:
2452            self._annotation_select_cache = {
2453                k: v
2454                for k, v in self.annotations.items()
2455                if k in self.annotation_select_mask
2456            }
2457            return self._annotation_select_cache
2458        else:
2459            return self.annotations
2460
2461    @property
2462    def extra_select(self) -> dict[str, tuple[str, list[Any]]]:
2463        if self._extra_select_cache is not None:
2464            return self._extra_select_cache
2465        if not self.extra:
2466            return {}
2467        elif self.extra_select_mask is not None:
2468            self._extra_select_cache = {
2469                k: v for k, v in self.extra.items() if k in self.extra_select_mask
2470            }
2471            return self._extra_select_cache
2472        else:
2473            return self.extra
2474
2475    def trim_start(
2476        self, names_with_path: list[tuple[str, list[Any]]]
2477    ) -> tuple[str, bool]:
2478        """
2479        Trim joins from the start of the join path. The candidates for trim
2480        are the PathInfos in names_with_path structure that are m2m joins.
2481
2482        Also set the select column so the start matches the join.
2483
2484        This method is meant to be used for generating the subquery joins &
2485        cols in split_exclude().
2486
2487        Return a lookup usable for doing outerq.filter(lookup=self) and a
2488        boolean indicating if the joins in the prefix contain a LEFT OUTER join.
2489        _"""
2490        all_paths = []
2491        for _, paths in names_with_path:
2492            all_paths.extend(paths)
2493        contains_louter = False
2494        # Trim and operate only on tables that were generated for
2495        # the lookup part of the query. That is, avoid trimming
2496        # joins generated for F() expressions.
2497        lookup_tables = [
2498            t for t in self.alias_map if t in self._lookup_joins or t == self.base_table
2499        ]
2500        for trimmed_paths, path in enumerate(all_paths):
2501            if path.m2m:
2502                break
2503            if self.alias_map[lookup_tables[trimmed_paths + 1]].join_type == LOUTER:
2504                contains_louter = True
2505            alias = lookup_tables[trimmed_paths]
2506            self.unref_alias(alias)
2507        # The path.join_field is a Rel, lets get the other side's field
2508        join_field = path.join_field.field
2509        # Build the filter prefix.
2510        paths_in_prefix = trimmed_paths
2511        trimmed_prefix = []
2512        for name, path in names_with_path:
2513            if paths_in_prefix - len(path) < 0:
2514                break
2515            trimmed_prefix.append(name)
2516            paths_in_prefix -= len(path)
2517        trimmed_prefix.append(join_field.foreign_related_fields[0].name)
2518        trimmed_prefix = LOOKUP_SEP.join(trimmed_prefix)
2519        # Lets still see if we can trim the first join from the inner query
2520        # (that is, self). We can't do this for:
2521        # - LEFT JOINs because we would miss those rows that have nothing on
2522        #   the outer side,
2523        # - INNER JOINs from filtered relations because we would miss their
2524        #   filters.
2525        first_join = self.alias_map[lookup_tables[trimmed_paths + 1]]
2526        if first_join.join_type != LOUTER and not first_join.filtered_relation:
2527            select_fields = [r[0] for r in join_field.related_fields]
2528            select_alias = lookup_tables[trimmed_paths + 1]
2529            self.unref_alias(lookup_tables[trimmed_paths])
2530            extra_restriction = join_field.get_extra_restriction(
2531                None, lookup_tables[trimmed_paths + 1]
2532            )
2533            if extra_restriction:
2534                self.where.add(extra_restriction, AND)
2535        else:
2536            # TODO: It might be possible to trim more joins from the start of the
2537            # inner query if it happens to have a longer join chain containing the
2538            # values in select_fields. Lets punt this one for now.
2539            select_fields = [r[1] for r in join_field.related_fields]
2540            select_alias = lookup_tables[trimmed_paths]
2541        # The found starting point is likely a join_class instead of a
2542        # base_table_class reference. But the first entry in the query's FROM
2543        # clause must not be a JOIN.
2544        for table in self.alias_map:
2545            if self.alias_refcount[table] > 0:
2546                self.alias_map[table] = self.base_table_class(
2547                    self.alias_map[table].table_name,
2548                    table,
2549                )
2550                break
2551        self.set_select([f.get_col(select_alias) for f in select_fields])
2552        return trimmed_prefix, contains_louter
2553
2554    def is_nullable(self, field: Field) -> bool:
2555        """Check if the given field should be treated as nullable."""
2556        # QuerySet does not have knowledge of which connection is going to be
2557        # used. For the single-database setup we always reference the default
2558        # connection here.
2559        return field.allow_null
2560
2561
2562def get_order_dir(field: str, default: str = "ASC") -> tuple[str, str]:
2563    """
2564    Return the field name and direction for an order specification. For
2565    example, '-foo' is returned as ('foo', 'DESC').
2566
2567    The 'default' param is used to indicate which way no prefix (or a '+'
2568    prefix) should sort. The '-' prefix always sorts the opposite way.
2569    """
2570    dirn = ORDER_DIR[default]
2571    if field[0] == "-":
2572        return field[1:], dirn[1]
2573    return field, dirn[0]
2574
2575
2576class JoinPromoter:
2577    """
2578    A class to abstract away join promotion problems for complex filter
2579    conditions.
2580    """
2581
2582    def __init__(self, connector: str, num_children: int, negated: bool):
2583        self.connector = connector
2584        self.negated = negated
2585        if self.negated:
2586            if connector == AND:
2587                self.effective_connector = OR
2588            else:
2589                self.effective_connector = AND
2590        else:
2591            self.effective_connector = self.connector
2592        self.num_children = num_children
2593        # Maps of table alias to how many times it is seen as required for
2594        # inner and/or outer joins.
2595        self.votes = Counter()
2596
2597    def __repr__(self) -> str:
2598        return (
2599            f"{self.__class__.__qualname__}(connector={self.connector!r}, "
2600            f"num_children={self.num_children!r}, negated={self.negated!r})"
2601        )
2602
2603    def add_votes(self, votes: Any) -> None:
2604        """
2605        Add single vote per item to self.votes. Parameter can be any
2606        iterable.
2607        """
2608        self.votes.update(votes)
2609
2610    def update_join_types(self, query: Query) -> set[str]:
2611        """
2612        Change join types so that the generated query is as efficient as
2613        possible, but still correct. So, change as many joins as possible
2614        to INNER, but don't make OUTER joins INNER if that could remove
2615        results from the query.
2616        """
2617        to_promote = set()
2618        to_demote = set()
2619        # The effective_connector is used so that NOT (a AND b) is treated
2620        # similarly to (a OR b) for join promotion.
2621        for table, votes in self.votes.items():
2622            # We must use outer joins in OR case when the join isn't contained
2623            # in all of the joins. Otherwise the INNER JOIN itself could remove
2624            # valid results. Consider the case where a model with rel_a and
2625            # rel_b relations is queried with rel_a__col=1 | rel_b__col=2. Now,
2626            # if rel_a join doesn't produce any results is null (for example
2627            # reverse foreign key or null value in direct foreign key), and
2628            # there is a matching row in rel_b with col=2, then an INNER join
2629            # to rel_a would remove a valid match from the query. So, we need
2630            # to promote any existing INNER to LOUTER (it is possible this
2631            # promotion in turn will be demoted later on).
2632            if self.effective_connector == OR and votes < self.num_children:
2633                to_promote.add(table)
2634            # If connector is AND and there is a filter that can match only
2635            # when there is a joinable row, then use INNER. For example, in
2636            # rel_a__col=1 & rel_b__col=2, if either of the rels produce NULL
2637            # as join output, then the col=1 or col=2 can't match (as
2638            # NULL=anything is always false).
2639            # For the OR case, if all children voted for a join to be inner,
2640            # then we can use INNER for the join. For example:
2641            #     (rel_a__col__icontains=Alex | rel_a__col__icontains=Russell)
2642            # then if rel_a doesn't produce any rows, the whole condition
2643            # can't match. Hence we can safely use INNER join.
2644            if self.effective_connector == AND or (
2645                self.effective_connector == OR and votes == self.num_children
2646            ):
2647                to_demote.add(table)
2648            # Finally, what happens in cases where we have:
2649            #    (rel_a__col=1|rel_b__col=2) & rel_a__col__gte=0
2650            # Now, we first generate the OR clause, and promote joins for it
2651            # in the first if branch above. Both rel_a and rel_b are promoted
2652            # to LOUTER joins. After that we do the AND case. The OR case
2653            # voted no inner joins but the rel_a__col__gte=0 votes inner join
2654            # for rel_a. We demote it back to INNER join (in AND case a single
2655            # vote is enough). The demotion is OK, if rel_a doesn't produce
2656            # rows, then the rel_a__col__gte=0 clause can't be true, and thus
2657            # the whole clause must be false. So, it is safe to use INNER
2658            # join.
2659            # Note that in this example we could just as well have the __gte
2660            # clause and the OR clause swapped. Or we could replace the __gte
2661            # clause with an OR clause containing rel_a__col=1|rel_a__col=2,
2662            # and again we could safely demote to INNER.
2663        query.promote_joins(to_promote)
2664        query.demote_joins(to_demote)
2665        return to_demote